Pergunta

Eu tenho um legado C ++ módulo que oferece criptografia / descriptografia usando a biblioteca openssl (criptografia DES). Eu estou tentando traduzir esse código em java, e eu não quero depender de uma DLL, JNI, etc ... C ++ olhares código como:

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 olhares código como:

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

Para que eu possa fazer a criptografia DES em Java muito facilmente, mas como eu posso conseguir o mesmo resultado que com o código acima com métodos que são completamente diferentes? O que me incomoda em particular, é o fato de que a versão C ++ utiliza 2 chaves enquanto o utiliza a versão Java apenas 1 chave. A resposta sobre DES no modo CBC é bastante satisfatório, mas não posso fazê-lo funcionar ainda. Aqui estão mais detalhes sobre o código original: Key1 de char não assinado [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);
...

Pelo que tenho lido, a chave deve ser de 56 (ou 64, não é claro para mim) bits de comprimento, mas aqui é 48 bytes de comprimento.

Foi útil?

Solução

Eu não sou um especialista OpenSSL, mas eu acho que o código C ++ está usando DES no modo CBC necessitando assim de um IV (que é o que o initKey provavelmente é, e é por isso que você acha que precisa de duas chaves). Se estou certo, você precisa mudar o seu código Java para usar o DES no modo CBC também, então o código Java também exigirá uma chave de criptografia e uma IV.

Outras dicas

Além disso, mantenha em mente que você realmente não deve usar sun.misc. * Classes no seu código. Isso pode quebrar em outras VMs como estes não são APIs públicas. Apache Commons Codecs (entre outros) têm implementações de Base64 que não dão este problema.

Eu não sou realmente certo porque DES único jamais usaria várias chaves. Mesmo se você estivesse usando Triple-DES, eu acredito que você usaria uma chave única (com mais bytes de dados) em vez de usar chaves separadas com a API Java Cryptography.

Os algoritmos deve corresponder; se você está recebendo resultados diferentes que pode ter a ver com a maneira que você está segurando as chaves e o texto. Também tenha em mente que os personagens Java são 2 bytes de comprimento, que caracteres de C ++ são 1 byte, de modo que pode ter algo a ver com isso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top