生成 RSA 并保存在 ASN.1/DER 中时出现分段错误?
Segmentation fault with generating an RSA and saving in ASN.1/DER?
#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#define RSA_LEN 2048
#define RSA_FACTOR 65537
int genRSA2048(unsigned char **pub,unsigned int *pub_l,unsigned char **priv,unsigned int *priv_l){
RSA *pRSA = NULL;
pRSA = RSA_generate_key(RSA_LEN,RSA_FACTOR,NULL,NULL);
if (pRSA){
pub_l = malloc(sizeof(pub_l));
*pub_l = i2d_RSAPublicKey(pRSA,pub);
priv_l = malloc(sizeof(priv_l));
*priv_l = i2d_RSAPrivateKey(pRSA,priv);
return 0;
} else {
return 1;
}
}
int main(){
unsigned char *pub = NULL;
unsigned int publ;
unsigned char *priv = NULL;
unsigned int privl;
genRSA2048(&pub,&publ,&priv,&privl);
RSA *privrsa = NULL;
d2i_RSAPrivateKey(&privrsa,(const unsigned char **)&priv,privl);
RSA *pubrsa = NULL;
d2i_RSAPublicKey(&pubrsa,(const unsigned char **)&pub,publ);
unsigned char * data ="01234567890123456789012345678912";
unsigned char encrypted[256];
unsigned char decrypted[32];
int len = RSA_private_encrypt(32,data,encrypted,privrsa,RSA_PKCS1_PADDING);
RSA_public_decrypt(len,encrypted,decrypted,pubrsa,RSA_PKCS1_PADDING);
}
我试图通过检查 gdb 来找到错误,但作为 C 的新手,我没有找到任何线索来告诉我发生了什么,但我相信这是一个分配问题,但是根据 d2i_RSAPrivateKey 和类似的,他们应该自己分配 space。
如有任何帮助,我们将不胜感激。
编译为cc foo.c -lcrypto
这是这个问题的跟进:
正如我所提到的,我在评论中使用了@WhozCraig 示例,可以在此处找到,即使它完全不同,也提供了很多帮助。
pub_l = malloc(sizeof(pub_l));
根本不需要。 priv_l = malloc(sizeof(priv_l));
也不是。从您的函数中删除它们。
您应该填充您的输出参数;相反,您将丢弃调用者提供的地址来填充和 (a) 填充您自己的地址,然后 (b) 泄漏您刚刚分配的内存。
结果是调用者的 privl
和 publ
未被触及,因此解码回 RSA
是功能失调的,因为这两个值都是不确定的。
pRSA = RSA_generate_key(RSA_LEN,RSA_FACTOR,NULL,NULL);
我认为这是错误的。我知道您应该使用 RSA_generate_key_ex
,我认为它需要 BIGNUM
,而不是整数。你应该得到警告。有关详细信息,请参阅 RSA_generate_key(3)
。
您的代码应该类似于:
BIGNUM* exp = BN_new();
ASSERT(exp != NULL);
int rc = BN_set_word(exp, RSA_F4);
ASSERT(rc == 1);
RSA* rsa = RSA_new();
ASSERT(rsa != NULL);
rc = RSA_generate_key_ex(rsa, 2048, exp, NULL);
ASSERT(rc == 1);
一定要在 BIGNUM
上调用 BN_free
,在 RSA
指针上调用 RSA_free
。
RSA *privrsa = NULL;
d2i_RSAPrivateKey(&privrsa,(const unsigned char **)&priv,privl);
RSA *pubrsa = NULL;
d2i_RSAPublicKey(&pubrsa,(const unsigned char **)&pub,publ);
为此,您似乎在尝试分离 public 密钥和私钥。为此,请使用 RSAPublicKey_dup
和 RSAPrivateKey_dup
。参见 Separating public and private keys from RSA keypair variable。
我不清楚你想用以下内容做什么。你应该说明你正在尝试做什么......
pub_l = malloc(sizeof(pub_l));
*pub_l = i2d_RSAPublicKey(pRSA,pub);
priv_l = malloc(sizeof(priv_l));
*priv_l = i2d_RSAPrivateKey(pRSA,priv);
我只是在猜测,但我要说这全错了。 sizeof(priv_l)
是指针的大小,所以它是 4 或 8 个字节。您还覆盖了调用者传入的指针...
另见 。它谈到用 SubjectPublicKeyInfo 和 PrivateKeyInfo 以 ASN.1/DER 和 PEM 格式保存密钥。
通过写入 {Public|Private}KeyInfo,OID 被写入密钥。这对于互操作很重要。您还使用 RSA*
(甚至 EVP_PKEY*
),而不是字节数组。
#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#define RSA_LEN 2048
#define RSA_FACTOR 65537
int genRSA2048(unsigned char **pub,unsigned int *pub_l,unsigned char **priv,unsigned int *priv_l){
RSA *pRSA = NULL;
pRSA = RSA_generate_key(RSA_LEN,RSA_FACTOR,NULL,NULL);
if (pRSA){
pub_l = malloc(sizeof(pub_l));
*pub_l = i2d_RSAPublicKey(pRSA,pub);
priv_l = malloc(sizeof(priv_l));
*priv_l = i2d_RSAPrivateKey(pRSA,priv);
return 0;
} else {
return 1;
}
}
int main(){
unsigned char *pub = NULL;
unsigned int publ;
unsigned char *priv = NULL;
unsigned int privl;
genRSA2048(&pub,&publ,&priv,&privl);
RSA *privrsa = NULL;
d2i_RSAPrivateKey(&privrsa,(const unsigned char **)&priv,privl);
RSA *pubrsa = NULL;
d2i_RSAPublicKey(&pubrsa,(const unsigned char **)&pub,publ);
unsigned char * data ="01234567890123456789012345678912";
unsigned char encrypted[256];
unsigned char decrypted[32];
int len = RSA_private_encrypt(32,data,encrypted,privrsa,RSA_PKCS1_PADDING);
RSA_public_decrypt(len,encrypted,decrypted,pubrsa,RSA_PKCS1_PADDING);
}
我试图通过检查 gdb 来找到错误,但作为 C 的新手,我没有找到任何线索来告诉我发生了什么,但我相信这是一个分配问题,但是根据 d2i_RSAPrivateKey 和类似的,他们应该自己分配 space。
如有任何帮助,我们将不胜感激。
编译为cc foo.c -lcrypto
这是这个问题的跟进:
正如我所提到的,我在评论中使用了@WhozCraig 示例,可以在此处找到,即使它完全不同,也提供了很多帮助。
pub_l = malloc(sizeof(pub_l));
根本不需要。 priv_l = malloc(sizeof(priv_l));
也不是。从您的函数中删除它们。
您应该填充您的输出参数;相反,您将丢弃调用者提供的地址来填充和 (a) 填充您自己的地址,然后 (b) 泄漏您刚刚分配的内存。
结果是调用者的 privl
和 publ
未被触及,因此解码回 RSA
是功能失调的,因为这两个值都是不确定的。
pRSA = RSA_generate_key(RSA_LEN,RSA_FACTOR,NULL,NULL);
我认为这是错误的。我知道您应该使用 RSA_generate_key_ex
,我认为它需要 BIGNUM
,而不是整数。你应该得到警告。有关详细信息,请参阅 RSA_generate_key(3)
。
您的代码应该类似于:
BIGNUM* exp = BN_new();
ASSERT(exp != NULL);
int rc = BN_set_word(exp, RSA_F4);
ASSERT(rc == 1);
RSA* rsa = RSA_new();
ASSERT(rsa != NULL);
rc = RSA_generate_key_ex(rsa, 2048, exp, NULL);
ASSERT(rc == 1);
一定要在 BIGNUM
上调用 BN_free
,在 RSA
指针上调用 RSA_free
。
RSA *privrsa = NULL; d2i_RSAPrivateKey(&privrsa,(const unsigned char **)&priv,privl); RSA *pubrsa = NULL; d2i_RSAPublicKey(&pubrsa,(const unsigned char **)&pub,publ);
为此,您似乎在尝试分离 public 密钥和私钥。为此,请使用 RSAPublicKey_dup
和 RSAPrivateKey_dup
。参见 Separating public and private keys from RSA keypair variable。
我不清楚你想用以下内容做什么。你应该说明你正在尝试做什么......
pub_l = malloc(sizeof(pub_l));
*pub_l = i2d_RSAPublicKey(pRSA,pub);
priv_l = malloc(sizeof(priv_l));
*priv_l = i2d_RSAPrivateKey(pRSA,priv);
我只是在猜测,但我要说这全错了。 sizeof(priv_l)
是指针的大小,所以它是 4 或 8 个字节。您还覆盖了调用者传入的指针...
另见
通过写入 {Public|Private}KeyInfo,OID 被写入密钥。这对于互操作很重要。您还使用 RSA*
(甚至 EVP_PKEY*
),而不是字节数组。