1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
package sign
import (
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"io/ioutil"
"os"
)
// LoadPEMPrivKeyFile reads a PEM encoded RSA private key from the file name.
// A new RSA private key will be returned if no error.
func LoadPEMPrivKeyFile(name string) (key *rsa.PrivateKey, err error) {
file, err := os.Open(name)
if err != nil {
return nil, err
}
defer func() {
closeErr := file.Close()
if err == nil {
err = closeErr
} else if closeErr != nil {
err = fmt.Errorf("close error: %v, original error: %w", closeErr, err)
}
}()
return LoadPEMPrivKey(file)
}
// LoadPEMPrivKey reads a PEM encoded RSA private key from the io.Reader.
// A new RSA private key will be returned if no error.
func LoadPEMPrivKey(reader io.Reader) (*rsa.PrivateKey, error) {
block, err := loadPem(reader)
if err != nil {
return nil, err
}
return x509.ParsePKCS1PrivateKey(block.Bytes)
}
// LoadEncryptedPEMPrivKey decrypts the PEM encoded private key using the
// password provided returning a RSA private key. If the PEM data is invalid,
// or unable to decrypt an error will be returned.
//
// Deprecated: RFC 1423 PEM encryption is insecure. Callers using encrypted
// keys should instead decrypt that payload externally and pass it to
// [LoadPEMPrivKey].
func LoadEncryptedPEMPrivKey(reader io.Reader, password []byte) (*rsa.PrivateKey, error) {
block, err := loadPem(reader)
if err != nil {
return nil, err
}
decryptedBlock, err := x509.DecryptPEMBlock(block, password)
if err != nil {
return nil, err
}
return x509.ParsePKCS1PrivateKey(decryptedBlock)
}
// LoadPEMPrivKeyPKCS8 reads a PEM-encoded RSA private key in PKCS8 format from
// the given reader.
//
// x509.ParsePKCS8PrivateKey can return multiple key types and this API does
// not discern between them. Callers in need of the underlying value must
// obtain it via type assertion:
//
// key, err := LoadPEMPrivKeyPKCS8(r)
// if err != nil { /* ... */ }
//
// switch key.(type) {
// case *rsa.PrivateKey:
// // ...
// case *ecdsa.PrivateKey:
// // ...
// case ed25519.PrivateKey:
// // ...
// default:
// panic("unrecognized private key type")
// }
//
// See aforementioned API docs for a full list of possible key types.
//
// If calling code can opaquely handle the returned key as a crypto.Signer, use
// [LoadPEMPrivKeyPKCS8AsSigner] instead.
func LoadPEMPrivKeyPKCS8(reader io.Reader) (interface{}, error) {
block, err := loadPem(reader)
if err != nil {
return nil, fmt.Errorf("load pem: %v", err)
}
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("parse pkcs8 key: %v", err)
}
return key, nil
}
var (
_ crypto.Signer = (*rsa.PrivateKey)(nil)
_ crypto.Signer = (*ecdsa.PrivateKey)(nil)
_ crypto.Signer = (ed25519.PrivateKey)(nil)
)
// LoadPEMPrivKeyPKCS8AsSigner wraps [LoadPEMPrivKeyPKCS8] to expect a crypto.Signer.
func LoadPEMPrivKeyPKCS8AsSigner(reader io.Reader) (crypto.Signer, error) {
key, err := LoadPEMPrivKeyPKCS8(reader)
if err != nil {
return nil, fmt.Errorf("load key: %v", err)
}
signer, ok := key.(crypto.Signer)
if !ok {
return nil, fmt.Errorf("key of type %T is not a crypto.Signer", key)
}
return signer, nil
}
func loadPem(reader io.Reader) (*pem.Block, error) {
b, err := ioutil.ReadAll(reader)
if err != nil {
return nil, err
}
block, _ := pem.Decode(b)
if block == nil {
// pem.Decode will set block to nil if there is no PEM data in the input
// the second parameter will contain the provided bytes that failed
// to be decoded.
return nil, fmt.Errorf("no valid PEM data provided")
}
return block, nil
}
|