Generating RSA Private and Public Key Pair in Go Lang?

How to generate a pair of RSA private and public key in Go lang? Go lang has a rich set of standard libraries. Using Go’s standard libraries, we can generate RSA private and Public keys.

The Crypto standard libraries in Go lang

Go lang standard libraries has a rich set of cryptography functions. Here are some that we will use.

crypto/rsa

The package crypto/rsa implements RSA encryption as specified in PKCS #1 and RFC 8017.

The func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) function generates an RSA keypair of the given bit size using the random source random (for example, crypto/rand.Reader, discussed below).

crypto/rand

The var Reader io.Reader struct is a global, shared instance of a cryptographically secure random number generator. On Linux, Reader uses getrandom(2) if available, /dev/urandom otherwise.

crypto/x509

The func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte function converts an RSA private key to PKCS #1, ASN.1 DER form. This kind of key is commonly encoded in PEM blocks of type "RSA PRIVATE KEY".

The func MarshalPKCS1PublicKey(key *rsa.PublicKey) []byte function converts an RSA public key to PKCS #1, ASN.1 DER form. This kind of key is commonly encoded in PEM blocks of type "RSA PUBLIC KEY".

encoding/pem

The func Encode(out io.Writer, b *Block) error function writes the PEM encoding of b to out.

The code to generate RSA private/public key pair in Go lang

With the above libraries available, we can generate a private/public key pair in Go lang by combining the Go lang standard libraries functions in a way like

rsa.GenerateKey() =>
x509.MarshalPKIXPublicKey() =>
pem.Encode()

We store the keys into a pair of files for the RSA private/public keys.

One example Go lang program is as follows.

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/pem"
    "fmt"
    "os"
)

func main() {
    // generate key
    privatekey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        fmt.Printf("Cannot generate RSA key\n")
        os.Exit(1)
    }
    publickey := &privatekey.PublicKey

    // dump private key to file
    var privateKeyBytes []byte = x509.MarshalPKCS1PrivateKey(privatekey)
    privateKeyBlock := &pem.Block{
        Type:  "RSA PRIVATE KEY",
        Bytes: privateKeyBytes,
    }
    privatePem, err := os.Create("private.pem")
    if err != nil {
        fmt.Printf("error when create private.pem: %s \n", err)
        os.Exit(1)
    }
    err = pem.Encode(privatePem, privateKeyBlock)
    if err != nil {
        fmt.Printf("error when encode private pem: %s \n", err)
        os.Exit(1)
    }

    // dump public key to file
    publicKeyBytes, err := x509.MarshalPKIXPublicKey(publickey)
    if err != nil {
        fmt.Printf("error when dumping publickey: %s \n", err)
        os.Exit(1)
    }
    publicKeyBlock := &pem.Block{
        Type:  "PUBLIC KEY",
        Bytes: publicKeyBytes,
    }
    publicPem, err := os.Create("public.pem")
    if err != nil {
        fmt.Printf("error when create public.pem: %s \n", err)
        os.Exit(1)
    }
    err = pem.Encode(publicPem, publicKeyBlock)
    if err != nil {
        fmt.Printf("error when encode public pem: %s \n", err)
        os.Exit(1)
    }
}
Leave a Reply

Your email address will not be published. Required fields are marked *