web-dev-qa-db-fra.com

Enregistrer et charger la clé privée crypto / rsa vers et depuis le disque

J'utilise crypto/rsa, et essayer de trouver un moyen de correctement enregistrer et charger une clé. Existe-t-il un moyen correct de créer un []byte d'un rsa.PrivateKey. Si oui, existe-t-il un moyen de le faire correctement pour un rsa.PublicKey?

Merci beaucoup à tous.

41
Alexander Bauer

Vous avez besoin d'une sorte de format pour rassembler la clé. Un format pris en charge par la bibliothèque standard Go peut être trouvé ici: http://golang.org/pkg/crypto/x509/#MarshalPKCS1PrivateKey

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

La fonction inverse est http://golang.org/pkg/crypto/x509/#ParsePKCS1PrivateKey .

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

Cependant, il est relativement standard d'encoder la clé marshalée dans un fichier PEM.

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

Vous pouvez trouver un exemple complet ici .

61
Stephen Weinberg

Voici un extrait de code qui montre l'importation et l'exportation des clés publiques et privées. Il est basé sur les autres réponses qui ont été très utiles, ainsi que sur les pâtes à copier des documents officiels.

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")
    }
}
26
David W

Puisque la partie clé publique de votre question n'a pas été répondue et que je suis juste tombé sur le même problème et que je l'ai résolu, le voici:

Noter la & devant l'argument à 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)

Lectures pertinentes:

  • MarshalPKIXPublicKey (interface de pub {}) ([] octet, erreur) godoc
  • EncodeToMemory (b * Block) [] octet godoc
  • Bloquer godoc

PS: MarshalPKIXPublicKey accepte également les clés ECDSA, ajustez l'en-tête pem de manière appropriée.

24
tike