无法解密在 Java 中加密的邮件
Can't decrypt message encrypted in Java
我想共享来自服务器 (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);
我的服务器向我的客户端发送 public 密钥:
像这样的客户端加密数据 (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
或 [=13=]
。事实并非如此 - 密文中可以有 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。
我想共享来自服务器 (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);
我的服务器向我的客户端发送 public 密钥:
像这样的客户端加密数据 (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
或 [=13=]
。事实并非如此 - 密文中可以有 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。