1 package keys
2
3 import (
4 "bytes"
5 "crypto"
6 "crypto/ed25519"
7 "crypto/rand"
8 "crypto/subtle"
9 "encoding/json"
10 "errors"
11 "fmt"
12 "io"
13
14 "github.com/theupdateframework/go-tuf/data"
15 )
16
17 func init() {
18 SignerMap.Store(data.KeyTypeEd25519, NewEd25519Signer)
19 VerifierMap.Store(data.KeyTypeEd25519, NewEd25519Verifier)
20 }
21
22 func NewEd25519Signer() Signer {
23 return &ed25519Signer{}
24 }
25
26 func NewEd25519Verifier() Verifier {
27 return &ed25519Verifier{}
28 }
29
30 type ed25519Verifier struct {
31 PublicKey data.HexBytes `json:"public"`
32 key *data.PublicKey
33 }
34
35 func (e *ed25519Verifier) Public() string {
36 return string(e.PublicKey)
37 }
38
39 func (e *ed25519Verifier) Verify(msg, sig []byte) error {
40 if !ed25519.Verify([]byte(e.PublicKey), msg, sig) {
41 return errors.New("tuf: ed25519 signature verification failed")
42 }
43 return nil
44 }
45
46 func (e *ed25519Verifier) MarshalPublicKey() *data.PublicKey {
47 return e.key
48 }
49
50 func (e *ed25519Verifier) UnmarshalPublicKey(key *data.PublicKey) error {
51 e.key = key
52
53
54 dec := json.NewDecoder(io.LimitReader(bytes.NewReader(key.Value), MaxJSONKeySize))
55
56
57 if err := dec.Decode(e); err != nil {
58 if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
59 return fmt.Errorf("tuf: the public key is truncated or too large: %w", err)
60 }
61 return err
62 }
63 if n := len(e.PublicKey); n != ed25519.PublicKeySize {
64 return fmt.Errorf("tuf: unexpected public key length for ed25519 key, expected %d, got %d", ed25519.PublicKeySize, n)
65 }
66 return nil
67 }
68
69 type Ed25519PrivateKeyValue struct {
70 Public data.HexBytes `json:"public"`
71 Private data.HexBytes `json:"private"`
72 }
73
74 type ed25519Signer struct {
75 ed25519.PrivateKey
76 }
77
78 func GenerateEd25519Key() (*ed25519Signer, error) {
79 _, private, err := ed25519.GenerateKey(rand.Reader)
80 if err != nil {
81 return nil, err
82 }
83 if err != nil {
84 return nil, err
85 }
86 return &ed25519Signer{
87 PrivateKey: ed25519.PrivateKey(data.HexBytes(private)),
88 }, nil
89 }
90
91 func NewEd25519SignerFromKey(keyValue Ed25519PrivateKeyValue) *ed25519Signer {
92 return &ed25519Signer{
93 PrivateKey: ed25519.PrivateKey(data.HexBytes(keyValue.Private)),
94 }
95 }
96
97 func (e *ed25519Signer) SignMessage(message []byte) ([]byte, error) {
98 return e.Sign(rand.Reader, message, crypto.Hash(0))
99 }
100
101 func (e *ed25519Signer) MarshalPrivateKey() (*data.PrivateKey, error) {
102 valueBytes, err := json.Marshal(Ed25519PrivateKeyValue{
103 Public: data.HexBytes([]byte(e.PrivateKey.Public().(ed25519.PublicKey))),
104 Private: data.HexBytes(e.PrivateKey),
105 })
106 if err != nil {
107 return nil, err
108 }
109 return &data.PrivateKey{
110 Type: data.KeyTypeEd25519,
111 Scheme: data.KeySchemeEd25519,
112 Algorithms: data.HashAlgorithms,
113 Value: valueBytes,
114 }, nil
115 }
116
117 func (e *ed25519Signer) UnmarshalPrivateKey(key *data.PrivateKey) error {
118 keyValue := &Ed25519PrivateKeyValue{}
119
120
121 dec := json.NewDecoder(io.LimitReader(bytes.NewReader(key.Value), MaxJSONKeySize))
122
123
124 if err := dec.Decode(keyValue); err != nil {
125 if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
126 return fmt.Errorf("tuf: the private key is truncated or too large: %w", err)
127 }
128 }
129
130
131 if n := len(keyValue.Private); n != ed25519.PrivateKeySize {
132 return fmt.Errorf("tuf: invalid ed25519 private key length, expected %d, got %d", ed25519.PrivateKeySize, n)
133 }
134
135
136 pub, _, err := ed25519.GenerateKey(bytes.NewReader(keyValue.Private))
137 if err != nil {
138 return fmt.Errorf("tuf: unable to derive public key from private key: %w", err)
139 }
140
141
142 if subtle.ConstantTimeCompare(keyValue.Public, pub) != 1 {
143 return errors.New("tuf: public and private keys don't match")
144 }
145
146
147 *e = ed25519Signer{
148 PrivateKey: ed25519.PrivateKey(data.HexBytes(keyValue.Private)),
149 }
150 return nil
151 }
152
153 func (e *ed25519Signer) PublicData() *data.PublicKey {
154 keyValBytes, _ := json.Marshal(ed25519Verifier{PublicKey: []byte(e.PrivateKey.Public().(ed25519.PublicKey))})
155 return &data.PublicKey{
156 Type: data.KeyTypeEd25519,
157 Scheme: data.KeySchemeEd25519,
158 Algorithms: data.HashAlgorithms,
159 Value: keyValBytes,
160 }
161 }
162
View as plain text