Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save and load crypto/rsa PrivateKey to and from the disk

I'm using crypto/rsa, and trying to find a way to properly save and load a key. Is there a correct way to create a []byte from an rsa.PrivateKey. If so, is there a way to properly do so for an rsa.PublicKey?

Thank you all very much.

like image 708
Alexander Bauer Avatar asked Nov 25 '12 20:11

Alexander Bauer


2 Answers

You need some sort of format to marshal the key into. One format supported by the Go standard library can be found here: http://golang.org/pkg/crypto/x509/#MarshalPKCS1PrivateKey

func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte 

The inverse function is http://golang.org/pkg/crypto/x509/#ParsePKCS1PrivateKey.

func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) 

However, it is relatively standard to encode the marshaled key into a PEM file.

pemdata := pem.EncodeToMemory(     &pem.Block{         Type: "RSA PRIVATE KEY",         Bytes: x509.MarshalPKCS1PrivateKey(key),     }, ) 

You can find a full example here.

like image 143
Stephen Weinberg Avatar answered Sep 23 '22 22:09

Stephen Weinberg


Here's code snippet that shows the import and export of both public and private keys. It's based on the other answers which were super helpful, as well as copy-pasta from the official docs.

package main  import (     "crypto/rand"     "crypto/rsa"     "crypto/x509"     "encoding/pem"     "errors"     "fmt" )  func GenerateRsaKeyPair() (*rsa.PrivateKey, *rsa.PublicKey) {     privkey, _ := rsa.GenerateKey(rand.Reader, 4096)     return privkey, &privkey.PublicKey }  func ExportRsaPrivateKeyAsPemStr(privkey *rsa.PrivateKey) string {     privkey_bytes := x509.MarshalPKCS1PrivateKey(privkey)     privkey_pem := pem.EncodeToMemory(             &pem.Block{                     Type:  "RSA PRIVATE KEY",                     Bytes: privkey_bytes,             },     )     return string(privkey_pem) }  func ParseRsaPrivateKeyFromPemStr(privPEM string) (*rsa.PrivateKey, error) {     block, _ := pem.Decode([]byte(privPEM))     if block == nil {             return nil, errors.New("failed to parse PEM block containing the key")     }      priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)     if err != nil {             return nil, err     }      return priv, nil }  func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) (string, error) {     pubkey_bytes, err := x509.MarshalPKIXPublicKey(pubkey)     if err != nil {             return "", err     }     pubkey_pem := pem.EncodeToMemory(             &pem.Block{                     Type:  "RSA PUBLIC KEY",                     Bytes: pubkey_bytes,             },     )      return string(pubkey_pem), nil }  func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {     block, _ := pem.Decode([]byte(pubPEM))     if block == nil {             return nil, errors.New("failed to parse PEM block containing the key")     }      pub, err := x509.ParsePKIXPublicKey(block.Bytes)     if err != nil {             return nil, err     }      switch pub := pub.(type) {     case *rsa.PublicKey:             return pub, nil     default:             break // fall through     }     return nil, errors.New("Key type is not RSA") }  func main() {      // Create the keys     priv, pub := GenerateRsaKeyPair()      // Export the keys to pem string     priv_pem := ExportRsaPrivateKeyAsPemStr(priv)     pub_pem, _ := ExportRsaPublicKeyAsPemStr(pub)      // Import the keys from pem string     priv_parsed, _ := ParseRsaPrivateKeyFromPemStr(priv_pem)     pub_parsed, _ := ParseRsaPublicKeyFromPemStr(pub_pem)      // Export the newly imported keys     priv_parsed_pem := ExportRsaPrivateKeyAsPemStr(priv_parsed)     pub_parsed_pem, _ := ExportRsaPublicKeyAsPemStr(pub_parsed)      fmt.Println(priv_parsed_pem)     fmt.Println(pub_parsed_pem)      // Check that the exported/imported keys match the original keys     if priv_pem != priv_parsed_pem || pub_pem != pub_parsed_pem {             fmt.Println("Failure: Export and Import did not result in same Keys")     } else {             fmt.Println("Success")     } } 
like image 36
David W Avatar answered Sep 22 '22 22:09

David W