This repository has been archived by the owner on Mar 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 102
/
keys.go
106 lines (91 loc) · 2.54 KB
/
keys.go
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
package cosign
import (
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"fmt"
"regexp"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"golang.org/x/crypto/ssh"
)
var (
supportedSSHKeyAlgos = map[string]struct{}{
ssh.KeyAlgoRSA: {},
ssh.KeyAlgoED25519: {},
ssh.KeyAlgoECDSA256: {},
ssh.KeyAlgoECDSA384: {},
ssh.KeyAlgoECDSA521: {},
}
PubkeyPrefixPattern = regexp.MustCompile(`^-----BEGIN (RSA |ED25519 |ECDSA ){0,1}PUBLIC KEY-----\n(.*\n)+-----END (RSA |ED25519 |ECDSA ){0,1}PUBLIC KEY-----\s*$`)
)
func PemEncodeCryptoPublicKey(pubKey crypto.PublicKey) ([]byte, string, error) {
encoded, err := cryptoutils.MarshalPublicKeyToPEM(pubKey)
if err != nil {
return nil, "", err
}
hash := sha256.Sum256(encoded)
fingerprint := hex.EncodeToString(hash[:])
return encoded, fingerprint, nil
}
func PemEncodeSSHPublicKey(key ssh.PublicKey) ([]byte, error) {
pubKey := key.(ssh.CryptoPublicKey).CryptoPublicKey()
pem, _, err := PemEncodeCryptoPublicKey(pubKey)
return pem, err
}
func ParseSSHPublicKey(keystr string) (crypto.PublicKey, error) {
keyBytes, err := base64.StdEncoding.DecodeString(keystr)
if err != nil {
return nil, err
}
parsedKey, err := ssh.ParsePublicKey(keyBytes)
if err != nil {
return nil, err
}
if _, ok := supportedSSHKeyAlgos[parsedKey.Type()]; !ok {
return nil, fmt.Errorf("Unsupported key type '%s'", parsedKey.Type())
}
return parsedKey.(ssh.CryptoPublicKey).CryptoPublicKey(), nil
}
// UnmarshalPEMToPublicKey converts a PEM-encoded byte slice into a crypto.PublicKey
func UnmarshalPEMToPublicKey(pemBytes []byte) (crypto.PublicKey, error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
return nil, fmt.Errorf("PEM decoding failed")
}
switch block.Type {
case "RSA PUBLIC KEY":
return x509.ParsePKCS1PublicKey(block.Bytes)
case "ECDSA PUBLIC KEY":
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
if ecdsaPub, ok := pub.(*ecdsa.PublicKey); ok {
return ecdsaPub, nil
}
case "PUBLIC KEY":
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
switch key := pub.(type) {
case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
return key, nil
}
case "ED25519 PUBLIC KEY":
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
if ed25519Pub, ok := pub.(ed25519.PublicKey); ok {
return ed25519Pub, nil
}
}
return nil, fmt.Errorf("unsupported public key type or format")
}