ECC Keys (PEM, DER, and Raw, with PKCS8 and OpenSSH)[Hazmat Home][Home]
With Elliptic Curve Cryptography (ECC) we can use a Weierstrass curve form of the form of \(y^2=x^3+ax+b \pmod p\). Bitcoin and Ethereum use secp256k1 and which has the form of \(y^2=x^3 + 7 \pmod p\). In most cases, though, we use the NIST defined curves. These are SECP256R1, SECP384R1, and SECP521R1, but an also use SECP224R1 and SECP192R1. SECP256R1 has 256-bit (x,y) points, and where the private key is a 256-bit scalar value (\(a\)) and which gives a public key point of \(a.G\). In this case, \(G\) is the base point of the curve. This page generates a range of ECC 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
With Elliptic Curve Cryptography (ECC) we can use a Weierstrass curve form of the form of \(y^2=x^3+ax+b \pmod p\). Bitcoin and Ethereum use secp256k1 and which has the form of \(y^2=x^3 + 7 \pmod p\). In most cases, though, we use the NIST defined curves. These are SECP256R1, SECP384R1, and SECP521R1, but an also use SECP224R1 and SECP192R1. SECP256R1 has 256-bit (x,y) points, and where the private key is a 256-bit scalar value (\(a\)) and which gives a public key point of:
\(a.G\)
In this case, \(G\) is the base point of the curve. This page generates a range of ECC 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. We can generate a 256-bit ECC key with:
ssh-keygen -t ecdsa -b 256 -C "[email protected]"
and which will generate an secp256r1 key pair. We typically store the private key in the ./ssh folder, and which contains a public key in the form:
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLvG4dI8fFcCNleBEia9g9v+uYDtTJ/7ueC7/JPANAFL3NrDmk79OPhd93yo3A18sBzVJeEaiYjueFJ2WS/cudk=
The private key typically has a PEM form (PKCS8):
-----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/MdaLrARTQqAsvlA EyrCeHufU5GWK3zhEVr1GvQOuoyhRANCAARAtmZP1go2YQCRgt+BxKwEhHWGGv1A ZmbGRYIxv8Nnc4zGuwsJiaNS5idpFPtawx+anWrIysm0w0O/AmEDMv7z -----END PRIVATE KEY-----
With ECDSA, 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 ECDSA 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.
For a public key with OpenSSH format we get:
Private key encoding: Encoding.PEM Private key format: PrivateFormat.PKCS8 Public key encoding: Encoding.OpenSSH Public key format: PublicFormat.OpenSSH Curve: secp256r1 Key size: 256 Private key: -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgIEp328M21HGCgd10 9R4IRHYYwkV4q59NpBlNAQtvCyehRANCAASjXasDn1SS4mX9g/cMTnReoFCeFEQI lhCITZHYMRsDHr4wzvbhQ6UWd5MCaVHU3UQrkalCRSBMc1xatD/C5DXA -----END PRIVATE KEY----- Public key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNdqwOfVJLiZf2D9wxOdF6gUJ4URAiWEIhNkdgxGwMevjDO9uFDpRZ3kwJpUdTdRCuRqUJFIExzXFq0P8LkNcA=
Coding
The code we can use is:
from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import ec 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 curve =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 (len(sys.argv)>5): curve=int(sys.argv[5]) 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=ec.generate_private_key(ec.SECP256K1()) if curve==1: key=ec.generate_private_key(ec.SECP256R1()) elif curve==2: key=ec.generate_private_key(ec.SECP384R1()) elif curve==3: key=ec.generate_private_key(ec.SECP521R1()) elif curve==4: key=ec.generate_private_key(ec.SECP224R1()) elif curve==5: key=ec.generate_private_key(ec.SECP192R1()) 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",key.curve.name) print("Key size:\t\t",key.curve.key_size) 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)