Generating an RSA key with Erlang

erlang cryptography

I’m currently doing something that needs RSA keys, so here are some Erlang snippets showing how to create one.

Generating an RSA key

Size = 2048,  % in bits
Exp = 65537,  % standard RSA exponent
RSAPrivateKey = public_key:generate_key({rsa, Size, Exp}).

This is the equivalent of openssl genrsa (using the default settings). You can be explicit: openssl genrsa -f4 2048.

Writing the private key as PEM (PKCS#1)

RSAPrivateKeyPEM = public_key:pem_encode([public_key:pem_entry_encode('RSAPrivateKey', RSAPrivateKey)]).
file:write_file("my.key", RSAPrivateKeyPEM).
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA15Spy6QYxqlG25i1uygrU5AY3xTRX8Bq/9EspqCht9iAEUG5
...
1Q033aDFz7D6XO8yfl3bqNsk+BdpApPSqw3YrH5iYowkpeZ/2aR9rkI=
-----END RSA PRIVATE KEY-----

You can display the key with openssl:

openssl rsa -in my.key -text -noout

Deriving the public key

For RSA, it’s pretty simple; you just copy the modulus and exponent into an RSAPublicKey record:

rr(public_key).   % if in the REPL, otherwise -include_lib("public_key/include/public_key.hrl").
#'RSAPrivateKey'{modulus = Modulus, publicExponent = PublicExponent} = RSAPrivateKey.
RSAPublicKey = #'RSAPublicKey'{modulus = Modulus, publicExponent = PublicExponent}.

Writing the public key as PEM (PKCS#1)

RSAPublicKeyPEM = public_key:pem_encode([public_key:pem_entry_encode('RSAPublicKey', RSAPublicKey)]).
file:write_file("my.pub", RSAPublicKeyPEM).
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA3hhgKg0aXwFMKe5dTTlmpnnQnLtUFy0iwwGFyjI8JdGtCgAMNoZB
...
IxbtysiR5Z8uES9jFMW5IMuciorjIhThuQIDAQAB
-----END RSA PUBLIC KEY-----

Writing the public key as PEM (PKCS#8)

openssl — as far as I can tell — doesn’t want to load public keys in this format, so we need to use PKCS#8 instead. To do this, we wrap the key in a SubjectPublicKeyInfo record:

SubjectPublicKeyInfo = #'SubjectPublicKeyInfo'{
  algorithm = #'AlgorithmIdentifier'{algorithm = {1,2,840,113549,1,1,1}, parameters = <<5,0>>},
  subjectPublicKey = public_key:der_encode('RSAPublicKey', RSAPublicKey)}.
file:write_file("my.pub",
  public_key:pem_encode([public_key:pem_entry_encode('SubjectPublicKeyInfo', SubjectPublicKeyInfo)])).

The {1,2,840,113549,1,1,1} refers to the rsaEncryption OID; see http://www.oid-info.com/get/1.2.840.113549.1.1.1. Normally, you’d use the ?'rsaEncryption' macro, but that doesn’t work in the REPL.

The <<5,0>> is a NULL; the algorithm takes no parameters.

That writes a file as follows:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA15Spy6QYxqlG25i1uygr
...
6QIDAQAB
-----END PUBLIC KEY-----

PKCS#1 files have -----BEGIN RSA PUBLIC KEY-----; PKCS#8 files have -----BEGIN PUBLIC KEY-----.

Obviously, substitute PRIVATE, PUBLIC, BEGIN, END as appropriate.

And now we can load that with openssl:

openssl rsa -pubin -in my.pub -text -noout