使用Java进行openssl加密

6

我有一个遗留的C++模块,使用openssl库(DES加密)提供加密/解密功能。我正在尝试将该代码翻译成Java,并且不想依赖于DLL、JNI等... C++代码如下:

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代码看起来像这样:

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

我可以很容易地在Java中进行DES加密,但如何使用完全不同的方法获得与上述代码相同的结果呢?特别困扰我的是C++版本使用2个密钥,而Java版本只使用1个密钥。 关于CBC模式下的DES的答案相当令人满意,但我还无法使其正常工作。 以下是有关原始代码的更多详细信息: 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);
...

根据我所了解的,密钥应该是56位(或64位,不太确定),但这里是48字节长。


现有的代码不足以说明 key1 和 key2 在后面被用来做什么... - Alexander
3个回答

1
我不是 OpenSSL 专家,但我猜测 C++ 代码使用的是 CBC 模式下的 DES,因此需要一个 IV(这就是 initKey 的作用,也是你认为需要两个密钥的原因)。如果我猜对了,你需要修改 Java 代码以在 CBC 模式下使用 DES,然后 Java 代码也将需要一个加密密钥和一个 IV。

1
此外,请记住在您的代码中不要使用sun.misc.*类。这可能会在其他VM中出现问题,因为这些不是公共API。Apache Commons Codecs(以及其他一些库)都有Base64的实现,不会出现这个问题。
我真的不确定为什么单DES会使用多个密钥。即使您使用Triple-DES,我认为您也会使用单个密钥(带有更多字节的数据),而不是使用Java加密API中的单独密钥。

0
算法应该匹配;如果你得到不同的结果,可能与你处理键和文本的方式有关。另外要记住,Java字符长度为2个字节,而C++字符长度为1个字节,这可能与此有关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接