RSA_private_decrypt 第二次调用时崩溃
RSA_private_decrypt crashes when called for the second time
请看下面的方法:
int BCVirtualCard::decrypt(std::string from, std::string *to, int keyId, bool padding)
{
if (to == nullptr)
{
NSCAssert(NO, @"Invalid params");
return 0;
}
NSString* privateKey = [m_storage privateKeyForSlot:keyId];
NSArray<NSString*>* components = [privateKey componentsSeparatedByString:@"_"];
const NSInteger componentsCount = 4;
if (components.count != componentsCount)
{
*to = "";
return 0;
}
const char* d = [components[0] UTF8String];
const char* n = [components[1] UTF8String];
const char* p = [components[2] UTF8String];
const char* q = [components[3] UTF8String];
RSA* rsa = RSA_new();
BN_hex2bn(&rsa->d, d);
BN_hex2bn(&rsa->n, n);
BN_hex2bn(&rsa->p, p);
BN_hex2bn(&rsa->q, q);
unsigned char* _to = (unsigned char *)calloc(1, sizeof(unsigned char));
int decryptedSize = RSA_private_decrypt((int)from.length(), (unsigned char *)from.c_str(), _to, rsa, RSA_NO_PADDING);
free(_to);
if (decryptedSize <= 0)
{
ERR_print_errors_cb(test, NULL);
*to = "";
return 0;
}
_to = (unsigned char *)calloc(decryptedSize, sizeof(unsigned char));
RSA_private_decrypt((int)from.length(), (unsigned char *)from.c_str(), _to, rsa, RSA_NO_PADDING);
*to = std::string((char *)_to, strlen((char *)_to));
free(_to);
RSA_free(rsa);
return 1;
}
此处字符串from
应该被解密并写入字符串to
。对于解密,我使用 RSA_private_decrypt
函数。我叫它两次。第一次是为了确定解密文本的大小,第二次是为了将解密文本写入 _to
缓冲区。当我第二次调用它时,它通常会像这样崩溃:
malloc: Heap corruption detected, free list is damaged at 0x280ff3d70
*** Incorrect guard value: 0
No1BCmail(2171,0x170efb000) malloc: *** set a breakpoint in malloc_error_break to debug
断点打开,这让我找到了崩溃的地方。但是我不明白它崩溃的原因。我尝试重新创建 RSA
结构并第二次使用分配给 _to
的大小,但没有任何帮助。你能看出这里出了什么问题吗?谢谢
RSA_private_decrypt
要求 to
参数指向足够大小的缓冲区。您的第一次调用仅使用大小为 1 的缓冲区,该缓冲区太小并且是未定义的行为。您需要做的是使用 RSA_size(rsa)
从 rsa
获取大小,然后您可以使用它为 _to
分配 space。这意味着您不需要调用该函数两次,因为您第一次就已经有了大小
如果要构建的字符串而不是使用 strlen
,则您还应该使用 decryptedSize
作为长度,因为 _to
可能不是空终止的。
将所有这些放在一起你应该看起来像
int BCVirtualCard::decrypt(std::string from, std::string *to, int keyId, bool padding)
{
if (to == nullptr)
{
NSCAssert(NO, @"Invalid params");
return 0;
}
NSString* privateKey = [m_storage privateKeyForSlot:keyId];
NSArray<NSString*>* components = [privateKey componentsSeparatedByString:@"_"];
const NSInteger componentsCount = 4;
if (components.count != componentsCount)
{
*to = "";
return 0;
}
const char* d = [components[0] UTF8String];
const char* n = [components[1] UTF8String];
const char* p = [components[2] UTF8String];
const char* q = [components[3] UTF8String];
RSA* rsa = RSA_new();
BN_hex2bn(&rsa->d, d);
BN_hex2bn(&rsa->n, n);
BN_hex2bn(&rsa->p, p);
BN_hex2bn(&rsa->q, q);
auto _to = std::make_unique<unsigned char[]>(RSA_size(rsa)); // use smart pointers so you don't have to worry about releasing the memory
int decryptedSize = RSA_private_decrypt((int)from.length(), (unsigned char *)from.c_str(), _to.get(), rsa, RSA_NO_PADDING);
if (decryptedSize <= 0)
{
ERR_print_errors_cb(test, NULL);
*to = "";
return 0;
}
*to = std::string((char *)_to.get(), decryptedSize);
return 1;
}
请看下面的方法:
int BCVirtualCard::decrypt(std::string from, std::string *to, int keyId, bool padding)
{
if (to == nullptr)
{
NSCAssert(NO, @"Invalid params");
return 0;
}
NSString* privateKey = [m_storage privateKeyForSlot:keyId];
NSArray<NSString*>* components = [privateKey componentsSeparatedByString:@"_"];
const NSInteger componentsCount = 4;
if (components.count != componentsCount)
{
*to = "";
return 0;
}
const char* d = [components[0] UTF8String];
const char* n = [components[1] UTF8String];
const char* p = [components[2] UTF8String];
const char* q = [components[3] UTF8String];
RSA* rsa = RSA_new();
BN_hex2bn(&rsa->d, d);
BN_hex2bn(&rsa->n, n);
BN_hex2bn(&rsa->p, p);
BN_hex2bn(&rsa->q, q);
unsigned char* _to = (unsigned char *)calloc(1, sizeof(unsigned char));
int decryptedSize = RSA_private_decrypt((int)from.length(), (unsigned char *)from.c_str(), _to, rsa, RSA_NO_PADDING);
free(_to);
if (decryptedSize <= 0)
{
ERR_print_errors_cb(test, NULL);
*to = "";
return 0;
}
_to = (unsigned char *)calloc(decryptedSize, sizeof(unsigned char));
RSA_private_decrypt((int)from.length(), (unsigned char *)from.c_str(), _to, rsa, RSA_NO_PADDING);
*to = std::string((char *)_to, strlen((char *)_to));
free(_to);
RSA_free(rsa);
return 1;
}
此处字符串from
应该被解密并写入字符串to
。对于解密,我使用 RSA_private_decrypt
函数。我叫它两次。第一次是为了确定解密文本的大小,第二次是为了将解密文本写入 _to
缓冲区。当我第二次调用它时,它通常会像这样崩溃:
malloc: Heap corruption detected, free list is damaged at 0x280ff3d70
*** Incorrect guard value: 0
No1BCmail(2171,0x170efb000) malloc: *** set a breakpoint in malloc_error_break to debug
断点打开,这让我找到了崩溃的地方。但是我不明白它崩溃的原因。我尝试重新创建 RSA
结构并第二次使用分配给 _to
的大小,但没有任何帮助。你能看出这里出了什么问题吗?谢谢
RSA_private_decrypt
要求 to
参数指向足够大小的缓冲区。您的第一次调用仅使用大小为 1 的缓冲区,该缓冲区太小并且是未定义的行为。您需要做的是使用 RSA_size(rsa)
从 rsa
获取大小,然后您可以使用它为 _to
分配 space。这意味着您不需要调用该函数两次,因为您第一次就已经有了大小
如果要构建的字符串而不是使用 strlen
,则您还应该使用 decryptedSize
作为长度,因为 _to
可能不是空终止的。
将所有这些放在一起你应该看起来像
int BCVirtualCard::decrypt(std::string from, std::string *to, int keyId, bool padding)
{
if (to == nullptr)
{
NSCAssert(NO, @"Invalid params");
return 0;
}
NSString* privateKey = [m_storage privateKeyForSlot:keyId];
NSArray<NSString*>* components = [privateKey componentsSeparatedByString:@"_"];
const NSInteger componentsCount = 4;
if (components.count != componentsCount)
{
*to = "";
return 0;
}
const char* d = [components[0] UTF8String];
const char* n = [components[1] UTF8String];
const char* p = [components[2] UTF8String];
const char* q = [components[3] UTF8String];
RSA* rsa = RSA_new();
BN_hex2bn(&rsa->d, d);
BN_hex2bn(&rsa->n, n);
BN_hex2bn(&rsa->p, p);
BN_hex2bn(&rsa->q, q);
auto _to = std::make_unique<unsigned char[]>(RSA_size(rsa)); // use smart pointers so you don't have to worry about releasing the memory
int decryptedSize = RSA_private_decrypt((int)from.length(), (unsigned char *)from.c_str(), _to.get(), rsa, RSA_NO_PADDING);
if (decryptedSize <= 0)
{
ERR_print_errors_cb(test, NULL);
*to = "";
return 0;
}
*to = std::string((char *)_to.get(), decryptedSize);
return 1;
}