2008-09-18 19 views
5

Tengo un módulo de C++ heredado que ofrece cifrado/descifrado usando la biblioteca de openssl (cifrado DES). Estoy tratando de traducir el código en Java, y no quiere depender de una DLL, JNI, etc ... código C++ parece:Uso del cifrado de openssl con Java

des_string_to_key(reinterpret_cast<const char *>(key1), &initkey); 
des_string_to_key(reinterpret_cast<const char *>(key2), &key); 
key_sched(&key, ks); 
// ... 
des_ncbc_encrypt(reinterpret_cast<const unsigned char *>(tmp.c_str()), 
reinterpret_cast< unsigned char *>(encrypted_buffer), tmp.length(), ks, &initkey, 
DES_ENCRYPT); 

return base64(reinterpret_cast<const unsigned char *>(encrypted_buffer), strlen(encrypted_buffer)); 

código Java se parece a:

Cipher ecipher; 
try { 
    ecipher = Cipher.getInstance("DES"); 
    SecretKeySpec keySpec = new SecretKeySpec(key, "DES");  
    ecipher.init(Cipher.ENCRYPT_MODE, keySpec);   
    byte[] utf8 = password.getBytes("UTF8"); 
    byte[] enc = ecipher.doFinal(utf8); 
    return new sun.misc.BASE64Encoder().encode(enc); 
} 
catch { 
    // ... 
} 

Así que puedo hacer cifrado DES en Java con bastante facilidad, pero ¿cómo puedo obtener el mismo resultado que con el código anterior con métodos que son completamente diferentes? Lo que me molesta en particular es el hecho de que la versión C++ usa 2 claves mientras que la versión Java usa solo 1 clave. La respuesta sobre DES en modo CBC es bastante satisfactoria, pero aún no puedo hacerlo funcionar. Aquí hay más detalles sobre el código original: unsigned char key1 [10] = {0}; char sin signo key2 [50] = {0};

int i; 
for (i=0;i<8;i++) 
    key1[i] = 31+int((i*sqrt((double)i*5)))%100; 
key1[9]=0; 

for (i=0;i<48;i++) 
    key2[i] = 31+int((i*i*sqrt((double)i*2)))%100; 
key2[49]=0; 
... 
// Initialize encrypted buffer 
memset(encrypted_buffer, 0, sizeof(encrypted_buffer)); 

// Add begin Text and End Text to the encrypted message 
std::string input; 
const char beginText = 2; 
const char endText = 3; 
input.append(1,beginText); 
input.append(bufferToEncrypt); 
input.append(1,endText);  

// Add padding 
tmp.assign(desPad(input)); 

des_ncbc_encrypt(reinterpret_cast<const unsigned char *>(tmp.c_str()),  
reinterpret_cast< unsigned char *>(encrypted_buffer), tmp.length(), ks, &initkey, 
DES_ENCRYPT); 
... 

Por lo que he leído, la clave debe ser de 56 (o 64, no es claro para mí) bits de largo, pero en este caso es de 48 bytes de longitud.

+0

No hay suficiente código para decir qué key1 y key2 se usan para más adelante ... – Alexander

Respuesta

1

No soy un experto en OpenSSL, pero supongo que el código C++ utiliza DES en modo CBC, por lo que necesita una IV (probablemente, la clave init es, y por eso cree que necesita dos claves). Si estoy en lo cierto, debe cambiar su código Java para usar DES también en modo CBC, entonces el código Java también requerirá una clave de cifrado y un IV.

0

Los algoritmos deben coincidir; Si obtiene resultados diferentes, puede tener que ver con la forma en que maneja las teclas y el texto. También tenga en cuenta que los caracteres Java tienen una longitud de 2 bytes, y que los caracteres C++ son de 1 byte, por lo que puede tener algo que ver con eso.

1

Además, tenga en cuenta que realmente no debe utilizar las clases sun.misc. * En su código. Esto podría romperse en otras máquinas virtuales ya que estas no son API públicas. Los códecs de Apache Commons (entre otros) tienen implementaciones de Base64 que no tienen este problema.

No estoy muy seguro de por qué el único DES usaría varias claves. Incluso si estuviera usando Triple-DES, creo que usaría una sola clave (con más bytes de datos) en lugar de usar claves separadas con la API de criptografía de Java.