无法解密在 Java 中加密的消息

Can't decrypt message encrypted in Java

本文关键字:加密 消息 Java 解密      更新时间:2023-10-16

我想共享来自服务器(c++)和客户端(Java)的数据。为了安全起见,我们使用RSA密钥(1024位,65537指数)

我生成的密钥对是这样的(C++/OpenSSL):

RSA *keyPair = RSA_generate_key(RSA_BITS, RSA_EXPONENT, NULL, NULL);
BIO* privateKey = BIO_new(BIO_s_mem());
BIO* publicKey = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(privateKey, keyPair, NULL, NULL, 0, NULL, NULL);
PEM_write_bio_RSA_PUBKEY(publicKey, keyPair);

我的服务器向我的客户端发送公钥:

客户端加密数据如下(Java):

Cipher m_cipher = Cipher.getInstance("RSA");
m_cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] result = m_cipher.doFinal(dataNeedToCrypt);

现在我收到我的消息,我试着像这样解密(C++/OpenSSL):

BIO* privateKey = StringtoBio(m_privateKey);
RSA* rsa = PEM_read_bio_RSAPrivateKey(privateKey, NULL, NULL, NULL);
char dataDecryptedBuffer[RSA_size(rsa)];
int result = RSA_private_decrypt(RSA_size(rsa), (uchar*)data.data(), (uchar*)&dataDecryptedBuffer, rsa, RSA_PKCS1_PADDING);
if(result == -1)
    CONSOLE_ERROR << "Can't decrypt error code : " << std::hex << ERR_get_error();
QByteArray dataDecrypted(dataDecryptedBuffer);
BIO_free_all(privateKey);
RSA_free(rsa);
return dataDecrypted;

我得到一个错误0x407109F,它似乎填充是错误的:

$ openssl errstr 0x407109F
error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error

在java密码中,"RSA"是"RSA/ECB/PKCS1Padding",所以填充应该很好。

但我无法解密我的消息!

怎么了?

基于解密方式:

int result = RSA_public_decrypt(RSA_size(rsa), (uchar*)data.data(), (uchar*)&dataDecryptedBuffer, rsa, RSA_PKCS1_PADDING);    
if(result == -1)
    CONSOLE_ERROR << "Can't decrypt error code : " << std::hex << ERR_get_error();
QByteArray dataDecrypted(dataDecryptedBuffer);

我猜你是在假设密文中没有NULL。事实并非如此——密文中可能存在NULL。

Java应该发送所有的密文,因为byte[]具有明确的大小。但当你通过电线收到它时,你可能读错了,或者收到后处理错了。

我看到你正在使用data.data(),我相信这意味着你有一个std::string。请确保使用显式长度构造字符串,而不是假设有NULL终止符。或者更好的做法是,执行这些断言,以便代码自行调试(您可以在时间上做更好的事情):

ASSERT(data.size() == RSA_size(rsa));
if(data.size() != RSA_size(rsa))
    CONSOLE_ERROR << "Invalid cipher text length" << endl;
int result = RSA_private_decrypt(RSA_size(rsa), (uchar*)data.data(), (uchar*)&dataDecryptedBuffer, rsa, RSA_PKCS1_PADDING);
ASSERT(result != -1);
if(result == -1)
    CONSOLE_ERROR << "Can't decrypt error code : " << std::hex << ERR_get_error();
QByteArray dataDecrypted(dataDecryptedBuffer, result);

相关的,OpenSSL项目建议使用高级EVP_*接口,而不是低级功能。为此,请参阅OpenSSL wiki上的EVP。