【问题标题】:rsa_public_encrypt returns -1, error 0x0406B07Arsa_public_encrypt 返回 -1,错误 0x0406B07A
【发布时间】:2018-03-02 12:36:26
【问题描述】:

我正在尝试使用 RSA_public_encrypt 加密数据,但它似乎不起作用(retEnc 始终为 -1)。我还尝试使用ERR_get_errorERR_error_string 查找有关错误的更多信息。

这是代码:

RSA *rsaPkey = NULL;

FILE *pemFile;
fopen_s(&pemFile, filename.c_str(), "r");
rsaPkey         = PEM_read_RSA_PUBKEY(pemFile, &rsaPkey, NULL, NULL);
fclose(pemFile);

if(rsaPkey == NULL)
    throw "Error pubkey file";

int size = RSA_size(rsaPkey);
unsigned char *encrypted;
encrypted = new unsigned char[size];

string instr  = "test";
int length = instr.length();
unsigned char *in = (unsigned char *)(instr.c_str());

unsigned long errorTrack = ERR_get_error() ;

int retEnc = RSA_public_encrypt(length, in, (unsigned char *)encrypted, rsaPkey, RSA_NO_PADDING);
errorTrack = ERR_get_error() ;
char *errorChar = new char[120];
errorChar = ERR_error_string(errorTrack, errorChar);

ERR_error_string 给我error:0406B07A:lib(4):func(107):reason(122)

我怎样才能找到有关此的更多详细信息,我在哪里可以找到库 4 和函数 107?

当我尝试使用 openssl cli 和相同的公钥文件进行加密时,加密工作正常。

【问题讨论】:

标签: c++ openssl error-code


【解决方案1】:
ERR_error_string gives me error:0406B07A:lib(4):func(107):reason(122)

我怎样才能找到有关此的更多详细信息,我在哪里可以找到库 4 和函数 107?

我发现从 OpenSSL 错误代码中了解更多信息的最简单方法是:

$ openssl errstr 0406B07A
error:0406B07A:rsa routines:RSA_padding_add_none:data too small for key size

char *errorChar = new char[120];
errorChar = ERR_error_string(errorTrack, errorChar);

另外,来自ERR_error_string man page

ERR_error_string() 生成一个人类可读的字符串,表示 错误代码 e,并将其放在 buf。 buf 必须至少为 256 字节 长。如果 buf 为 NULL,则错误字符串放置在静态缓冲区中。 请注意,此函数不是线程安全的,并且不检查 缓冲区的大小;请改用 ERR_error_string_n()。

由于您使用的是 C++,这样的事情可能会更容易:

std::string errorMsg;
errorMsg.resize(256);

(void)ERR_error_string(errorTrack, &errorMsg[0]);

在上面,您正在使用std::string 来管理资源。要获取非常量指针,您需要获取第一个元素的地址。

如果你愿意,你可以适当地调整errorMsg 的大小:

(void)ERR_error_string(errorTrack, &errorMsg[0]);
errorMsg.resize(std::strlen(errorMsg.c_str()));

这是另一个可能使 C++ 更易于使用的技巧。

typedef unsigned char byte;
...

std::string encrypted;
int size = RSA_size(rsaPkey);

if (size < 0)
    throw std::runtime_error("RSA_size failed");

// Resize to the maximum size
encrypted.resize(size);
...

int retEnc = RSA_public_encrypt(length, in, (byte*)&encrypted[0], rsaPkey, RSA_NO_PADDING);

if (retEnc < 0)
    throw std::runtime_error("RSA_public_encrypt failed");

// Resize the final string now that the size is known
encrypted.resize(retEnc );

在上面,您正在使用std::string 来管理资源。要获取非常量指针,您需要获取第一个元素的地址。

另外,NO_PADDING 通常是个坏主意。您通常需要 OAEP 填充。请参阅 RSA_public_encrypt man page 中的注释,了解填充如何影响最大尺寸。


C++ 可以更轻松地使用 OpenSSL。您可以使用unique_ptr 避免显式调用EVP_CIPHER_CTX_free 等函数。请参阅 OpenSSL wiki 上的 EVP Symmetric Encryption and Decryption | C++ Programsunique_ptr and OpenSSL's STACK_OF(X509)*How to get PKCS7_sign result into a char * or std::string 等。

在您的情况下,管理资源看起来像 these would be helpful

using FILE_ptr = std::unique_ptr<FILE, decltype(&::fclose)>;
using RSA_ptr = std::unique_ptr<RSA, decltype(&::RSA_free)>;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    • 2013-02-14
    相关资源
    最近更新 更多