How to generate RSA public key using crypto provided Exponent and Modulus

Hey, I am trying to achieve generating an RSA public key, any ideas on how to achieve this in elixir?

I wrote a service that encrypts secrets using asymmetric cryptography and this is the function that generates key pairs.

The keys are encoded in PEM format

with private keys like

-----BEGIN RSA PRIVATE KEY-----
$key
-----END RSA PRIVATE KEY-----

and the public keys

ssh-rsa $key

You might not need the text format encoding and skip it.

 def key_pair(bits \\ 4096) do
    {:RSAPrivateKey, _, modulus, publicExponent, _, _, _, _exponent1, _, _, _otherPrimeInfos} =
      rsa_private_key = :public_key.generate_key({:rsa, bits, 65537})

    rsa_public_key = {:RSAPublicKey, modulus, publicExponent}

    pem_entry = :public_key.pem_entry_encode(:RSAPrivateKey, rsa_private_key)
    private_key = :public_key.pem_encode([pem_entry])

    public_key = :public_key.ssh_encode([{rsa_public_key, []}], :openssh_public_key)

    IO.puts(~s/PUBLIC KEY:\n\n#{public_key}\n\nPRIVATE KEY\n\n#{private_key}/)
  end
5 Likes

Thank you, this worked like a charm, it is sad that erlang docs are a bit shallow on explanations.

Adjusted for OTP 25

  def key_pair(bits \\ 4096) do
    {:RSAPrivateKey, _, modulus, publicExponent, _, _, _, _exponent1, _, _, _otherPrimeInfos} =
      rsa_private_key = :public_key.generate_key({:rsa, bits, 65537})

    rsa_public_key = {:RSAPublicKey, modulus, publicExponent}
    pem_entry = :public_key.pem_entry_encode(:RSAPrivateKey, rsa_private_key)
    private_key = :public_key.pem_encode([pem_entry])
    public_key = :ssh_file.encode([{rsa_public_key, []}], :openssh_key)
    IO.puts(~s/PUBLIC KEY:\n\n#{public_key}\n\nPRIVATE KEY\n\n#{private_key}/)
  end
5 Likes

fwiw: otp 26 (2048 bit key)

defmodule RSAKeyGenerator do
    def generate_rsa_key_pair() do
      {:RSAPrivateKey, _, modulus, publicExponent, _, _, _, _exponent1, _, _, _otherPrimeInfos} =
        rsa_private_key = :public_key.generate_key({:rsa, 2048, 65537})

      rsa_public_key = {:RSAPublicKey, modulus, publicExponent}

      private_key =
        [:public_key.pem_entry_encode(:RSAPrivateKey, rsa_private_key)]
        |> :public_key.pem_encode()

      public_key =
        [:public_key.pem_entry_encode(:RSAPublicKey, rsa_public_key)]
        |> :public_key.pem_encode()

      {private_key, public_key}
    end
end
4 Likes