0%

C/C++ 中,modulus,privateExponent, pulbicExponent 如何转换成 RSA密钥

p.s: 以下内容均以 openssl 实现。
RSA 密钥的存储方式有很多,某些情况下,我们直接保存密钥的 modulus(n),publicExponent(e),privateExponent(d),使用的时候再将它们转换成 RSA 密钥。下面来讲讲在 C/C++ 环境中,如何把这几个大整数转换成 RSA 密钥来用。
根据 openssl 的文档,openssl提供了这样一个函数

1
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);

这个参数里面的 n , e , q 对应 RSA 算法里面的参数,实际使用中,它们分别是

  • n –> modulus
  • e –> publicExponent
  • d –> privateExponent

其中,n和e组成了公钥,n和d组成私钥(取自 RSA算法原理),那么,我们想用 modulus(n),publicExponent(e),privateExponent(q) 来生成一个RSA密钥使用的话,可以用下面这样简短的方式

1
2
3
4
5
6
7
8
RSA* rsa = RSA_new();
BIGNUM* modulus = BN_new();
BIGNUM* publicExponent = BN_new();
BIGNUM* privateExponent = BN_new();
BN_hex2bn(&modulus,"the_modulus_hex_str");
BN_hex2bn(&publicExponent,"the_publicexponent_hex_str");
BN_hex2bn(&privateExponent,"the_privateexponent_hex_str");
RSA_set0_key(rsa,n,e,d);

其中,the_modulus_hex_strthe_publicexponent_hex_strthe_privateexponent_hex_str 是指对应的巨大整数的十六进制字符串。例如

1
2
3
n: XXXXXX31C433EDD1B99CE2B218C253F46FDFFFB888B6CFC6B2ED7C733454E744BF95369DA3E6648AFB6FB11EF85A5BB25A1F328266844C2E3FAC8EFAAB4B2C45588604BAC6CF8A9B528F0D03E6B56BDE534B0360F1BD9E8B36D4197FE6F058D97DE670C0F178D9633FEEAE94237827A4006BC737344932E8F3E349F62175B7
e: 010001
d: XXXXXXX6566B839C1F88C15D1A46771F1E4C3918000787D56016208B758F3E1A33A923226850DA53C288F9CF6753DFBE48750A83B3DE58D5C0B85933C5B92ABCCD60D80992AABA03C3B1A7E58B8289A93383D8DAA4EE23178660D09E0335522EDCEAD84FB34D7A39B7794C905F15883FC8D1F3D57790259B4D51BA25F67D2D211

上面对应的巨大整数的十进制数为

1
2
3
n: XXXXXXX9057732971629580498028671059682869498690832625587443656573925941563146104539350008204291144532450083831552937873084816334755400478676505846850294967700928692649221538739009633205352515287702420255727528786212412171786407245232978625501660599119803054000638252479305264674077018562561222430729026237879
e: 65537
d: XXXXXXXX041865311331499528401083208041704898325216901065444649537573972168292421030450065823066407208305456734951704373218531670621023627175563960996010664960509836168571614423098404829680294776295068450558648709945648817915783177775326687433116356887666860252766677606932669252345719029413488408688871813075473

这样,我们就得到了一个RSA密钥。接下来可以使用这个密钥对一些数据加密/解密。
比如,使用 RSA/ECB/PKCS1Padding 填充方式,进行公钥加密,私钥解密例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
char encrypteddata[1024] = { 0 };
char originnaldata[1024] = { 0 };
const char* testinfo = "this is a sample info to encrypt";
int encryptlen = 0;
int retlen = 0;
encryptlen = RSA_public_encrypt(strlen(testinfo), (const unsigned char*)testinfo, (unsigned char *)encrypteddata, rsa, RSA_PKCS1_PADDING);
if (encryptlen > 0)
{
retlen = RSA_private_decrypt(encryptlen, (const unsigned char*)encrypteddata, (unsigned char*)originnaldata, rsa, RSA_PKCS1_PADDING);
if (retlen > 0)
{
printf("%.*s\n", retlen, originnaldata);
}
}

openssl 里面,公钥加密,私钥解密的函数原型是

1
2
3
4
5
int RSA_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);

int RSA_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);

同样的,还有私钥加密,公钥解密的函数原型是

1
2
3
4
5
int RSA_private_encrypt(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);

int RSA_public_decrypt(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);