How can I transform between the two styles of public key format,
one format is:
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
the other format is:
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----
for example I generated id_rsa/id_rsa.pub pair using ssh-keygen command,
I calculated the public key from id_rsa using:
openssl rsa -in id_rsa -pubout -out pub2
then again I calculated the public key from id_rsa.pub using :
ssh-keygen -f id_rsa.pub -e -m pem > pub1
the content is pub1 is :
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----
and the content of pub2 is :
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB
-----END PUBLIC KEY-----
According to my understanding, pub1 and pub2 contain the same public key information, but they are in different format, I wonder how can I transform between the two format? Can anyone show me some concise introduction on the tow formats?
Best Answer
I wanted to help explain what's going on here.
An RSA "Public Key" consists of two numbers:
Using your RSA public key as an example, the two numbers are:
The question then becomes how do we want to store these numbers in a computer. First we convert both to hexadecimal:
RSA invented the first format
RSA invented a format first:
They chose to use the DER flavor of the ASN.1 binary encoding standard to represent the two numbers [1]:
The final binary encoding in ASN.1 is:
If you then run all those bytes together and Base64 encode it, you get:
RSA labs then said add a header and trailer:
Five hyphens, and the words
BEGIN RSA PUBLIC KEY
. That is your PEM DER ASN.1 PKCS#1 RSA Public keyNot just RSA
After that, other forms of public key cryptography came along:
When it came time to create a standard for how to represent the parameters of those encryption algorithms, people adopted a lot of the same ideas that RSA originally defined:
BEGIN PUBLIC KEY
But rather than using:
-----BEGIN RSA PUBLIC KEY-----
-----BEGIN DH PUBLIC KEY-----
-----BEGIN EC PUBLIC KEY-----
They decided instead to include the Object Identifier (OID) of what is to follow. In the case of an RSA public key, that is:
1.2.840.113549.1.1.1
So for RSA public key it was essentially:
Now they created SubjectPublicKeyInfo which is basically:
In actual DER ASN.1 definition is:
That gives you an ASN.1 of:
The final binary encoding in ASN.1 is:
And as before, you take all those bytes, Base64 encode them, you end up with your second example:
Add the slightly different header and trailer, and you get:
And this is your X.509 SubjectPublicKeyInfo/OpenSSL PEM public key [2].
Do it right, or hack it
Now that you know that the encoding isn't magic, you can write all the pieces needed to parse out the RSA modulus and exponent. Or you can recognize that the first 24 bytes are just added new stuff on top of the original PKCS#1 standard
Those first 24-bytes are "new" stuff added:
And due to an extraordinary coincidence of fortune and good luck:
Because in Base64: 3-bytes becomes four characters:
That means if you take your second X.509 public key, the first 32 characters corresponds only to newly added stuff:
If you remove the first 32 characters, and change it to BEGIN RSA PUBLIC KEY:
You have exactly what you wanted - the older
RSA PUBLIC KEY
format.