9
openssl genrsa -out $1.rsa $2
openssl rsa -in $1.rsa -pubout > $1.rsa.pub

I'm passing in two arguments to this tiny script, how can I do this using golang? I'm not getting the parsing formats right.

genghisjahn
  • 93
  • 1
  • 4

1 Answers1

18

To generate a RSA key pair and write the private and public keys to separate files, you'll need to do the following:

  1. generate a RSA keypair using rsa.GenerateKey
  2. get the public key component using rsa.PrivateKey.Public
  3. convert the keys to PKCS#1 ASN.1 DER form using x509.MarshalPKCS1PrivateKey and x509.MarshalPKCS1PublicKey respectively
  4. encode into PEM blocks using pem.EncodeToMemory
  5. write out to files

The full set of operations can be seen below, where filename and bitSize are your $1 and $2 arguments respectively.

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/pem"
    "io/ioutil"
)

func main() {
    filename := "key"
    bitSize := 4096

    // Generate RSA key.
    key, err := rsa.GenerateKey(rand.Reader, bitSize)
    if err != nil {
        panic(err)
    }

    // Extract public component.
    pub := key.Public()

    // Encode private key to PKCS#1 ASN.1 PEM.
    keyPEM := pem.EncodeToMemory(
        &pem.Block{
            Type:  "RSA PRIVATE KEY",
            Bytes: x509.MarshalPKCS1PrivateKey(key),
        },
    )

    // Encode public key to PKCS#1 ASN.1 PEM.
    pubPEM := pem.EncodeToMemory(
        &pem.Block{
            Type:  "RSA PUBLIC KEY",
            Bytes: x509.MarshalPKCS1PublicKey(pub.(*rsa.PublicKey)),
        },
    )

    // Write private key to file.
    if err := ioutil.WriteFile(filename+".rsa", keyPEM, 0700); err != nil {
        panic(err)
    }

    // Write public key to file.
    if err := ioutil.WriteFile(filename+".rsa.pub", pubPEM, 0755); err != nil {
        panic(err)
    }
}

This will generate the two following files:

key.rsa:

-----BEGIN RSA PRIVATE KEY-----
MIIJJwIBAAKCAgEAsmJ+97V6zCOQdXDd0pivvgoXynKAHaImVdafXDwN+Eb2xKTg
zjhthm144DZzO9/SllCdyLwhXKBQkgim2S5A4iV5w6/yvChqL72+BrItP0+1tAgY
vt/CcShDtMdSikW13BN3+SGZSP9yrEsdU2KMK6HSGcSxMpki/XW2BbGkdr3gMtpM
...
S8tZZ/gby/k9nG7Pbw55QM8/Jkyvy/lPP94HrE+MuIiTEd9BG4c7CRNIuE6QoCjp
1+NIbqEPJTJMfH57cx8R/stLh2nBGcngjmWz+VWhufzhsOr7Wl8Xd6hf13hm4hWG
y+2pknoTGvw05tiU/eLAbNimtWMOtEdfePzT5NTjV++9kJSr470eyDs2bg==
-----END RSA PRIVATE KEY-----

key.rsa.pub:

-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEAsmJ+97V6zCOQdXDd0pivvgoXynKAHaImVdafXDwN+Eb2xKTgzjht
hm144DZzO9/SllCdyLwhXKBQkgim2S5A4iV5w6/yvChqL72+BrItP0+1tAgYvt/C
...
8Xil1cP/5LxIMa1WGHEG1jzrWJkyaVXHS0JOi3FcI4KPQttut2rWpSi3MtAlmuTx
k/AfM3oNnAUlcjYNa+onSs7GgLhd1A5/EiLGMR304uWKno8HrYQfESsCAwEAAQ==
-----END RSA PUBLIC KEY-----

I recommend you become familiar with the functions linked, their documentation is quite useful. There are also other format options available (eg: PKCS#8 and PKIX) as well as encrypted PEM for the private key.

Marc
  • 19,394
  • 6
  • 47
  • 51
  • Great answer, but for those who are trying to generate AWS CloudFront PublicKey, use `bitSize:=2048`, `x509.MarshalPKIXPublicKey` for public part and `x509.MarshalPKCS8PrivateKey` for private part. – astef Mar 14 '23 at 14:55