Successfully parse private key PEM blocks (#1030)

This commit is contained in:
Matt Holt 2020-01-06 08:52:56 -07:00 committed by Ludovic Fernandez
parent 4f72de468d
commit c7bbf62dd4

View file

@ -3,6 +3,7 @@ package certcrypto
import ( import (
"crypto" "crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
@ -13,6 +14,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"strings"
"time" "time"
"golang.org/x/crypto/ocsp" "golang.org/x/crypto/ocsp"
@ -77,17 +79,35 @@ func ParsePEMBundle(bundle []byte) ([]*x509.Certificate, error) {
return certificates, nil return certificates, nil
} }
// ParsePEMPrivateKey parses a private key from key, which is a PEM block.
// Borrowed from Go standard library, to handle various private key and PEM block types.
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L291-L308
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L238)
func ParsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) { func ParsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) {
keyBlock, _ := pem.Decode(key) keyBlockDER, _ := pem.Decode(key)
switch keyBlock.Type { if keyBlockDER.Type != "PRIVATE KEY" && !strings.HasSuffix(keyBlockDER.Type, " PRIVATE KEY") {
case "RSA PRIVATE KEY": return nil, fmt.Errorf("unknown PEM header %q", keyBlockDER.Type)
return x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
case "EC PRIVATE KEY":
return x509.ParseECPrivateKey(keyBlock.Bytes)
default:
return nil, errors.New("unknown PEM header value")
} }
if key, err := x509.ParsePKCS1PrivateKey(keyBlockDER.Bytes); err == nil {
return key, nil
}
if key, err := x509.ParsePKCS8PrivateKey(keyBlockDER.Bytes); err == nil {
switch key := key.(type) {
case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey:
return key, nil
default:
return nil, fmt.Errorf("found unknown private key type in PKCS#8 wrapping: %T", key)
}
}
if key, err := x509.ParseECPrivateKey(keyBlockDER.Bytes); err == nil {
return key, nil
}
return nil, errors.New("failed to parse private key")
} }
func GeneratePrivateKey(keyType KeyType) (crypto.PrivateKey, error) { func GeneratePrivateKey(keyType KeyType) (crypto.PrivateKey, error) {