Your RSA Keys Are Likely To Be So Important For The Security of Your Organisation … especially…

Do you know your DER from your PEM, and PKCS1 from OpenSSH keys?

Photo by Sixteen Miles Out on Unsplash

Your RSA Keys Are Likely To Be So Important For The Security of Your Organisation … especially OpenSSH ones

Do you know your DER from your PEM, and PKCS1 from OpenSSH keys?

Your 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-----

Method

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 [here]:

Private key:
-----BEGIN PRIVATE KEY-----
MIIB1QIBADANBgkqhkiG9w0BAQEFAASCAb8wggG7AgEAAl0DE9kTKz1WHSM2qLtX
wp6+GhQvrQPLlROHwKxVWkauvNDReulTnK/sIzIkXUEjnJEkmofxc2NBNt6i9K4X
2NJJzz18KIlC24ekK7dpOxEBAeOfjHohqjMwpdsyghECAwEAAQJdAWjb6t3JUGI0
ONr8RGxOTYCgcl3q+RqlQW7NAKNC8NJnSyvjJ3sDUUOlueZE6cs29XVjBBJPgC2c
HwSmt6wTb/0JDZEw9lXULGoi+j+JtU0nyTegBXoOXXSrYInhAi8B2K5ANcYjNxv/
AnZEhnP7JInt/aWCN++LGVBdtspHDfU3jFT3uD3Y8WqWRuxPTQIvAaqxKRMzkwDR
YFl3PDUcpx9uG3idPFMRubdK7sXkb8pyFmdFIMe2vJGedswxI9UCLwElbE4p03zK
2hM8iQRS3q6ZaRIW8eZbKNWVekEiloDzVjUMZTZ95c7FVqBBGLLFAi8AzOym0Hz9
hfAIuQ8F0HBBZ1vnP6csWKzzp68KO+p5Mh5W2iQeGSyPJdSYM3sKPQIvAQ0e5AHk
WUNSCnLO3PoLDbnrJjXT0Gc6WPxImUbXpAoANcK9xwcM7Rg+XXd7+ic=
-----END PRIVATE KEY-----

Public key:
-----BEGIN RSA PUBLIC KEY-----
MGQCXQMT2RMrPVYdIzaou1fCnr4aFC+tA8uVE4fArFVaRq680NF66VOcr+wjMiRd
QSOckSSah/FzY0E23qL0rhfY0knPPXwoiULbh6Qrt2k7EQEB45+MeiGqMzCl2zKC
EQIDAQAB
-----END RSA PUBLIC KEY-----

For a PKCS8 format for the private key and OpenSSL for the public key we have [here]:

Private key:
-----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-----

Public key:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAXQMfdioW/ibO3rtEACYqplJjfYa2hSqQtfNIk4h7Dah+IrHeiN0m8vr2ldkso2gqQpvxFArJZ2EAiRtMQVfeTyauhd5rk0x8H00AfQABJDq6grldizuYy5tCC7V2Fw==

Coding

The code we can use is [here]:

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
# PEM or DER
public_key_encode=0
public_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:
private_key = key.private_bytes(private_key_encoding,private_key_format,crypto_serialization.NoEncryption())

public_key = key.public_key().public_bytes(public_key_encoding,public_key_format)
if (private_key_encoding== crypto_serialization.Encoding.DER):
print(f"Private key:\n{binascii.b2a_hex(private_key).decode()}")
else:
print(f"Private key:\n{private_key.decode()}")
if (public_key_encoding== crypto_serialization.Encoding.DER):
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(e)

Conclusions

RSA keys are often fundamental to the security of Cloud and GitHub infrastructures, and the OpenSSH format is fairly typical in authenticating a user. If someone manages to find your private key, then are likely to be able to log into a trusted account… so be careful!

While there’s a move to using ECC key pairs, RSA is still the most popular method for authenticating with a key pair.