1 package keys
2
3 import (
4 "bytes"
5 "crypto"
6 "crypto/rand"
7 "crypto/rsa"
8 "crypto/sha256"
9 "crypto/x509"
10 "encoding/json"
11 "encoding/pem"
12 "errors"
13 "fmt"
14 "io"
15
16 "github.com/theupdateframework/go-tuf/data"
17 )
18
19 func init() {
20 VerifierMap.Store(data.KeyTypeRSASSA_PSS_SHA256, NewRsaVerifier)
21 SignerMap.Store(data.KeyTypeRSASSA_PSS_SHA256, newRsaSigner)
22 }
23
24 func NewRsaVerifier() Verifier {
25 return &rsaVerifier{}
26 }
27
28 func newRsaSigner() Signer {
29 return &rsaSigner{}
30 }
31
32 type rsaVerifier struct {
33 PublicKey *PKIXPublicKey `json:"public"`
34 rsaKey *rsa.PublicKey
35 key *data.PublicKey
36 }
37
38 func (p *rsaVerifier) Public() string {
39
40 r, err := x509.MarshalPKIXPublicKey(p.rsaKey)
41 if err != nil {
42
43
44 panic(err)
45 }
46 return string(r)
47 }
48
49 func (p *rsaVerifier) Verify(msg, sigBytes []byte) error {
50 hash := sha256.Sum256(msg)
51
52 return rsa.VerifyPSS(p.rsaKey, crypto.SHA256, hash[:], sigBytes, &rsa.PSSOptions{})
53 }
54
55 func (p *rsaVerifier) MarshalPublicKey() *data.PublicKey {
56 return p.key
57 }
58
59 func (p *rsaVerifier) UnmarshalPublicKey(key *data.PublicKey) error {
60
61 dec := json.NewDecoder(io.LimitReader(bytes.NewReader(key.Value), MaxJSONKeySize))
62
63
64 if err := dec.Decode(p); err != nil {
65 if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
66 return fmt.Errorf("tuf: the public key is truncated or too large: %w", err)
67 }
68 return err
69 }
70
71 rsaKey, ok := p.PublicKey.PublicKey.(*rsa.PublicKey)
72 if !ok {
73 return fmt.Errorf("invalid public key")
74 }
75
76 if _, err := x509.MarshalPKIXPublicKey(rsaKey); err != nil {
77 return fmt.Errorf("marshalling to PKIX key: invalid public key")
78 }
79
80 p.rsaKey = rsaKey
81 p.key = key
82 return nil
83 }
84
85 type rsaSigner struct {
86 *rsa.PrivateKey
87 }
88
89 type rsaPrivateKeyValue struct {
90 Private string `json:"private"`
91 Public *PKIXPublicKey `json:"public"`
92 }
93
94 func (s *rsaSigner) PublicData() *data.PublicKey {
95 keyValBytes, _ := json.Marshal(rsaVerifier{PublicKey: &PKIXPublicKey{PublicKey: s.Public()}})
96 return &data.PublicKey{
97 Type: data.KeyTypeRSASSA_PSS_SHA256,
98 Scheme: data.KeySchemeRSASSA_PSS_SHA256,
99 Algorithms: data.HashAlgorithms,
100 Value: keyValBytes,
101 }
102 }
103
104 func (s *rsaSigner) SignMessage(message []byte) ([]byte, error) {
105 hash := sha256.Sum256(message)
106 return rsa.SignPSS(rand.Reader, s.PrivateKey, crypto.SHA256, hash[:], &rsa.PSSOptions{})
107 }
108
109 func (s *rsaSigner) ContainsID(id string) bool {
110 return s.PublicData().ContainsID(id)
111 }
112
113 func (s *rsaSigner) MarshalPrivateKey() (*data.PrivateKey, error) {
114 priv := x509.MarshalPKCS1PrivateKey(s.PrivateKey)
115 pemKey := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: priv})
116 val, err := json.Marshal(rsaPrivateKeyValue{
117 Private: string(pemKey),
118 Public: &PKIXPublicKey{PublicKey: s.Public()},
119 })
120 if err != nil {
121 return nil, err
122 }
123 return &data.PrivateKey{
124 Type: data.KeyTypeRSASSA_PSS_SHA256,
125 Scheme: data.KeySchemeRSASSA_PSS_SHA256,
126 Algorithms: data.HashAlgorithms,
127 Value: val,
128 }, nil
129 }
130
131 func (s *rsaSigner) UnmarshalPrivateKey(key *data.PrivateKey) error {
132 val := rsaPrivateKeyValue{}
133 if err := json.Unmarshal(key.Value, &val); err != nil {
134 return err
135 }
136 block, _ := pem.Decode([]byte(val.Private))
137 if block == nil {
138 return errors.New("invalid PEM value")
139 }
140 if block.Type != "RSA PRIVATE KEY" {
141 return fmt.Errorf("invalid block type: %s", block.Type)
142 }
143 k, err := x509.ParsePKCS1PrivateKey(block.Bytes)
144 if err != nil {
145 return err
146 }
147 if _, err := json.Marshal(rsaVerifier{
148 PublicKey: &PKIXPublicKey{PublicKey: k.Public()}}); err != nil {
149 return fmt.Errorf("invalid public key: %s", err)
150 }
151
152 s.PrivateKey = k
153 return nil
154 }
155
156 func GenerateRsaKey() (*rsaSigner, error) {
157 privkey, err := rsa.GenerateKey(rand.Reader, 2048)
158 if err != nil {
159 return nil, err
160 }
161 return &rsaSigner{privkey}, nil
162 }
163
View as plain text