openssl generate RSA or EC public key pair

Main picture of the post: openssl generate RSA or EC public key pair

OpenSSL it’s a versatile tool for cryptographic operations ranging from hash functions, encryption, digital signature and so on.

This post will provide command examples to run the tool for generating a key pair for asymmetric cryptography with the well known algorithms RSA (Rivest, Shamir y Adleman) and EC (Elliptic Curve).

Create only a new RSA key pair with openssl

If you only need a key pair without generating a certificate request, then you can start with the following command:

$ openssl genrsa -out private_key.pem 4096
Generating RSA private key, 4096 bit long modulus
................................................................................++
...............................................................................................................................++
e is 65537 (0x10001)

This command will generate the a RSA private key of the key pair with a key length of 4096 bits in clear text without encryption.

In order to obtain also the public key for this private key, the following command will help you to do so:

$ openssl rsa -in private_key.pem -pubout -out public_key.pem
writing RSA key

Either the private key and the public key is generated in PEM (Privacy Enhanced Mail) format, which is equivalent to encoding a DER (Distinguished Encoding Rules) format in base 64. This is a sample of how both generated file looks:

$ head -n3 private_key.pem public_key.pem 
==> private_key.pem <==
-----BEGIN RSA PRIVATE KEY-----
MIIJKgIBAAKCAgEA3NI64BRAhvq4H5bmj4Omc70kt2skUsH3GC5wf7FryWJmFgct
st9oTZkRnFkI2hYZUTBpI38YUQWpfRnngfnujAv4unp9/mr7ntApspRvY87v7Vdl

==> public_key.pem <==
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3NI64BRAhvq4H5bmj4Om
c70kt2skUsH3GC5wf7FryWJmFgctst9oTZkRnFkI2hYZUTBpI38YUQWpfRnngfnu

The security issue of generating the private key in plain text is that it doesn’t have an appropriate protection against unauthorised access. Despite you can set the OS permissions and user access control to protect the key, it doesn’t cover the use case that an authorised third party, who has access to your system for administration purposes with root privileges, can view your private key, which should be only readable by the owner of it. However, openssl provides an option to protect the private key with encryption and it could only be decrypted issuing a correct password. Check the next section to increase the security of your private key.

Create a new RSA key pair protected by password

It is possible to create a private key encrypted so it could only be usable if a correct password is provided. The command to do so it’s very similar, but has an additional option to set the encryption algorithm to protect the key:

$ openssl genrsa -aes256 -out private_key.pem 4096
Generating RSA private key, 4096 bit long modulus
...............................................................................................................................................................................................................++
.....................................++
e is 65537 (0x10001)
Enter pass phrase for private_key.pem:
Verifying - Enter pass phrase for private_key.pem:

The resulting file it will look similar to the unencrypted private key but with the encryption algorithm information:

$ head -n6 private_key.pem 
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,6C29B534697D20DF978FA429492B2C3D

BkSiQ4q16Q55v9ezJ6M3NWyt3iR0WwRC80kTIwUsI/dAujT30900CnlcVXwmJhgh
UccUvDhfEp9gDy0mL0P9ZuXOnUPY/CGemJJveVaSSkyB3SvrkqFvS9mDAP4FALls

To test the password protection, the next command will perform a check prompting for a password. If the password is not correct then openssl will complain that could not load the private key:

$ openssl rsa -check -in private_key.pem 
Enter pass phrase for private_key.pem:
unable to load Private Key
140061221283728:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:623:
140061221283728:error:0906A065:PEM routines:PEM_do_header:bad decrypt:pem_lib.c:488:

But if the password is correct then the command will successfully load the key and print the plain text private key:

$ openssl rsa -check -in private_key.pem 
Enter pass phrase for private_key.pem:
RSA key ok
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MIIJJwIBAAKCAgEA72KLtTlqCfjVQOTFqU3ULcErnoIoCLdlHzs4rBW7Zx6IjMhv
PDop2fZ14Q+XUM2L2PCJBx+XZUM9jX+JqnyEgZS+Tc1L1dblvja2UeYAK9gNcuay
GfNzkIxNPg0q5WtsizXT+nG75Vy3/bF7FHhrIkJOSDnR9OPcwR/rrUzs9gQqyZ9k
...

To get the public key from this encrypted private key, you need to execute the same command stated previously but it will prompt for the password:

$ openssl rsa -in private_key.pem -pubout -out public_key.pem
Enter pass phrase for private_key.pem:
writing RSA key

By encrypting the private key you ensure an additional security control in place to protect this sensitive information.

Nevertheless, each time that the key is used or loaded, it needs the password in order to access correctly the private key. This is something you need to consider when it comes to automate infrastructure deployment or any DevOps tasks, where the automation is the key from end to end, and it could loose it’s essence if at some deployment step is paused due to any password prompt to access a private key.

Create only a new EC key pair with openssl

Another asymmetric encryption algorithm that could be used is the EC (Elliptic Curve) which provides the same level of cryptography security as RSA but with smaller key sizes. In EC a 256 key size provides the same cryptography strength as RSA 3072 of key length.

The following command line can be used to generate a prime256v1 EC key pair:

$ openssl ecparam -genkey -name prime256v1 -out ec256_private_key.pem

Then, compute the public key using the private key generated:

$ openssl ec -in ec256_private_key.pem -pubout -out ec256_public_key.pem
read EC key
writing EC key

Checking the key pair content:

$ head ec256_private_key.pem ec256_public_key.pem
==> ec256_private_key.pem <==
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIDB7BkwiZ6GL4tKnK2nxrgq2+BByHrIGdycpAD81R13zoAoGCCqGSM49
AwEHoUQDQgAEkelf9GJB/8ayHJcEIUNJsVrTHpBhf+ZOFya8qtran6bv4Qa75Aab
+pG4ukL8px5ujkkTAe2goFMOkFZUcsS5ew==
-----END EC PRIVATE KEY-----

==> ec256_public_key.pem <==
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkelf9GJB/8ayHJcEIUNJsVrTHpBh
f+ZOFya8qtran6bv4Qa75Aab+pG4ukL8px5ujkkTAe2goFMOkFZUcsS5ew==
-----END PUBLIC KEY-----

This EC key material are generated in plain text, so let’s check the next section to protect it with encryption.

Generate a EC key pair password protected

The objective is to generate a EC key pair with encryption protection accessible only if a correct password is provided. The outcome should be similar as protecting a RSA key pair with encryption but using a EC key pair:

$ openssl ecparam -genkey -name prime256v1 | openssl ec -aes256 -out ec256_private_key.pem
read EC key
writing EC key
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

In the EC case, it’s a combination of 2 commands in order to generate the key pair and then encrypt it with password. These can be done separately but, bear in mind to clean any sensitive information in plain text written in disk after completing the task.

The result file of the above command will look like this:

$ head ec256_private_key.pem
-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,BE07E8C72CF3E18C5EB0CE038B1C54E3

bTx96K0mGSs91cX6e/PxiR1C3K1lPlmqPQh5b/TuMjG0my6piZ2gNm3uZeMRDgE5
+l0wHvgqJ+2CKK0VIJoduHHObOcf/jnIgPr6ZOsvq0ZUD1YHq/3F0HNi38gC4b3N
6pHxarpzhe9He0WoW+d/JTlieh7pt0SyY+uxB81Axjw=
-----END EC PRIVATE KEY-----

If the public key needs to be generated from the encrypted EC private key, then execute the next command and provide the password used to encrypt it:

$ openssl ec -in ec256_private_key.pem -pubout -out ec256_public_key.pem
read EC key
Enter PEM pass phrase:
writing EC key

Use specific random file for generating a RSA or EC key pair with openssl

Another important aspect when generating key material is to have a good level of entropy to increase the unpredictability of the random number used to generate the keys. So, in order to force openssl to use an specific random file like /dev/random you can do it by adding the option -rand /dev/random to the RSA and EC key generation commands:

$ openssl genrsa -rand /dev/random -aes256 -out private_key.pem 4096
2048 semi-random bytes loaded
Generating RSA private key, 4096 bit long modulus
................................................++
.............++
e is 65537 (0x10001)
Enter pass phrase for private_key.pem:
Verifying - Enter pass phrase for private_key.pem:

$ openssl ecparam -genkey -rand /dev/random -name prime256v1 | openssl ec -aes256 -out ec256_private_key.pem
read EC key
2048 semi-random bytes loaded
writing EC key
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

Both commands above can use other random files like /dev/urandom as well.

Convert a PEM RSA or EC key pair to DER format with openssl

If you need the key pair in DER format instead of PEM format, you can use openssl to make the format conversion. In the case of RSA key pair:

$ openssl rsa -inform pem -in private_key.pem -outform der -out private_key.der
writing RSA key

To convert a EC key pair to DER format:

$ openssl ec -inform pem -in ec256_private_key.pem -outform der -out ec256_private_key.der
read EC key
writing EC key

The above commands can be executed in the same way for the public keys.