1
2
3
4
5 package ed25519
6
7 import (
8 "bytes"
9 "crypto/internal/fips140"
10 "crypto/internal/fips140/drbg"
11 "crypto/internal/fips140/edwards25519"
12 "crypto/internal/fips140/sha512"
13 "errors"
14 "strconv"
15 )
16
17
18
19
20 const (
21 seedSize = 32
22 publicKeySize = 32
23 privateKeySize = seedSize + publicKeySize
24 signatureSize = 64
25 sha512Size = 64
26 )
27
28 type PrivateKey struct {
29 seed [seedSize]byte
30 pub [publicKeySize]byte
31 s edwards25519.Scalar
32 prefix [sha512Size / 2]byte
33 }
34
35 func (priv *PrivateKey) Bytes() []byte {
36 k := make([]byte, 0, privateKeySize)
37 k = append(k, priv.seed[:]...)
38 k = append(k, priv.pub[:]...)
39 return k
40 }
41
42 func (priv *PrivateKey) Seed() []byte {
43 seed := priv.seed
44 return seed[:]
45 }
46
47 func (priv *PrivateKey) PublicKey() []byte {
48 pub := priv.pub
49 return pub[:]
50 }
51
52 type PublicKey struct {
53 a edwards25519.Point
54 aBytes [32]byte
55 }
56
57 func (pub *PublicKey) Bytes() []byte {
58 a := pub.aBytes
59 return a[:]
60 }
61
62
63 func GenerateKey() (*PrivateKey, error) {
64 priv := &PrivateKey{}
65 return generateKey(priv)
66 }
67
68 func generateKey(priv *PrivateKey) (*PrivateKey, error) {
69 fips140.RecordApproved()
70 drbg.Read(priv.seed[:])
71 precomputePrivateKey(priv)
72 fipsPCT(priv)
73 return priv, nil
74 }
75
76 func NewPrivateKeyFromSeed(seed []byte) (*PrivateKey, error) {
77 priv := &PrivateKey{}
78 return newPrivateKeyFromSeed(priv, seed)
79 }
80
81 func newPrivateKeyFromSeed(priv *PrivateKey, seed []byte) (*PrivateKey, error) {
82 fips140.RecordApproved()
83 if l := len(seed); l != seedSize {
84 return nil, errors.New("ed25519: bad seed length: " + strconv.Itoa(l))
85 }
86 copy(priv.seed[:], seed)
87 precomputePrivateKey(priv)
88 return priv, nil
89 }
90
91 func precomputePrivateKey(priv *PrivateKey) {
92 hs := sha512.New()
93 hs.Write(priv.seed[:])
94 h := hs.Sum(make([]byte, 0, sha512Size))
95
96 s, err := priv.s.SetBytesWithClamping(h[:32])
97 if err != nil {
98 panic("ed25519: internal error: setting scalar failed")
99 }
100 A := (&edwards25519.Point{}).ScalarBaseMult(s)
101 copy(priv.pub[:], A.Bytes())
102
103 copy(priv.prefix[:], h[32:])
104 }
105
106 func NewPrivateKey(priv []byte) (*PrivateKey, error) {
107 p := &PrivateKey{}
108 return newPrivateKey(p, priv)
109 }
110
111 func newPrivateKey(priv *PrivateKey, privBytes []byte) (*PrivateKey, error) {
112 fips140.RecordApproved()
113 if l := len(privBytes); l != privateKeySize {
114 return nil, errors.New("ed25519: bad private key length: " + strconv.Itoa(l))
115 }
116
117 copy(priv.seed[:], privBytes[:32])
118
119 hs := sha512.New()
120 hs.Write(priv.seed[:])
121 h := hs.Sum(make([]byte, 0, sha512Size))
122
123 if _, err := priv.s.SetBytesWithClamping(h[:32]); err != nil {
124 panic("ed25519: internal error: setting scalar failed")
125 }
126
127
128
129 copy(priv.pub[:], privBytes[32:])
130
131 copy(priv.prefix[:], h[32:])
132
133 return priv, nil
134 }
135
136 func NewPublicKey(pub []byte) (*PublicKey, error) {
137 p := &PublicKey{}
138 return newPublicKey(p, pub)
139 }
140
141 func newPublicKey(pub *PublicKey, pubBytes []byte) (*PublicKey, error) {
142 if l := len(pubBytes); l != publicKeySize {
143 return nil, errors.New("ed25519: bad public key length: " + strconv.Itoa(l))
144 }
145
146 if _, err := pub.a.SetBytes(pubBytes); err != nil {
147 return nil, errors.New("ed25519: bad public key")
148 }
149 copy(pub.aBytes[:], pubBytes)
150 return pub, nil
151 }
152
153
154
155 const (
156
157 domPrefixPure = ""
158
159
160 domPrefixPh = "SigEd25519 no Ed25519 collisions\x01"
161
162
163 domPrefixCtx = "SigEd25519 no Ed25519 collisions\x00"
164 )
165
166 func Sign(priv *PrivateKey, message []byte) []byte {
167
168
169 signature := make([]byte, signatureSize)
170 return sign(signature, priv, message)
171 }
172
173 func sign(signature []byte, priv *PrivateKey, message []byte) []byte {
174 fipsSelfTest()
175 fips140.RecordApproved()
176 return signWithDom(signature, priv, message, domPrefixPure, "")
177 }
178
179 func SignPH(priv *PrivateKey, message []byte, context string) ([]byte, error) {
180
181
182 signature := make([]byte, signatureSize)
183 return signPH(signature, priv, message, context)
184 }
185
186 func signPH(signature []byte, priv *PrivateKey, message []byte, context string) ([]byte, error) {
187 fipsSelfTest()
188 fips140.RecordApproved()
189 if l := len(message); l != sha512Size {
190 return nil, errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l))
191 }
192 if l := len(context); l > 255 {
193 return nil, errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l))
194 }
195 return signWithDom(signature, priv, message, domPrefixPh, context), nil
196 }
197
198 func SignCtx(priv *PrivateKey, message []byte, context string) ([]byte, error) {
199
200
201 signature := make([]byte, signatureSize)
202 return signCtx(signature, priv, message, context)
203 }
204
205 func signCtx(signature []byte, priv *PrivateKey, message []byte, context string) ([]byte, error) {
206 fipsSelfTest()
207
208 fips140.RecordNonApproved()
209
210 if l := len(context); l > 255 {
211 return nil, errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l))
212 }
213 return signWithDom(signature, priv, message, domPrefixCtx, context), nil
214 }
215
216 func signWithDom(signature []byte, priv *PrivateKey, message []byte, domPrefix, context string) []byte {
217 mh := sha512.New()
218 if domPrefix != domPrefixPure {
219 mh.Write([]byte(domPrefix))
220 mh.Write([]byte{byte(len(context))})
221 mh.Write([]byte(context))
222 }
223 mh.Write(priv.prefix[:])
224 mh.Write(message)
225 messageDigest := make([]byte, 0, sha512Size)
226 messageDigest = mh.Sum(messageDigest)
227 r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest)
228 if err != nil {
229 panic("ed25519: internal error: setting scalar failed")
230 }
231
232 R := (&edwards25519.Point{}).ScalarBaseMult(r)
233
234 kh := sha512.New()
235 if domPrefix != domPrefixPure {
236 kh.Write([]byte(domPrefix))
237 kh.Write([]byte{byte(len(context))})
238 kh.Write([]byte(context))
239 }
240 kh.Write(R.Bytes())
241 kh.Write(priv.pub[:])
242 kh.Write(message)
243 hramDigest := make([]byte, 0, sha512Size)
244 hramDigest = kh.Sum(hramDigest)
245 k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest)
246 if err != nil {
247 panic("ed25519: internal error: setting scalar failed")
248 }
249
250 S := edwards25519.NewScalar().MultiplyAdd(k, &priv.s, r)
251
252 copy(signature[:32], R.Bytes())
253 copy(signature[32:], S.Bytes())
254
255 return signature
256 }
257
258 func Verify(pub *PublicKey, message, sig []byte) error {
259 return verify(pub, message, sig)
260 }
261
262 func verify(pub *PublicKey, message, sig []byte) error {
263 fipsSelfTest()
264 fips140.RecordApproved()
265 return verifyWithDom(pub, message, sig, domPrefixPure, "")
266 }
267
268 func VerifyPH(pub *PublicKey, message []byte, sig []byte, context string) error {
269 fipsSelfTest()
270 fips140.RecordApproved()
271 if l := len(message); l != sha512Size {
272 return errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l))
273 }
274 if l := len(context); l > 255 {
275 return errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l))
276 }
277 return verifyWithDom(pub, message, sig, domPrefixPh, context)
278 }
279
280 func VerifyCtx(pub *PublicKey, message []byte, sig []byte, context string) error {
281 fipsSelfTest()
282
283 fips140.RecordNonApproved()
284 if l := len(context); l > 255 {
285 return errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l))
286 }
287 return verifyWithDom(pub, message, sig, domPrefixCtx, context)
288 }
289
290 func verifyWithDom(pub *PublicKey, message, sig []byte, domPrefix, context string) error {
291 if l := len(sig); l != signatureSize {
292 return errors.New("ed25519: bad signature length: " + strconv.Itoa(l))
293 }
294
295 if sig[63]&224 != 0 {
296 return errors.New("ed25519: invalid signature")
297 }
298
299 kh := sha512.New()
300 if domPrefix != domPrefixPure {
301 kh.Write([]byte(domPrefix))
302 kh.Write([]byte{byte(len(context))})
303 kh.Write([]byte(context))
304 }
305 kh.Write(sig[:32])
306 kh.Write(pub.aBytes[:])
307 kh.Write(message)
308 hramDigest := make([]byte, 0, sha512Size)
309 hramDigest = kh.Sum(hramDigest)
310 k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest)
311 if err != nil {
312 panic("ed25519: internal error: setting scalar failed")
313 }
314
315 S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:])
316 if err != nil {
317 return errors.New("ed25519: invalid signature")
318 }
319
320
321 minusA := (&edwards25519.Point{}).Negate(&pub.a)
322 R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S)
323
324 if !bytes.Equal(sig[:32], R.Bytes()) {
325 return errors.New("ed25519: invalid signature")
326 }
327 return nil
328 }
329
View as plain text