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_str
,the_publicexponent_hex_str
,the_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);
|