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 144 145 146
|
package signerverifier
import (
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"encoding/hex"
"errors"
"strings"
)
var KeyIDHashAlgorithms = []string{"sha256", "sha512"}
var (
ErrNotPrivateKey = errors.New("loaded key is not a private key")
ErrSignatureVerificationFailed = errors.New("failed to verify signature")
ErrUnknownKeyType = errors.New("unknown key type")
ErrInvalidThreshold = errors.New("threshold is either less than 1 or greater than number of provided public keys")
ErrInvalidKey = errors.New("key object has no value")
ErrInvalidPEM = errors.New("unable to parse PEM block")
)
const (
PublicKeyPEM = "PUBLIC KEY"
PrivateKeyPEM = "PRIVATE KEY"
)
type SSLibKey struct {
KeyIDHashAlgorithms []string `json:"keyid_hash_algorithms"`
KeyType string `json:"keytype"`
KeyVal KeyVal `json:"keyval"`
Scheme string `json:"scheme"`
KeyID string `json:"keyid"`
}
type KeyVal struct {
Private string `json:"private,omitempty"`
Public string `json:"public,omitempty"`
Certificate string `json:"certificate,omitempty"`
Identity string `json:"identity,omitempty"`
Issuer string `json:"issuer,omitempty"`
}
// LoadKey returns an SSLibKey object when provided a PEM encoded key.
// Currently, RSA, ED25519, and ECDSA keys are supported.
func LoadKey(keyBytes []byte) (*SSLibKey, error) {
pemBlock, rawKey, err := decodeAndParsePEM(keyBytes)
if err != nil {
return nil, err
}
var key *SSLibKey
switch k := rawKey.(type) {
case *rsa.PublicKey:
pubKeyBytes, err := x509.MarshalPKIXPublicKey(k)
if err != nil {
return nil, err
}
key = &SSLibKey{
KeyIDHashAlgorithms: KeyIDHashAlgorithms,
KeyType: RSAKeyType,
KeyVal: KeyVal{
Public: strings.TrimSpace(string(generatePEMBlock(pubKeyBytes, PublicKeyPEM))),
},
Scheme: RSAKeyScheme,
}
case *rsa.PrivateKey:
pubKeyBytes, err := x509.MarshalPKIXPublicKey(k.Public())
if err != nil {
return nil, err
}
key = &SSLibKey{
KeyIDHashAlgorithms: KeyIDHashAlgorithms,
KeyType: RSAKeyType,
KeyVal: KeyVal{
Public: strings.TrimSpace(string(generatePEMBlock(pubKeyBytes, PublicKeyPEM))),
Private: strings.TrimSpace(string(generatePEMBlock(pemBlock.Bytes, pemBlock.Type))),
},
Scheme: RSAKeyScheme,
}
case ed25519.PublicKey:
key = &SSLibKey{
KeyIDHashAlgorithms: KeyIDHashAlgorithms,
KeyType: ED25519KeyType,
KeyVal: KeyVal{
Public: strings.TrimSpace(hex.EncodeToString(k)),
},
Scheme: ED25519KeyType,
}
case ed25519.PrivateKey:
pubKeyBytes := k.Public()
key = &SSLibKey{
KeyIDHashAlgorithms: KeyIDHashAlgorithms,
KeyType: ED25519KeyType,
KeyVal: KeyVal{
Public: strings.TrimSpace(hex.EncodeToString(pubKeyBytes.(ed25519.PublicKey))),
Private: strings.TrimSpace(hex.EncodeToString(k)),
},
Scheme: ED25519KeyType,
}
case *ecdsa.PublicKey:
pubKeyBytes, err := x509.MarshalPKIXPublicKey(k)
if err != nil {
return nil, err
}
key = &SSLibKey{
KeyIDHashAlgorithms: KeyIDHashAlgorithms,
KeyType: ECDSAKeyType,
KeyVal: KeyVal{
Public: strings.TrimSpace(string(generatePEMBlock(pubKeyBytes, PublicKeyPEM))),
},
Scheme: ECDSAKeyScheme,
}
case *ecdsa.PrivateKey:
pubKeyBytes, err := x509.MarshalPKIXPublicKey(k.Public())
if err != nil {
return nil, err
}
key = &SSLibKey{
KeyIDHashAlgorithms: KeyIDHashAlgorithms,
KeyType: ECDSAKeyType,
KeyVal: KeyVal{
Public: strings.TrimSpace(string(generatePEMBlock(pubKeyBytes, PublicKeyPEM))),
Private: strings.TrimSpace(string(generatePEMBlock(pemBlock.Bytes, PrivateKeyPEM))),
},
Scheme: ECDSAKeyScheme,
}
default:
return nil, ErrUnknownKeyType
}
keyID, err := calculateKeyID(key)
if err != nil {
return nil, err
}
key.KeyID = keyID
return key, nil
}
|