Extraction and loading of RSA public keys in X509 certificatesDue to project requirements, I plan to use OpenSSL to develop a basic CA for certificate issuance and other functions. In the project model, the public-private key pair is generated by the user and is submitted to the CA in a hexadecimal format. We know that when OpenSSL is used to issue certificates, public/private key pairs are usually generated by OpenSSL. For example, the following three functions are used: rsa_generate_key.
Evp_pkey_assign_rsa
X509_set_pubkey
The process from key generation to certificate loading can be easily completed, while extracting the certificate Public Key only requires
X509_get_pubkey
There is no relevant introduction to how to load the certificate with the RSA public key in hexadecimal form. After several days of research, I finally got it done and posted it to share with you. We can use the following functions
RSA * d2i_rsapublickey (null, (const unsigned **) PP, int Len)
* PP points to the memory unit that stores the public key, and Len refers to the length of the public key. Note that the public key here refers to the Public Key encoded by ASN.1, it is quite complicated to fully elaborate, but it would be much simpler if it is limited to making RSA public keys. The following is the hexadecimal description of ASN.1 encoding of the 1024-bit RSA public key, which occupies 140 bytes in total:
30 81 89 02 81 81 00 E3 8d 99 06 9f BD 9A C0 E5
6a 5d 03 B3 CF 09 ca 8e C1 4A 6C F9 90 C2 46 E0
89 44 69 CD A5 62 91 42 8A 5f E5 8f D3 FB 93 3f
BC D7 6e 5E F2 80 41 A6 79 78 8e 4D 1D 3D 65 AD
D4 36 9C C5 83 55 9d F1 BB 20 4C B7 6C 95 37 B0
37 06 E3 40 FB 8f 74 C3 59 91 A2 BF A2 E1 dB 99
54 29 5f 9B A5 57 F5 40 7A 54 82 9C 84 D4 35 86
14 38 69 14 60 F3 C6 C7 11 75 F2 43 2C 34 ed 89
4A AE E1 9d 57 3E A1 02 03 01 01 ASN.1 adopts tag, lenth, value, and encoding method. Here we compile the entire sequence into a struct, with 30 as the start sign, the second 81 represents the length of 1 byte, that is, 89 represents the length (if it is 82, it indicates the length of two byte, and so on ), converts the string to 137 in decimal format, which is exactly the same as the number of subsequent bytes. Starting from the fourth byte 02, It is the meaning of the sequence, which is equivalent to the element of the struct. Generally, sequence usually needs to be nested, it is equivalent to a struct, but there is only one layer for the sequence of the public key. The fourth 02 represents the bit stream, and the subsequent 81 represents the length of one byte, and the sixth 81 represents the length of 129, that is, starting from 00 till the last row A1 is 129 bytes, removing the previous 00, the remaining 128 bits is the N value of the RSA public key, and the last 5 bytes are bit streams, start with 02, 03 indicates the length is 3, and the last 01 00 01 is the e value of the RSA public key. This may be ASN.1's rule on why we need to add 00 before the N value. If the first four-bit hexadecimal value of a bit stream is smaller than 8, we need to add zero at the beginning, see the following example 30 81 88 02 81 80 32 8d 99 06 9f BD 9A C0 E5 6a
5D 03 B3 CF 09 ca 8e C1 4A 6C F9 90 C2 46 E0 89
44 69 CD A5 62 91 42 8A 5f E5 8f D3 FB 93 3f BC
D7 6e 5E F2 80 41 A6 79 78 8e 4D 1D 3D 65 AD D4
36 9C C5 83 55 9d F1 BB 20 4C B7 6C 95 37 B0 37
06 E3 40 FB 8f 74 C3 59 91 A2 BF A2 E1 dB 99 54
29 5f 9B A5 57 F5 40 7A 54 82 9C 84 D4 35 86 14
38 69 14 60 F3 C6 C7 11 75 F2 43 2C 34 ed 89 4A
AE E1 9d 57 3E A1 02 03 01 00 01 N the first four bits are 0 X3 less than 8, so Zero is not required. Under what circumstances should we use 8x to indicate the number of digits after the tag value to represent length? I understand that if the first four bits of length are greater than 8 or more than one byte, it must be marked with 8x; otherwise, it is not required. After learning about the RSA public key encoding rules, we can easily compile the RSA public key generated by other tools into an acceptable OpenSSL code type to import the public key, for public key extraction, the same function int i2d_rsapublickey (RSA *, (const char **) returns the length of the public key, of course, after ASN.1 encoding. After converting bit streams and RSA, the rest of the work will be very easy. Here we will introduce several simple methods to convert bit and evp_pkey directly: export: len = i2d_rsapublickey (pkey-> pkey. RSA, (const char **) pp); import takes several more steps: pkey-> save_type = 6;
Pkey-> type = evp_pkey_type (6 );
Pkey-> pkey. RSA = d2i_rsapublickey (null, (const char **) PP, Len); pkey is defined as evp_pkey * pkey; during the import process, the first two rows set the RSA password algorithm. If the bit-> RSA-> pkey mode is used, this task is done by evp_pkey_assign_rsa. I have been in contact with openssl4 for a few months. I have summarized my experiences and welcome your criticism.