1 package privatekey
2
3 import (
4 "crypto"
5 "crypto/ecdsa"
6 "crypto/rand"
7 "crypto/rsa"
8 "crypto/sha256"
9 "crypto/x509"
10 "encoding/pem"
11 "errors"
12 "fmt"
13 "hash"
14 "os"
15 )
16
17 func makeVerifyHash() (hash.Hash, error) {
18 randBytes := make([]byte, 32)
19 _, err := rand.Read(randBytes)
20 if err != nil {
21 return nil, err
22 }
23
24 hash := sha256.New()
25 _, err = hash.Write(randBytes)
26 if err != nil {
27 return nil, err
28 }
29 return hash, nil
30 }
31
32
33 func verifyRSA(privKey *rsa.PrivateKey, pubKey *rsa.PublicKey, msgHash hash.Hash) (crypto.Signer, crypto.PublicKey, error) {
34 signatureRSA, err := rsa.SignPSS(rand.Reader, privKey, crypto.SHA256, msgHash.Sum(nil), nil)
35 if err != nil {
36 return nil, nil, fmt.Errorf("failed to sign using the provided RSA private key: %s", err)
37 }
38
39 err = rsa.VerifyPSS(pubKey, crypto.SHA256, msgHash.Sum(nil), signatureRSA, nil)
40 if err != nil {
41 return nil, nil, fmt.Errorf("the provided RSA private key failed signature verification: %s", err)
42 }
43 return privKey, privKey.Public(), nil
44 }
45
46
47 func verifyECDSA(privKey *ecdsa.PrivateKey, pubKey *ecdsa.PublicKey, msgHash hash.Hash) (crypto.Signer, crypto.PublicKey, error) {
48 r, s, err := ecdsa.Sign(rand.Reader, privKey, msgHash.Sum(nil))
49 if err != nil {
50 return nil, nil, fmt.Errorf("failed to sign using the provided ECDSA private key: %s", err)
51 }
52
53 verify := ecdsa.Verify(pubKey, msgHash.Sum(nil), r, s)
54 if !verify {
55 return nil, nil, errors.New("the provided ECDSA private key failed signature verification")
56 }
57 return privKey, privKey.Public(), nil
58 }
59
60
61
62
63
64 func verify(privateKey crypto.Signer) (crypto.Signer, crypto.PublicKey, error) {
65 verifyHash, err := makeVerifyHash()
66 if err != nil {
67 return nil, nil, err
68 }
69
70 switch k := privateKey.(type) {
71 case *rsa.PrivateKey:
72 return verifyRSA(k, &k.PublicKey, verifyHash)
73
74 case *ecdsa.PrivateKey:
75 return verifyECDSA(k, &k.PublicKey, verifyHash)
76
77 default:
78
79 return nil, nil, errors.New("the provided private key could not be asserted to ECDSA or RSA")
80 }
81 }
82
83
84
85
86
87
88
89 func Load(keyPath string) (crypto.Signer, crypto.PublicKey, error) {
90 keyBytes, err := os.ReadFile(keyPath)
91 if err != nil {
92 return nil, nil, fmt.Errorf("could not read key file %q", keyPath)
93 }
94
95 var keyDER *pem.Block
96 for {
97 keyDER, keyBytes = pem.Decode(keyBytes)
98 if keyDER == nil || keyDER.Type != "EC PARAMETERS" {
99 break
100 }
101 }
102 if keyDER == nil {
103 return nil, nil, fmt.Errorf("no PEM formatted block found in %q", keyPath)
104 }
105
106
107 signer, err := x509.ParsePKCS8PrivateKey(keyDER.Bytes)
108 if err == nil {
109 cryptoSigner, ok := signer.(crypto.Signer)
110 if ok {
111 return verify(cryptoSigner)
112 }
113 }
114
115
116 rsaSigner, err := x509.ParsePKCS1PrivateKey(keyDER.Bytes)
117 if err != nil && keyDER.Type == "RSA PRIVATE KEY" {
118 return nil, nil, fmt.Errorf("unable to parse %q as a PKCS#1 RSA private key: %w", keyPath, err)
119 }
120 if err == nil {
121 return verify(rsaSigner)
122 }
123
124
125 ecdsaSigner, err := x509.ParseECPrivateKey(keyDER.Bytes)
126 if err == nil {
127 return verify(ecdsaSigner)
128 }
129 return nil, nil, fmt.Errorf("unable to parse %q as a private key", keyPath)
130 }
131
View as plain text