1 package signerverifier
2
3 import (
4 "context"
5 "crypto"
6 "crypto/rand"
7 "crypto/rsa"
8 "crypto/sha256"
9 "crypto/x509"
10 "fmt"
11 "os"
12 "strings"
13 )
14
15 const (
16 RSAKeyType = "rsa"
17 RSAKeyScheme = "rsassa-pss-sha256"
18 RSAPrivateKeyPEM = "RSA PRIVATE KEY"
19 )
20
21
22
23 type RSAPSSSignerVerifier struct {
24 keyID string
25 private *rsa.PrivateKey
26 public *rsa.PublicKey
27 }
28
29
30
31 func NewRSAPSSSignerVerifierFromSSLibKey(key *SSLibKey) (*RSAPSSSignerVerifier, error) {
32 if len(key.KeyVal.Public) == 0 {
33 return nil, ErrInvalidKey
34 }
35
36 _, publicParsedKey, err := decodeAndParsePEM([]byte(key.KeyVal.Public))
37 if err != nil {
38 return nil, fmt.Errorf("unable to create RSA-PSS signerverifier: %w", err)
39 }
40
41 if len(key.KeyVal.Private) > 0 {
42 _, privateParsedKey, err := decodeAndParsePEM([]byte(key.KeyVal.Private))
43 if err != nil {
44 return nil, fmt.Errorf("unable to create RSA-PSS signerverifier: %w", err)
45 }
46
47 return &RSAPSSSignerVerifier{
48 keyID: key.KeyID,
49 public: publicParsedKey.(*rsa.PublicKey),
50 private: privateParsedKey.(*rsa.PrivateKey),
51 }, nil
52 }
53
54 return &RSAPSSSignerVerifier{
55 keyID: key.KeyID,
56 public: publicParsedKey.(*rsa.PublicKey),
57 private: nil,
58 }, nil
59 }
60
61
62 func (sv *RSAPSSSignerVerifier) Sign(ctx context.Context, data []byte) ([]byte, error) {
63 if sv.private == nil {
64 return nil, ErrNotPrivateKey
65 }
66
67 hashedData := hashBeforeSigning(data, sha256.New())
68
69 return rsa.SignPSS(rand.Reader, sv.private, crypto.SHA256, hashedData, &rsa.PSSOptions{SaltLength: sha256.Size, Hash: crypto.SHA256})
70 }
71
72
73 func (sv *RSAPSSSignerVerifier) Verify(ctx context.Context, data []byte, sig []byte) error {
74 hashedData := hashBeforeSigning(data, sha256.New())
75
76 if err := rsa.VerifyPSS(sv.public, crypto.SHA256, hashedData, sig, &rsa.PSSOptions{SaltLength: sha256.Size, Hash: crypto.SHA256}); err != nil {
77 return ErrSignatureVerificationFailed
78 }
79
80 return nil
81 }
82
83
84
85 func (sv *RSAPSSSignerVerifier) KeyID() (string, error) {
86 return sv.keyID, nil
87 }
88
89
90
91 func (sv *RSAPSSSignerVerifier) Public() crypto.PublicKey {
92 return sv.public
93 }
94
95
96
97 func LoadRSAPSSKeyFromFile(path string) (*SSLibKey, error) {
98 contents, err := os.ReadFile(path)
99 if err != nil {
100 return nil, fmt.Errorf("unable to load RSA key from file: %w", err)
101 }
102
103 return LoadRSAPSSKeyFromBytes(contents)
104 }
105
106
107
108
109 func LoadRSAPSSKeyFromBytes(contents []byte) (*SSLibKey, error) {
110 pemData, keyObj, err := decodeAndParsePEM(contents)
111 if err != nil {
112 return nil, fmt.Errorf("unable to load RSA key from file: %w", err)
113 }
114
115 key := &SSLibKey{
116 KeyType: RSAKeyType,
117 Scheme: RSAKeyScheme,
118 KeyIDHashAlgorithms: KeyIDHashAlgorithms,
119 KeyVal: KeyVal{},
120 }
121
122 pubKeyBytes, err := marshalAndGeneratePEM(keyObj)
123 if err != nil {
124 return nil, fmt.Errorf("unable to load RSA key from file: %w", err)
125 }
126 key.KeyVal.Public = strings.TrimSpace(string(pubKeyBytes))
127
128 if _, ok := keyObj.(*rsa.PrivateKey); ok {
129 key.KeyVal.Private = strings.TrimSpace(string(generatePEMBlock(pemData.Bytes, RSAPrivateKeyPEM)))
130 }
131
132 if len(key.KeyID) == 0 {
133 keyID, err := calculateKeyID(key)
134 if err != nil {
135 return nil, fmt.Errorf("unable to load RSA key from file: %w", err)
136 }
137 key.KeyID = keyID
138 }
139
140 return key, nil
141 }
142
143 func marshalAndGeneratePEM(key interface{}) ([]byte, error) {
144 var pubKeyBytes []byte
145 var err error
146
147 switch k := key.(type) {
148 case *rsa.PublicKey:
149 pubKeyBytes, err = x509.MarshalPKIXPublicKey(k)
150 case *rsa.PrivateKey:
151 pubKeyBytes, err = x509.MarshalPKIXPublicKey(k.Public())
152 default:
153 return nil, fmt.Errorf("unexpected key type: %T", k)
154 }
155
156 if err != nil {
157 return nil, err
158 }
159
160 return generatePEMBlock(pubKeyBytes, PublicKeyPEM), nil
161 }
162
View as plain text