RSA 加密然后解密失败并出现“oaep 解码错误”
Posted
技术标签:
【中文标题】RSA 加密然后解密失败并出现“oaep 解码错误”【英文标题】:RSA encrypt then decrypt fails with "oaep decoding error" 【发布时间】:2020-09-22 15:06:21 【问题描述】:我正在尝试调试一个简单的 openssl 程序,但无法完全理解 openssl 的“oaep 解码错误”是什么意思。我已经将我的程序简化为这个,测试,一个:
#include <iostream>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <assert.h>
#include <memory>
#include <list>
#include <algorithm>
#include <string.h>
static const std::string private_key =
R"(-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAriDoH3gBbJo+SojeL5j+4yQumXgnjhrt5+FChBxOfvTcyczz
p5qlUNqLzQQcQ/a+XR5qUhaA4l97DgNseFNyoYHIxrB5t+BQw27Q+UuUYYaIwJqZ
6r2PVCnQF9WPqqWdzBN6+13IlreH2XX4qy47kuLI3lcPlP5qhYaDogpZCl7lN7Oe
Qj2FAPZ1nkV+PL4RYfWZbBymUz0C105ytT7PWgLAZVvag8kHiNXRYv4Ksc9SJ3AE
ZriZ1tzpJ6/ZkI3vfJZqCeclELQ8zGxb8CbfSd4mHoHCVY7t1h+BNM4zUxSjN8d7
bctYJwnfBtztRFN2uTotDJs6njsoxfmh4/SzAQIDAQABAoIBAAGTWKZYPqMN7jxc
aq5BkyTZAfbviGQXyElN1308iFVLv+evjBDbLF3D7HnpbJwM0oIjMVEW1Qm3VXS2
AThBgQsHEpsBo8hPJkvuZ8OptGkBf6FGhNgD6RUY38Inc4pWv0vGbVly6sq6VGda
Uuqxm2Zj2O9yGDj/6FTW97/ymgWm/FfKczg/zGtjdog67W8LvvtmAj5ynSuimOP8
mOINPjewIbcl7rKvxcMNrOXKsRWwVxTNXdMNMsXd1Figw022KTqdiazQ/DPIXU6M
f8H+U/gS5QZRIAF8i0r3cvq6ai26dX0OFtsoizqG4qlRNwtQ+wyRsilZKiKnFuMY
bt1pRBUCgYEA1TlAT/Ui4TBdgGmm0Rlj7JKJENnpDKIFE8bP6Vy8SwBmp5MiRofE
TMne4BBKLcFcslCJrFvjl7+v4B9a2de7hJYqtevrXjM91vwFhc6z0m27vv6MKStQ
3uKX8+0RGHQ3j53kAvLxFSuAqYQ+gf9IAuyG0gpMABRvj0/8HY3T7tMCgYEA0Q/O
0og9UbXh8y3yI94ztczWdIQERyEhQiGNRUnHCqO2QbZQ9Nm190Jx/8yew03xpPVb
fyWWfKqO8Kjg5np0w37porI0UmfLZ5QMC+GFMq0jOUXidsvkyoWOe4D8LII0L98k
sjihHBlGNrfFjEgOUQaoreB+8F07m/iofRCROlsCgYAPUUGRfOa4jqTo6K4XL1/C
SvSVxVG8mpcKyKl+9i6ApNK7DxLTRkWPzqC4L/NkphpOq4J4Y1GCQT79NsNsCtdp
uu/uibgq2DuFCi3LYwIAB+oI2nhvLLFukZCg8VLdEtw68PjETXeMMcfYZaun4xLl
QuCcjijPiKhK/0/5P4sOCQKBgHsi7XXRqxRapdg/ArUfpqN5IAOG0qI2oEk8S+I4
v1TD8pCn2u0s4mHdsBmzovt0CFVZ8udj80xAhWq4facjD20qbmBWyDyVSBgc+i9x
SKv9kJamU+oW1A55NeAGrAFnO2fK7elPM43CUTnfairjMhOFcYrghMP8liSbBFqN
jIyrAoGAVGZQVZgicmSppbBuZYJPOuegPVYhncq3XtBZCtEGGlMtQpKgz+GRhyvT
Ar/HC7xnS5Gjfyjj6eGHsBAjTsE4t38qD4nxQXzBmAQQ1/7/iq3WNu63OV2q4GRh
wChOO0pcJPOZfWtvKiy7hbN09e0nt5blX1yqe6LdO7mACWli/Ss=
-----END RSA PRIVATE KEY-----)";
static const std::string public_key =
R"(-----BEGIN RSA PUBLIC KEY-----
MIIBCAKCAQEAx5WRSyfFVe/JbPYnswghuMj5Nzo9YG82Z7ehyI/dbjkcdCIzTlKd
QcMvSUZafAnM9p3xnBrgbKaNltaVNrZNyN6A2ou0PQgms7ykJ67G9Hbbs/uo0rPS
GS4pYw0QiOvoYXjGqbOzQjXbAV7ez05XRb43nRdZUFO0LLvEp2VfaTL7WWzaan6r
Ve6p8t8JIwpWSn7njBYH2XPNJj1NccpvD+kT1kGn6kWZfmFBzR7Bw2+rW+rpt02F
4arxXfvzDYhZdxLKb7m2KqwZTiug2HoD5AY9l3GzRIdNvXIDP87XTl4960lpg8cI
8XuTSLFjSx0fvlXXFwTcgMLv7Q0+ISSXQwIBJQ==
-----END RSA PUBLIC KEY-----)";
static inline
void check_errors()
const int error = ERR_get_error();
if ( error != 0 )
std::cerr << ERR_reason_error_string( error ) << '\n';
assert(0);
int main()
ERR_load_crypto_strings();
// load rsa keys into a memory buffer
BIO * bio_private = BIO_new_mem_buf( (char*) private_key.data(), private_key.size() ); check_errors();
BIO * bio_public = BIO_new_mem_buf( (char*) public_key.data(), public_key.size() ); check_errors();
// use the memory buffer to create a RSA struct
RSA * rsa_private = RSA_new(); check_errors();
RSA * rsa_public = RSA_new(); check_errors();
PEM_read_bio_RSAPrivateKey( bio_private, &rsa_private, nullptr, 0 ); check_errors();
PEM_read_bio_RSAPublicKey( bio_public, &rsa_public, nullptr, 0 ); check_errors();
// encrypt this text ...
std::string text_to_encrypt = "hello";
// ... in this buffer
std::vector< unsigned char > buffer;
buffer.resize( RSA_size( rsa_private ) );
const int flen = RSA_public_encrypt(
text_to_encrypt.size(), // shorter than the key in my test
(const unsigned char*)text_to_encrypt.data(),
&buffer[0],
rsa_public,
RSA_PKCS1_OAEP_PADDING
); check_errors();
// now decrypt the buffer back to the original text
std::vector< unsigned char > buffer_decrypt;
buffer_decrypt.resize( RSA_size( rsa_private ), '\0' );
RSA_private_decrypt(
flen,
&buffer[0],
&buffer_decrypt[0],
rsa_private,
RSA_PKCS1_OAEP_PADDING
); check_errors();
// and print it
std::cout << (char*) &buffer_decrypt[0] << '\n';
位于RSA_private_decrypt
之后的check_errors()
触发了上述错误,我不知道为什么。
编辑:使用 RSA_public_encrypt 返回的值稍微改进了代码。在实践中它不会影响结果。
【问题讨论】:
嗯。在一次执行期间,我遇到了另一个错误:数据对于模数来说太大 也许能帮上忙:***.com/questions/9284074/rsa-private-decrypt-failed 您可能应该包括<string>
,而不是<string.h>
。您还需要包含<vector>
。最后,您应该包括<cassert>
,而不是<assert.h>
。
@qdii - 什么是R"(...)"
?这真的有效吗?它甚至可以编译吗?
@jww 这些是原始字符串文字,添加了 C++11 :) 是的,只要您提供 c++11 编译器,这段代码就可以正常编译。我使用这条 gcc 行编译:g++ -o test test.cpp -std=c++11 -lssl -lcrypto
【参考方案1】:
位于 RSA_private_decrypt 之后的 check_errors() 触发了上述错误,我不知道为什么。
您的公钥与私钥不匹配。
当我在读取密钥后添加以下内容时:
FILE* ff = fopen("temp.pem", "w");
PEM_write_RSAPublicKey(ff, rsa_private);
然后cat
公钥:
$ cat temp.pem
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAriDoH3gBbJo+SojeL5j+4yQumXgnjhrt5+FChBxOfvTcyczzp5ql
UNqLzQQcQ/a+XR5qUhaA4l97DgNseFNyoYHIxrB5t+BQw27Q+UuUYYaIwJqZ6r2P
VCnQF9WPqqWdzBN6+13IlreH2XX4qy47kuLI3lcPlP5qhYaDogpZCl7lN7OeQj2F
APZ1nkV+PL4RYfWZbBymUz0C105ytT7PWgLAZVvag8kHiNXRYv4Ksc9SJ3AEZriZ
1tzpJ6/ZkI3vfJZqCeclELQ8zGxb8CbfSd4mHoHCVY7t1h+BNM4zUxSjN8d7bctY
JwnfBtztRFN2uTotDJs6njsoxfmh4/SzAQIDAQAB
-----END RSA PUBLIC KEY-----
宾果!它与硬编码的公钥不匹配。
如果您想超越它进行测试,只需使用rsa_private
进行加密。 RSA_public_encrypt
期间仅使用密钥的公共部分:
int flen = RSA_public_encrypt(
text_to_encrypt.size() + 1,
text_to_encrypt.data(),
&buffer[0],
rsa_private,
RSA_PKCS1_OAEP_PADDING
);
或者,既然您知道它应该是什么,只需更新公钥即可。
【讨论】:
【参考方案2】:我编译了@jww 提出的固定解决方案以及一些其他改进/修复(内存泄漏),以防有人遇到同样的问题。
#include <iostream>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <assert.h>
#include <memory>
#include <list>
#include <algorithm>
#include <vector>
#include <string.h>
static const std::string private_key =
R"(-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAriDoH3gBbJo+SojeL5j+4yQumXgnjhrt5+FChBxOfvTcyczz
p5qlUNqLzQQcQ/a+XR5qUhaA4l97DgNseFNyoYHIxrB5t+BQw27Q+UuUYYaIwJqZ
6r2PVCnQF9WPqqWdzBN6+13IlreH2XX4qy47kuLI3lcPlP5qhYaDogpZCl7lN7Oe
Qj2FAPZ1nkV+PL4RYfWZbBymUz0C105ytT7PWgLAZVvag8kHiNXRYv4Ksc9SJ3AE
ZriZ1tzpJ6/ZkI3vfJZqCeclELQ8zGxb8CbfSd4mHoHCVY7t1h+BNM4zUxSjN8d7
bctYJwnfBtztRFN2uTotDJs6njsoxfmh4/SzAQIDAQABAoIBAAGTWKZYPqMN7jxc
aq5BkyTZAfbviGQXyElN1308iFVLv+evjBDbLF3D7HnpbJwM0oIjMVEW1Qm3VXS2
AThBgQsHEpsBo8hPJkvuZ8OptGkBf6FGhNgD6RUY38Inc4pWv0vGbVly6sq6VGda
Uuqxm2Zj2O9yGDj/6FTW97/ymgWm/FfKczg/zGtjdog67W8LvvtmAj5ynSuimOP8
mOINPjewIbcl7rKvxcMNrOXKsRWwVxTNXdMNMsXd1Figw022KTqdiazQ/DPIXU6M
f8H+U/gS5QZRIAF8i0r3cvq6ai26dX0OFtsoizqG4qlRNwtQ+wyRsilZKiKnFuMY
bt1pRBUCgYEA1TlAT/Ui4TBdgGmm0Rlj7JKJENnpDKIFE8bP6Vy8SwBmp5MiRofE
TMne4BBKLcFcslCJrFvjl7+v4B9a2de7hJYqtevrXjM91vwFhc6z0m27vv6MKStQ
3uKX8+0RGHQ3j53kAvLxFSuAqYQ+gf9IAuyG0gpMABRvj0/8HY3T7tMCgYEA0Q/O
0og9UbXh8y3yI94ztczWdIQERyEhQiGNRUnHCqO2QbZQ9Nm190Jx/8yew03xpPVb
fyWWfKqO8Kjg5np0w37porI0UmfLZ5QMC+GFMq0jOUXidsvkyoWOe4D8LII0L98k
sjihHBlGNrfFjEgOUQaoreB+8F07m/iofRCROlsCgYAPUUGRfOa4jqTo6K4XL1/C
SvSVxVG8mpcKyKl+9i6ApNK7DxLTRkWPzqC4L/NkPhPOq4J4Y1GCQT79NsNsCtdp
uu/uibgq2DuFCi3LYwIAB+oI2nhvLLFukZCg8VLdEtw68PjETXeMMcfYZaun4xLl
QuCcjijPiKhK/0/5P4sOCQKBgHsi7XXRqxRapdg/ArUfpqN5IAOG0qI2oEk8S+I4
v1TD8pCn2u0s4mHdsBmzovt0CFVZ8udj80xAhWq4facjD20qbmBWyDyVSBgc+i9x
SKv9kJamU+oW1A55NeAGrAFnO2fK7elPM43CUTnfairjMhOFcYrghMP8liSbBFqN
jIyrAoGAVGZQVZgicmSppbBuZYJPOuegPVYhncq3XtBZCtEGGlMtQpKgz+GRhyvT
Ar/HC7xnS5Gjfyjj6eGHsBAjTsE4t38qD4nxQXzBmAQQ1/7/iq3WNu63OV2q4GRh
wChOO0pcJPOZfWtvKiy7hbN09e0nt5blX1yqe6LdO7mACWli/Ss=
-----END RSA PRIVATE KEY-----)"; // do not indent!!
static const std::string public_key =
R"(-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAriDoH3gBbJo+SojeL5j+4yQumXgnjhrt5+FChBxOfvTcyczzp5ql
UNqLzQQcQ/a+XR5qUhaA4l97DgNseFNyoYHIxrB5t+BQw27Q+UuUYYaIwJqZ6r2P
VCnQF9WPqqWdzBN6+13IlreH2XX4qy47kuLI3lcPlP5qhYaDogpZCl7lN7OeQj2F
APZ1nkV+PL4RYfWZbBymUz0C105ytT7PWgLAZVvag8kHiNXRYv4Ksc9SJ3AEZriZ
1tzpJ6/ZkI3vfJZqCeclELQ8zGxb8CbfSd4mHoHCVY7t1h+BNM4zUxSjN8d7bctY
JwnfBtztRFN2uTotDJs6njsoxfmh4/SzAQIDAQAB
-----END RSA PUBLIC KEY-----)"; // do not indent!!
int main()
// load rsa keys into a memory buffer
BIO * bio_private = BIO_new_mem_buf( (char*) private_key.data(), private_key.size() );
BIO * bio_public = BIO_new_mem_buf( (char*) public_key.data(), public_key.size() );
// use the memory buffer to create a RSA struct
RSA * rsa_private = PEM_read_bio_RSAPrivateKey( bio_private, 0 , 0, 0 );
RSA * rsa_public = PEM_read_bio_RSAPublicKey( bio_public, 0, 0, 0 );
if(!rsa_private)
printf("ERROR: Could not load PRIVATE KEY! PEM_read_bio_RSAPrivateKey FAILED: %s\n", ERR_error_string(ERR_get_error(), NULL));
if(!rsa_public)
printf("ERROR: Could not load PUBLIC KEY! PEM_read_bio_RSA_PUBKEY FAILED: %s\n", ERR_error_string( ERR_get_error(), NULL)) ;
// encrypt this text ...
std::string text_to_encrypt = "hello";
// ... in this buffer
std::vector< unsigned char > buffer;
buffer.resize( RSA_size( rsa_public ) );
const int flen = RSA_public_encrypt(
text_to_encrypt.size(), // shorter than the key in my test
(const unsigned char*)text_to_encrypt.data(),
&buffer[0],
rsa_public,
RSA_PKCS1_OAEP_PADDING
);
if(flen == -1)
printf("ERROR: RSA_public_encrypt: %s\n", ERR_error_string(ERR_get_error(), NULL));
BIO_free(bio_public);
RSA_free(rsa_public);
// now decrypt the buffer back to the original text
std::vector< unsigned char > buffer_decrypt;
buffer_decrypt.resize( RSA_size( rsa_private ), '\0' );
const int flen2 = RSA_private_decrypt(
buffer_decrypt.size(),
&buffer[0],
&buffer_decrypt[0],
rsa_private,
RSA_PKCS1_OAEP_PADDING
);
if(flen2 == -1)
printf("ERROR: RSA_private_decrypt: %s\n", ERR_error_string(ERR_get_error(), NULL)) ;
BIO_free(bio_private);
RSA_free(rsa_private);
// and print it
std::cout << (char*) &buffer_decrypt[0] << '\n';
【讨论】:
以上是关于RSA 加密然后解密失败并出现“oaep 解码错误”的主要内容,如果未能解决你的问题,请参考以下文章