Domanda

Ho un modulo C++ legacy che offre crittografia/decrittografia utilizzando la libreria openssl (crittografia DES).Sto cercando di tradurre quel codice in Java e non voglio fare affidamento su una DLL, JNI, ecc...Il codice C++ è simile a:

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

Il codice Java è simile 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 {
    // ...
}

Quindi posso eseguire la crittografia DES in Java abbastanza facilmente, ma come posso ottenere lo stesso risultato del codice precedente con metodi completamente diversi?Ciò che mi dà fastidio in particolare è il fatto che la versione C++ utilizza 2 chiavi mentre la versione Java ne utilizza solo 1.La risposta sul DES in modalità CBC è abbastanza soddisfacente ma non riesco ancora a farlo funzionare.Ecco maggiori dettagli sul codice originale:chiave carattere senza segno1[10]= {0};chiave carattere senza segno2[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);
...

Da quello che ho letto, la chiave dovrebbe essere lunga 56 (o 64, non mi è chiaro) bit, ma qui è lunga 48 byte.

È stato utile?

Soluzione

Non sono un esperto di OpenSSL, ma immagino che il codice C++ utilizzi DES in modalità CBC, quindi necessiti di un IV (questo è probabilmente initKey, ed è per questo che pensi di aver bisogno di due chiavi).Se ho ragione, devi modificare il tuo codice Java per utilizzare DES anche in modalità CBC, quindi anche il codice Java richiederà una chiave di crittografia e un IV.

Altri suggerimenti

Inoltre, tieni presente che non dovresti usare le classi sun.misc.* nel tuo codice.Ciò potrebbe interrompere altre VM poiché non si tratta di API pubbliche.I codec Apache Commons (tra gli altri) hanno implementazioni di Base64 che non sopportano questo problema.

Non sono proprio sicuro del motivo per cui un singolo DES utilizzerebbe mai più chiavi.Anche se utilizzassi Triple-DES, credo che utilizzeresti una singola chiave (con più byte di dati) anziché utilizzare chiavi separate con l'API di crittografia Java.

Gli algoritmi dovrebbero corrispondere;se ottieni risultati diversi potrebbe avere a che fare con il modo in cui gestisci i tasti e il testo.Tieni inoltre presente che i caratteri Java sono lunghi 2 byte, mentre i caratteri C++ sono 1 byte, quindi potrebbe avere qualcosa a che fare con questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top