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

前端 未结 4 1123
萌比男神i
萌比男神i 2021-01-30 10:13

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.P

相关标签:
4条回答
  • 2021-01-30 10:51

    Since the public key part of your question wasn't answered and I just ran into the same problem and solved it, here it is:

    Note the & in front of the Argument to MarshalPKIXPublicKey

    Priv := rsa.GenerateKey(rand.Reader, 4096)
    
    pubASN1, err := x509.MarshalPKIXPublicKey(&Priv.PublicKey)
    if err != nil {
        // do something about it
    }
    
    pubBytes := pem.EncodeToMemory(&pem.Block{
        Type:  "RSA PUBLIC KEY",
        Bytes: pubASN1,
    })
    
    ioutil.WriteFile("key.pub", pubBytes, 0644)
    

    Relevant reads:

    • MarshalPKIXPublicKey(pub interface{}) ([]byte, error) godoc
    • EncodeToMemory(b *Block) []byte godoc
    • Block godoc

    PS: MarshalPKIXPublicKey also accepts ECDSA keys, ajust the pem header appropriately.

    0 讨论(0)
  • 2021-01-30 10:58

    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.

    0 讨论(0)
  • 2021-01-30 11:00

    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")
        }
    }
    
    0 讨论(0)
  • 2021-01-30 11:06

    FYI: I polished up @David W 's answer and put it in a tiny Go Module. https://github.com/rokk4/gorsapemhelpers

    0 讨论(0)
提交回复
热议问题