2008-09-18 13 views
5

Ich habe ein Vermächtnis C++ Modul, das die Verschlüsselung/Entschlüsselung mit der OpenSSL-Bibliothek (DES-Verschlüsselung) bietet. Ich versuche, diesen Code in Java zu übersetzen, und ich will nicht auf einer DLL verlassen, JNI, etc ... C++ Code wie folgt aussieht:mit OpenSSL-Verschlüsselung mit 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)); 

Java-Code wie folgt aussieht:

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 { 
    // ... 
} 

so kann ich die dES-Verschlüsselung in Java ziemlich leicht, aber wie kann ich das gleiche Ergebnis wie mit dem obigen Code mit Methoden erhalten, die völlig unterschiedlich sind? Was mich besonders beschäftigt, ist die Tatsache, dass die C++ - Version 2 Schlüssel verwendet, während die Java-Version nur 1 Schlüssel verwendet. Die Antwort über DIE im CBC-Modus ist sehr befriedigend, aber ich kann es noch nicht an der Arbeit. Hier sind weitere Informationen über die Original-Code: 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); 
... 

Von dem, was ich gelesen habe, sollte der Schlüssel 56 (oder 64, dann ist es mir nicht klar) Bits lang, aber hier ist es 48 Byte lang.

+0

Es gibt nicht genug Code, um zu sagen, was key1 und key2 für später verwendet werden ... – Alexander

Antwort

1

Ich bin kein OpenSSL-Experte, aber ich vermute, dass der C++ - Code DES im CBC-Modus verwendet und somit eine IV benötigt (das ist wahrscheinlich der initKey, und deshalb denkt man, dass man zwei Schlüssel benötigt). Wenn ich recht habe, müssen Sie Ihren Java-Code ändern, um DES auch im CBC-Modus zu verwenden, dann wird auch der Java-Code einen Verschlüsselungsschlüssel und eine IV erfordern.

0

Die Algorithmen sollten übereinstimmen; Wenn Sie unterschiedliche Ergebnisse erhalten, kann das mit der Art und Weise zusammenhängen, wie Sie mit den Schlüsseln und dem Text umgehen. Denken Sie auch daran, dass Java Zeichen 2 Bytes lang ist, die C++ Zeichen sind 1 Byte, so dass etwas damit zu tun haben kann.

1

Denken Sie auch daran, dass Sie sun.misc. * Klassen in Ihrem Code wirklich nicht verwenden sollten. Dies könnte andere VMs einreißen, da es sich nicht um öffentliche APIs handelt. Apache Commons Codecs (unter anderem) haben Implementierungen von Base64, die dieses Problem nicht tragen.

Ich bin nicht wirklich sicher, warum einzelne DES jemals mehrere Schlüssel verwenden würde. Selbst wenn Sie Triple-DES verwenden würden, würden Sie vermutlich einen einzelnen Schlüssel (mit mehr Datenbytes) verwenden als separate Schlüssel mit der Java Cryptography API.