Ed25519 Keys (PEM, DER, and Raw, with PKCS8 and OpenSSH)[Hazmat Home][Home]
Curve 25519 is one of the most widely used ECC methods. It uses a curve of \(y^2 = x^3 + 486662 x^2 + x\) [plot], and which is a Montgomery curve. The prime number used is \(2^{255}-19\). This page generates an Ed25519 key pair, and displays the private and public key in various formats. The encoding formats are PEM, DER and Raw, and the formating is undertaken with OpenSSH, PublicSubjectInfo and Raw.
|
Method
Curve 25519 is one of the most widely used ECC methods. It uses a curve of \(y^2 = x^3 + 486662 x^2 + x\) [plot], and which is a Montgomery curve. The prime number used is \(2^{255}-19\). This page generates an Ed25519 key pair, and displays the private and public key in various formats. The private key a random scalar value (\(a\)), and the public key is:
\(Pk=a.G\)
and where \(G\) is the base point on the curve. This is normally an (\(x,y\)) point, but in Curve 25519 we only need to store the \(x\) value. Thus the private key is the same size as the public key.
$ ssh-keygen -t ed25519 -C "[email protected]"
and which will generate an Ed25519 key pair. We typically store the private key in the ./ssh folder, and which contains a public key in the form:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFP7xLB1QQNFqgh3KXymNzmDU4OlLBybR7BWwgcL4R+c uYy5tCC7V2Fw==
The private key typically has a PEM form:
-----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEIL6m8j7OWZiZj8xC4Gx7qaMwy23LcWZqLoytC/DLLOst -----END PRIVATE KEY-----
With EdDSA, we generate a private key and a public key. We sign data with the private key, and prove the signature with the public key. With our EdDSA key, there are a number of formats that can be used for the keys.
For the private key, we can have a DER, PEM or Raw encoding. With DER, we have binary encoding, with PEM we have a Base64 encoding, and for Raw we get raw binary scalar value. With the private key format, we normally have a PublicKeyInfo, OpenSSH or Raw format. For the public key format, we typically use either p OpenSSH format is used when OpenSSH is used.
A raw format for the public and private key is:
Private key encoding: Encoding.Raw Private key format: PrivateFormat.Raw Public key encoding: Encoding.Raw Public key format: PublicFormat.Raw Private key: 308edd7fca562182adbffaa59264a138d9e04f9f3adbda2c80ef1ca71b7dcfa4 Public key: a06042d815cab4e60f0bc3e5baa6cdb599a5dbd85ab593c5fbd4af80c985f5d1
For a public key with OpenSSH format we get:
Private key encoding: Encoding.Raw Private key format: PrivateFormat.Raw Public key encoding: Encoding.OpenSSH Public key format: PublicFormat.OpenSSH Private key: 3154ff11e34ba6494d03151189e4d7705ef6fe7d417b7ba9cfce82d55aa1eb99 Public key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKgYa4mZmicb0SyyptNV0bAe96QrWWdS9ckhvmFcnFde
and for PEM format for both the private and public key:
Private key encoding: Encoding.PEM Private key format: PrivateFormat.PKCS8 Public key encoding: Encoding.PEM Public key format: PublicFormat.SubjectPublicKeyInfo Private key: -----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEIDGbusIw21Mq7BoGMjluljkvYRFX+35R1YMI/ig/ofuK -----END PRIVATE KEY----- Public key: -----BEGIN PUBLIC KEY----- MCowBQYDK2VwAyEA7GzoeIO9cCOKVHXWu76FfNzmb1dklaO6Cx7li5BOTVc= -----END PUBLIC KEY-----
Coding
The code we can use is:
from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.backends import default_backend as crypto_default_backend import binascii import sys private_key_encoding= crypto_serialization.Encoding.PEM private_key_format= crypto_serialization.PrivateFormat.OpenSSH public_key_format= crypto_serialization.PublicFormat.OpenSSH # PEM or DER public_key_encode=0 public_key_form=0 private_key_encode=0 private_key_form=0 if (len(sys.argv)>1): private_key_encode=int(sys.argv[1]) if (len(sys.argv)>2): private_key_form=int(sys.argv[2]) if (len(sys.argv)>3): public_key_encode=int(sys.argv[3]) if (len(sys.argv)>4): public_key_form=int(sys.argv[4]) if (private_key_encode==0): private_key_encoding= crypto_serialization.Encoding.PEM elif (private_key_encode==1): private_key_encoding= crypto_serialization.Encoding.DER else: private_key_encoding= crypto_serialization.Encoding.Raw 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.Raw if (public_key_encode==0): public_key_encoding= crypto_serialization.Encoding.PEM elif (public_key_encode==1): public_key_encoding= crypto_serialization.Encoding.DER elif (public_key_encode==2): public_key_encoding= crypto_serialization.Encoding.OpenSSH else: public_key_encoding= crypto_serialization.Encoding.Raw if (public_key_form==0): public_key_format= crypto_serialization.PublicFormat.SubjectPublicKeyInfo elif (public_key_form==1): public_key_format= crypto_serialization.PublicFormat.OpenSSH else: public_key_format= crypto_serialization.PublicFormat.Raw key=Ed25519PrivateKey.generate() 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) 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("Public key error: ",e)