RSA Keys (PEM, DER, PKCS1, PKCS8 and OpenSSH)[OpenSSH Home][Home]
With RSA, we generate a private key and a public key. The public key can be used to encrypt data, and the private key to decrypt it. We can also sign data with the private key, and prove the signature with the public key. With our RSA key, there are a number of formats that can be used for the keys. For the private key, we can have a DER or a PEM encoding. With DER, we have binary encoding, and with PEM we have a Base64 encoding. With the private key format, we normally have a PKCS8 or OpenSSH format. For the public key format, we typically use either PKCS1 or OpenSSH format. PKCS1 (RFC 8017 [here]) is used for RSA public keys, and PKCS8 (RFC 5208 [here]) for RSA private keys. The OpenSSH format is used when OpenSSH is used.
|
Method
Our RSA keys are likely to be fundamental to your organisation's security? Why? Well, if your company has a connection to the Cloud, it is likely that you’ll be using SSH to connect to it. Also, if you have GitHub, your company will often use an OpenSSH key pair to authenticate you. For this, we create an RSA key pair and then store the private key on your host, and then upload the public key onto the server. When you log in, you sign a message with your private key, and where the public key on the server then authenticates you. A typical command is:
$ ssh-keygen -t rsa -b 4096 -C "[email protected]"
and which will generate a 4,096-bit key pair. We typically store the private key in the ./ssh folder, and which contains a public key in the form:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAXQMfdioW/ibO3rtEACYqplJjfYa2hSqQtfNIk4h 7Dah+IrHeiN0m8vr2ldkso2gqQpvxFArJZ2EAiRtMQVfeTyauhd5rk0x8H00AfQABJDq6grldiz uYy5tCC7V2Fw==
The private key typically has a PEM form:
-----BEGIN PRIVATE KEY----- MIIB1QIBADANBgkqhkiG9w0BAQEFAASCAb8wggG7AgEAAl0DH3YqFv4mzt67RAAm KqZSY32GtoUqkLXzSJOIew2ofiKx3ojdJvL69pXZLKNoKkKb8RQKyWdhAIkbTEFX 3k8mroXea5NMfB9NAH0AASQ6uoK5XYs7mMubQgu1dhcCAwEAAQJdAjrb+LAUaQe8 +cFTze0UeK48Ow5nxn4wvniriIA9v3vaMGJ0Hl6qkFO1qq76O+uvSehxPHnzBrfs SXkQ8nScyeGpoTpn0DCnMnFRiY1hAMy6SqVdC4t7UP9u6oCBAi8B+POU6nCyUOnL FlPVGFoBxSoxC7q7tJytq+xaPfGBN63AT3sdnXm06YAH1uE/1wIvAZVPf+1sDjIP c4hFNPzIPh/x1M3qDN9eBr6tdPwymuPmpQ1lik/b9ZpMfXGns8ECLwDTVfcci+BF tyP1i06jq4AUKg1u8E+BTxXs37YBOOOxDvpvCYMiln6eP6SITavvAi8A6n71d8rl p6by4+uOjZXZA6hpw7zfN7hx1I4MugEZRjPiWI7f5/ZN8bjBdylcwQIvAQp1f9vQ S+P5ktRlO7vEm10LtKotJ85Rp+le7PX56re+nntKVZFsliKW0yPmWJE= -----END PRIVATE KEY-----
With RSA, we generate a private key and a public key. The public key can be used to encrypt data, and the private key to decrypt it. We can also sign data with the private key, and prove the signature with the public key. With our RSA key, there are a number of formats that can be used for the keys.
For the private key, we can have a DER or a PEM encoding. With DER, we have binary encoding, and with PEM we have a Base64 encoding. With the private key format, we normally have a PKCS8 or OpenSSH format. For the public key format, we typically use either PKCS1 or OpenSSH format. PKCS1 (RFC 8017 [here]) is used for RSA public keys, and PKCS8 (RFC 5208 [here]) for RSA private keys. The OpenSSH format is used when OpenSSH is used.
For a PKCS8 format for the private key and PKCS1 for the public key we have:
Private key encoding: Encoding.PEM Private key format: PrivateFormat.PKCS8 Public key encoding: Encoding.PEM Public key format: PublicFormat.PKCS1 Curve: RSA Key size: 512 Private key: -----BEGIN PRIVATE KEY----- MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAolXeu/Z3CmsQ3+cC oUU0/ckmNmOzfCfHcxbOsvIg0W+ZCw9Dunqkwu8n+DOv52y4sVucPN4/n1h/5wT/ LwK1gQIDAQABAkAKHHMdHgLYIUcRyx+8z8S3MfoxVRBu4UNpBbimKLKmmMV2UqIK IbTzithZWol8YZVOzwe6GZqZdbWsN2A/99fJAiEA0RYqbzrG+rj/JNN+uB2onIJ5 hX04p7F4R6naoRw/sC8CIQDGwlcSqdyciiNx4mzLNBADkxRaKIwWa4k5/+P5BNVZ TwIhAJbTAXtJD/4OcuZytedEZbu4lsaHZNX6vAQd73rmcL67AiEAqqLdriA2Tg4q L/N8A1hHB0qWBnEZE4Zu4WRWi8sifvECIHOwaiu894SZOXT/oVWUe1Tt8TTUkjh3 vrzFEngj1KH1 -----END PRIVATE KEY----- Public key: -----BEGIN RSA PUBLIC KEY----- MEgCQQCiVd679ncKaxDf5wKhRTT9ySY2Y7N8J8dzFs6y8iDRb5kLD0O6eqTC7yf4 M6/nbLixW5w83j+fWH/nBP8vArWBAgMBAAE= -----END RSA PUBLIC KEY----- == Key details == Private key p: 94572548861418413170793281130206948262270743656077910281902919609818141405231 Private key q: 89901313305153493837701246798962325038348122110633117471237293551165111621967 Private key d: 529562926001195601356684301698866326413345712090993164221410379202037190321577763828933217411281353522563929370506825155100138444226272376429593583146953 Private key dmp1: 68219742243672360386487821618788371135371613078735419817461289417491686145723 Private key dmq1: 77180943464015078158664921340568171505525409195304358170219800789824890371825 Private key iqmp: 52327675434767630609908503478553704202898127769459895123317013029443897434613 Public key N: 8502196345257314092629353032934493491952826539271783195389165120471315860388533789897638465459959515059108061765928203429656415393078278070600051028309377 Public key e: 65537
For a PKCS8 format for the private key and OpenSSL for the public key we have:
Private key encoding: Encoding.PEM Private key format: PrivateFormat.PKCS8 Public key encoding: Encoding.OpenSSH Public key format: PublicFormat.OpenSSH Curve: RSA Key size: 512 Private key: -----BEGIN PRIVATE KEY----- MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmrlxD5nriWnx6sjq RShGE09rODVfsOf8eM9LoQmGuKMVyYwiLzBxfb/9fI/85mGZ5lz4q99/aYRMzDEW 1b7ztQIDAQABAkAKQqXmvPRLpoTuZuhyMZuECE456gAwgRHTCRwgz7rpX3zXJHDj u9eTb72M6xpySSVzzm4dnyApDI3cczH8KVhBAiEAzdrjWtUasmUNsVbSyN32x3ZQ oRH3qQ7ygj8ZSZQSmz0CIQDAagxTasVSwRYkSfxi9QCw7HZB69Pwu5o4Slm/3Tih 2QIgeZpGF9AvNxbO4eWCGrpUHzvbIWr1u95ij2Iq0/Yuj5kCIHr2CkRwkgMNY3Hz Wfd/LF7j7bq40ysfKDHayboDzEIZAiEAtCaFTAi6jwlNH8eiDGJGcQpLQHZszbzC RE93Czur8RE= -----END PRIVATE KEY----- Public key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQCauXEPmeuJafHqyOpFKEYTT2s4NV+w5/x4z0uhCYa4oxXJjCIvMHF9v/18j/zmYZnmXPir339phEzMMRbVvvO1 == Key details == Private key p: 93110875764949719476238107672919838687628633107480967655388250638667882863421 Private key q: 87031437786729667164140930047172401841167023011440001381225829497798292709849 Private key d: 537377816486057093623489898048742650307780775209058960854798861864356041641982701729791124202966316352993094018697228194170186627346400257856269332338753 Private key dmp1: 55002432890798532734227720225970347055142208250652580707244773719050130722713 Private key dmq1: 55616882767688865686579890616073780635517586870655029950213146241013325251097 Private key iqmp: 81484372915588842505944083993148404899258637724832461768066878335252901392657 Public key N: 8103573391405136618684458685784732414454907654136239557648631617580373193992499590832953636793406019816852260372917254966135377710040073283801059648533429 Public key e: 65537
Coding
The code we can use is:
from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.backends import default_backend as crypto_default_backend import binascii import sys keysize=512 private_key_encoding= crypto_serialization.Encoding.PEM public_key_encode=0 public_key_form=0 private_key_encode=0 private_key_form=0 private_key_format= crypto_serialization.PrivateFormat.PKCS8 public_key_format= crypto_serialization.PrivateFormat.TraditionalOpenSSL if (len(sys.argv)>1): keysize=int(sys.argv[1]) if (len(sys.argv)>2): private_key_encode=int(sys.argv[2]) if (len(sys.argv)>3): private_key_form=int(sys.argv[3]) if (len(sys.argv)>4): public_key_encode=int(sys.argv[4]) if (len(sys.argv)>5): public_key_form=int(sys.argv[5]) if (private_key_encode==0): private_key_encoding= crypto_serialization.Encoding.DER elif (private_key_encode==1): private_key_encoding= crypto_serialization.Encoding.PEM else: private_key_encoding= crypto_serialization.Encoding.OpenSSH if (private_key_form==0): private_key_format= crypto_serialization.PrivateFormat.PKCS8 elif (private_key_form==1): private_key_format= crypto_serialization.PrivateFormat.OpenSSH else: private_key_format= crypto_serialization.PrivateFormat.TraditionalOpenSSL if (public_key_encode==0): public_key_encoding= crypto_serialization.Encoding.DER elif (public_key_encode==1): public_key_encoding= crypto_serialization.Encoding.PEM else: public_key_encoding= crypto_serialization.Encoding.OpenSSH if (public_key_form==0): public_key_format= crypto_serialization.PublicFormat.PKCS1 elif (public_key_form==1): public_key_format= crypto_serialization.PublicFormat.OpenSSH else: public_key_format= crypto_serialization.PublicFormat.Raw key = rsa.generate_private_key( backend=crypto_default_backend(), public_exponent=65537, key_size=keysize ) try: print("Private key encoding:\t",private_key_encoding) print("Private key format:\t",private_key_format) print("Public key encoding:\t",public_key_encoding) print("Public key format:\t",public_key_format) print("Curve:\t\t\t RSA") private_key = key.private_bytes(private_key_encoding,private_key_format,crypto_serialization.NoEncryption()) if (private_key_encoding== crypto_serialization.Encoding.DER or private_key_encoding== crypto_serialization.Encoding.Raw): print(f"\nPrivate key:\n{binascii.b2a_hex(private_key).decode()}") else: print(f"\nPrivate key:\n{private_key.decode()}") except Exception as e: print("Private key error: ",e) try: public_key = key.public_key().public_bytes(public_key_encoding,public_key_format) if (public_key_encoding== crypto_serialization.Encoding.DER or public_key_encoding== crypto_serialization.Encoding.Raw): print(f"\nPublic key:\n{binascii.b2a_hex(public_key).decode()}") else: print(f"\nPublic key:\n{public_key.decode()}") except Exception as e: print("\nPublic key error: ",e) print("\n== Key details ==") print(f"Private key p: {key.private_numbers().p}") print(f"Private key q: {key.private_numbers().q}") print(f"Private key d: {key.private_numbers().d}") print(f"Private key dmp1: {key.private_numbers().dmp1}") print(f"Private key dmq1: {key.private_numbers().dmq1}") print(f"Private key iqmp: {key.private_numbers().iqmp}") print(f"Public key N: {key.private_numbers().public_numbers.n}") print(f"Public key e: {key.private_numbers().public_numbers.e}")