1
- // Copyright 2013 The Go Authors. All rights reserved.
1
+ // Copyright 2016 The Go Authors. All rights reserved.
2
2
// Use of this source code is governed by a BSD-style
3
3
// license that can be found in the LICENSE file.
4
4
5
5
// Package ed25519 implements the Ed25519 signature algorithm. See
6
- // http://ed25519.cr.yp.to/.
6
+ // https://ed25519.cr.yp.to/.
7
+ //
8
+ // These functions are also compatible with the “Ed25519” function defined in
9
+ // RFC 8032. However, unlike RFC 8032's formulation, this package's private key
10
+ // representation includes a public key suffix to make multiple signing
11
+ // operations with the same key more efficient. This package refers to the RFC
12
+ // 8032 private key as the “seed”.
7
13
package ed25519
8
14
9
- // This code is a port of the public domain, " ref10" implementation of ed25519
15
+ // This code is a port of the public domain, “ ref10” implementation of ed25519
10
16
// from SUPERCOP.
11
17
12
18
import (
19
+ "bytes"
20
+ "crypto"
21
+ cryptorand "crypto/rand"
13
22
"crypto/sha512"
14
- "crypto/subtle "
23
+ "errors "
15
24
"io"
25
+ "strconv"
16
26
17
- "github.com/agl/ ed25519/edwards25519"
27
+ "github.com/diagprov/golang- ed25519/edwards25519"
18
28
)
19
29
20
30
const (
21
- PublicKeySize = 32
31
+ // PublicKeySize is the size, in bytes, of public keys as used in this package.
32
+ PublicKeySize = 32
33
+ // PrivateKeySize is the size, in bytes, of private keys as used in this package.
22
34
PrivateKeySize = 64
23
- SignatureSize = 64
35
+ // SignatureSize is the size, in bytes, of signatures generated and verified by this package.
36
+ SignatureSize = 64
37
+ // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
38
+ SeedSize = 32
24
39
)
25
40
26
- // GenerateKey generates a public/private key pair using randomness from rand.
27
- func GenerateKey (rand io.Reader ) (publicKey * [PublicKeySize ]byte , privateKey * [PrivateKeySize ]byte , err error ) {
28
- privateKey = new ([64 ]byte )
29
- publicKey = new ([32 ]byte )
30
- _ , err = io .ReadFull (rand , privateKey [:32 ])
31
- if err != nil {
41
+ // PublicKey is the type of Ed25519 public keys.
42
+ type PublicKey []byte
43
+
44
+ // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
45
+ type PrivateKey []byte
46
+
47
+ // Public returns the PublicKey corresponding to priv.
48
+ func (priv PrivateKey ) Public () crypto.PublicKey {
49
+ publicKey := make ([]byte , PublicKeySize )
50
+ copy (publicKey , priv [32 :])
51
+ return PublicKey (publicKey )
52
+ }
53
+
54
+ // Seed returns the private key seed corresponding to priv. It is provided for
55
+ // interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
56
+ // in this package.
57
+ func (priv PrivateKey ) Seed () []byte {
58
+ seed := make ([]byte , SeedSize )
59
+ copy (seed , priv [:32 ])
60
+ return seed
61
+ }
62
+
63
+ // Sign signs the given message with priv.
64
+ // Ed25519 performs two passes over messages to be signed and therefore cannot
65
+ // handle pre-hashed messages. Thus opts.HashFunc() must return zero to
66
+ // indicate the message hasn't been hashed. This can be achieved by passing
67
+ // crypto.Hash(0) as the value for opts.
68
+ func (priv PrivateKey ) Sign (rand io.Reader , message []byte , opts crypto.SignerOpts ) (signature []byte , err error ) {
69
+ if opts .HashFunc () != crypto .Hash (0 ) {
70
+ return nil , errors .New ("ed25519: cannot sign hashed message" )
71
+ }
72
+
73
+ return Sign (priv , message ), nil
74
+ }
75
+
76
+ // GenerateKey generates a public/private key pair using entropy from rand.
77
+ // If rand is nil, crypto/rand.Reader will be used.
78
+ func GenerateKey (rand io.Reader ) (PublicKey , PrivateKey , error ) {
79
+ if rand == nil {
80
+ rand = cryptorand .Reader
81
+ }
82
+
83
+ seed := make ([]byte , SeedSize )
84
+ if _ , err := io .ReadFull (rand , seed ); err != nil {
32
85
return nil , nil , err
33
86
}
34
87
35
- h := sha512 . New ( )
36
- h . Write ( privateKey [: 32 ] )
37
- digest := h . Sum ( nil )
88
+ privateKey := NewKeyFromSeed ( seed )
89
+ publicKey := make ([] byte , PublicKeySize )
90
+ copy ( publicKey , privateKey [ 32 :] )
38
91
92
+ return publicKey , privateKey , nil
93
+ }
94
+
95
+ // NewKeyFromSeed calculates a private key from a seed. It will panic if
96
+ // len(seed) is not SeedSize. This function is provided for interoperability
97
+ // with RFC 8032. RFC 8032's private keys correspond to seeds in this
98
+ // package.
99
+ func NewKeyFromSeed (seed []byte ) PrivateKey {
100
+ if l := len (seed ); l != SeedSize {
101
+ panic ("ed25519: bad seed length: " + strconv .Itoa (l ))
102
+ }
103
+
104
+ digest := sha512 .Sum512 (seed )
39
105
digest [0 ] &= 248
40
106
digest [31 ] &= 127
41
107
digest [31 ] |= 64
42
108
43
109
var A edwards25519.ExtendedGroupElement
44
110
var hBytes [32 ]byte
45
- copy (hBytes [:], digest )
111
+ copy (hBytes [:], digest [:] )
46
112
edwards25519 .GeScalarMultBase (& A , & hBytes )
47
- A .ToBytes (publicKey )
113
+ var publicKeyBytes [32 ]byte
114
+ A .ToBytes (& publicKeyBytes )
115
+
116
+ privateKey := make ([]byte , PrivateKeySize )
117
+ copy (privateKey , seed )
118
+ copy (privateKey [32 :], publicKeyBytes [:])
48
119
49
- copy (privateKey [32 :], publicKey [:])
50
- return
120
+ return privateKey
51
121
}
52
122
53
- // Sign signs the message with privateKey and returns a signature.
54
- func Sign (privateKey * [PrivateKeySize ]byte , message []byte ) * [SignatureSize ]byte {
123
+ // Sign signs the message with privateKey and returns a signature. It will
124
+ // panic if len(privateKey) is not PrivateKeySize.
125
+ func Sign (privateKey PrivateKey , message []byte ) []byte {
126
+ if l := len (privateKey ); l != PrivateKeySize {
127
+ panic ("ed25519: bad private key length: " + strconv .Itoa (l ))
128
+ }
129
+
55
130
h := sha512 .New ()
56
131
h .Write (privateKey [:32 ])
57
132
@@ -87,20 +162,28 @@ func Sign(privateKey *[PrivateKeySize]byte, message []byte) *[SignatureSize]byte
87
162
var s [32 ]byte
88
163
edwards25519 .ScMulAdd (& s , & hramDigestReduced , & expandedSecretKey , & messageDigestReduced )
89
164
90
- signature := new ([ 64 ]byte )
165
+ signature := make ([ ]byte , SignatureSize )
91
166
copy (signature [:], encodedR [:])
92
167
copy (signature [32 :], s [:])
168
+
93
169
return signature
94
170
}
95
171
96
- // Verify returns true iff sig is a valid signature of message by publicKey.
97
- func Verify (publicKey * [PublicKeySize ]byte , message []byte , sig * [SignatureSize ]byte ) bool {
98
- if sig [63 ]& 224 != 0 {
172
+ // Verify reports whether sig is a valid signature of message by publicKey. It
173
+ // will panic if len(publicKey) is not PublicKeySize.
174
+ func Verify (publicKey PublicKey , message , sig []byte ) bool {
175
+ if l := len (publicKey ); l != PublicKeySize {
176
+ panic ("ed25519: bad public key length: " + strconv .Itoa (l ))
177
+ }
178
+
179
+ if len (sig ) != SignatureSize || sig [63 ]& 224 != 0 {
99
180
return false
100
181
}
101
182
102
183
var A edwards25519.ExtendedGroupElement
103
- if ! A .FromBytes (publicKey ) {
184
+ var publicKeyBytes [32 ]byte
185
+ copy (publicKeyBytes [:], publicKey )
186
+ if ! A .FromBytes (& publicKeyBytes ) {
104
187
return false
105
188
}
106
189
edwards25519 .FeNeg (& A .X , & A .X )
@@ -117,11 +200,18 @@ func Verify(publicKey *[PublicKeySize]byte, message []byte, sig *[SignatureSize]
117
200
edwards25519 .ScReduce (& hReduced , & digest )
118
201
119
202
var R edwards25519.ProjectiveGroupElement
120
- var b [32 ]byte
121
- copy (b [:], sig [32 :])
122
- edwards25519 .GeDoubleScalarMultVartime (& R , & hReduced , & A , & b )
203
+ var s [32 ]byte
204
+ copy (s [:], sig [32 :])
205
+
206
+ // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
207
+ // the range [0, order) in order to prevent signature malleability.
208
+ if ! edwards25519 .ScMinimal (& s ) {
209
+ return false
210
+ }
211
+
212
+ edwards25519 .GeDoubleScalarMultVartime (& R , & hReduced , & A , & s )
123
213
124
214
var checkR [32 ]byte
125
215
R .ToBytes (& checkR )
126
- return subtle . ConstantTimeCompare (sig [:32 ], checkR [:]) == 1
216
+ return bytes . Equal (sig [:32 ], checkR [:])
127
217
}
0 commit comments