Pregunta

Tengo un legado módulo de C++ que ofrece el cifrado/descifrado utilizando la biblioteca openssl (cifrado DES).Estoy tratando de traducir ese código en java, y no quiero depender de una DLL, JNI, etc...El código de C++ se ve así:

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));

El 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í, puedo hacer el 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 el C++ versión utiliza 2 llaves, mientras que la versión de Java utiliza sólo 1 clave.La respuesta acerca de la DES en modo CBC es bastante satisfactorio, pero no puedo conseguir que funcione todavía.Aquí hay más detalles sobre el código original:unsigned char key1[10]= {0};unsigned char 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 56 (o de 64, no es claro para mí) bits de largo, pero aquí es de 48 bytes de largo.

¿Fue útil?

Solución

Yo no soy un OpenSSL experto, pero me imagino el código de C++ es el uso de DES en modo CBC por lo tanto la necesidad de una vía INTRAVENOSA (que es lo que la initKey probablemente lo es, y es por eso que usted piensa que necesita dos llaves).Si estoy en lo correcto, usted necesita para cambiar su código de Java para el uso de DES en modo CBC también, a continuación, el código de Java también requerirá de una clave de cifrado y de una inyección INTRAVENOSA.

Otros consejos

También, tenga en cuenta que usted realmente no debería usar el sol.misc.* clases en el código.Esto podría romper en otras VMs como estas no son las Api públicas.Apache Commons Codecs (entre otras) de las implementaciones de Base64 que no son portadores de este problema.

No estoy realmente seguro de por qué solo DES nunca usaría varias claves.Incluso si se utiliza el Triple-DES, yo creo que haría uso de una clave única (con más bytes de datos) en lugar de utilizar claves separadas con el Java API de Criptografía.

Los algoritmos deben coincidir;si usted está obteniendo diferentes resultados que puede tener que ver con la manera en que usted maneja las claves y el texto.También hay que tener en cuenta que Java caracteres de 2 bytes de largo, que C++ caracteres de 1 byte, por lo que puede tener algo que ver con ella.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top