首页 > 技术文章 > 【学习笔记】RSA非对称加密

nightnine 2020-05-18 12:44 原文

某日对接公司的加密设备时遇到的,所以学习记录下

1.生成秘钥对,秘钥对格式

在 在线生成RSA秘钥对网站上,随便生成的公钥内容如下:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCchr+uRYTwmme1pOZOfDHk5Rdu
cXySDP8OHqQMynbq+0YokMONcNtuB6tm63N8sBZwYkmgQ3IRY80K6ozZohS+xHQS
9S9Y2tRU961ToBiMnZCZSfFHMY4ZvffW5aZbxg/8ZvSRKToJKcgsQ0OrxM4/4xYB
JIVRJrIeN+0h4l9UTwIDAQAB
-----END PUBLIC KEY-----

可以看出,内容由: -----BEGIN PUBLIC KEY----- ,Base64编码的数据,-----END PUBLIC KEY-----,3部分组成

2.BASE64编码的数据


16进制数据如下

30 81 9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 81 8D 00 30 
81 89 02 81 81 00 9C 86 BF AE 45 84 F0 9A 67 B5 A4 E6 4E 7C 31 E4 E5 
17 6E 71 7C 92 0C FF 0E 1E A4 0C CA 76 EA FB 46 28 90 C3 8D 70 DB 6E 
07 AB 66 EB 73 7C B0 16 70 62 49 A0 43 72 11 63 CD 0A EA 8C D9 A2 14 
BE C4 74 12 F5 2F 58 DA D4 54 F7 AD 53 A0 18 8C 9D 90 99 49 F1 47 31 
8E 19 BD F7 D6 E5 A6 5B C6 0F FC 66 F4 91 29 3A 09 29 C8 2C 43 43 AB 
C4 CE 3F E3 16 01 24 85 51 26 B2 1E 37 ED 21 E2 5F 54 4F 02 03 01 00 01 

此数据为RSA公钥的ASN.1 DER表示方法

3.解析

30  <------>   ASN.1的SEQUENCE编码
   81 9F  <------>  81 表示有一个长度字节,如果是82就是有2个长度字节,9F表示下面还有159字节                   ---------------
        30
            0D  <------> 长度13字节
            06           -------------------           ——
            09                                          |
            2A                                          |
            86 48                                       |   
            86 F7 0D                                    |
        01  01  01                                      |    
        05  00           --------------------          ——
        03
            81 8D   <------>  81 表示有一个长度字节,8D表示下面还有141字节      
            00 
            30
               81 89  <------>  81 表示有一个长度字节,89表示下面还有137字节
               02
               81 81  <------>  81 表示有一个长度字节,81表示129字节,即实际公钥key内容长度+1
            00 
            9C 86 BF AE 45 84 F0 9A 67 B5 A4 E6 4E 7C 31 E4 E5                <------>实际公钥key内容
            17 6E 71 7C 92 0C FF 0E 1E A4 0C CA 76 EA FB 46 28 90 C3 8D 70 DB 6E <------>实际公钥key内容
            07 AB 66 EB 73 7C B0 16 70 62 49 A0 43 72 11 63 CD 0A EA 8C D9 A2 14 <------>实际公钥key内容
            BE C4 74 12 F5 2F 58 DA D4 54 F7 AD 53 A0 18 8C 9D 90 99 49 F1 47 31 <------>实际公钥key内容
            8E 19 BD F7 D6 E5 A6 5B C6 0F FC 66 F4 91 29 3A 09 29 C8 2C 43 43 AB <------>实际公钥key内容
            C4 CE 3F E3 16 01 24 85 51 26 B2 1E 37 ED 21 E2 5F 54 4F             <------>实际公钥key内容
            02
            03
            01 00 01                                                                                    -------------

4.拼接

因为设备给出的只有,实际公钥key内容,想调用openssl的RSA公钥加密,需要进行拼接,如 上一节说明,只需考虑实际公钥key长度变化的那几位,然后进行拼接,相当于上面几步的逆向,4->3->2->1,组装成 begin+base64+end的形式。

RSA* createRSA(unsigned char* key, int flag)
{
	BIO *bio=NULL;
	RSA *rsa = NULL;
	bio = BIO_new_mem_buf(key, -1);
	if (NULL == bio) 
		return rsa;
	if(flag == 1)
	{
		rsa = PEM_read_bio_RSAPublicKey(bio, &rsa, NULL, NULL);
	}
	else if(flag == 2)
	{
		rsa = PEM_read_bio_RSA_PUBKEY(bio, &rsa, NULL, NULL);
	}
	else if (flag == 3)
	{
		rsa = PEM_read_bio_RSAPrivateKey(bio, &rsa, NULL, NULL);
	}
	if(rsa == NULL)
		MessageBoxA(NULL, "Failed to create RSA","",MB_OK);

	return rsa;
}

再调用RSA_public_encrypt进行加密

推荐阅读