Skip to content

Commit 593e9b1

Browse files
committed
Backport x/crypto changes, fix tests, make a module.
1 parent 5312a61 commit 593e9b1

File tree

6 files changed

+274
-80
lines changed

6 files changed

+274
-80
lines changed

ed25519.go

+121-31
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,132 @@
1-
// Copyright 2013 The Go Authors. All rights reserved.
1+
// Copyright 2016 The Go Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

55
// 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”.
713
package ed25519
814

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
1016
// from SUPERCOP.
1117

1218
import (
19+
"bytes"
20+
"crypto"
21+
cryptorand "crypto/rand"
1322
"crypto/sha512"
14-
"crypto/subtle"
23+
"errors"
1524
"io"
25+
"strconv"
1626

17-
"github.com/agl/ed25519/edwards25519"
27+
"github.com/diagprov/golang-ed25519/edwards25519"
1828
)
1929

2030
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.
2234
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
2439
)
2540

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 {
3285
return nil, nil, err
3386
}
3487

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:])
3891

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)
39105
digest[0] &= 248
40106
digest[31] &= 127
41107
digest[31] |= 64
42108

43109
var A edwards25519.ExtendedGroupElement
44110
var hBytes [32]byte
45-
copy(hBytes[:], digest)
111+
copy(hBytes[:], digest[:])
46112
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[:])
48119

49-
copy(privateKey[32:], publicKey[:])
50-
return
120+
return privateKey
51121
}
52122

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+
55130
h := sha512.New()
56131
h.Write(privateKey[:32])
57132

@@ -87,20 +162,28 @@ func Sign(privateKey *[PrivateKeySize]byte, message []byte) *[SignatureSize]byte
87162
var s [32]byte
88163
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
89164

90-
signature := new([64]byte)
165+
signature := make([]byte, SignatureSize)
91166
copy(signature[:], encodedR[:])
92167
copy(signature[32:], s[:])
168+
93169
return signature
94170
}
95171

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 {
99180
return false
100181
}
101182

102183
var A edwards25519.ExtendedGroupElement
103-
if !A.FromBytes(publicKey) {
184+
var publicKeyBytes [32]byte
185+
copy(publicKeyBytes[:], publicKey)
186+
if !A.FromBytes(&publicKeyBytes) {
104187
return false
105188
}
106189
edwards25519.FeNeg(&A.X, &A.X)
@@ -117,11 +200,18 @@ func Verify(publicKey *[PublicKeySize]byte, message []byte, sig *[SignatureSize]
117200
edwards25519.ScReduce(&hReduced, &digest)
118201

119202
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)
123213

124214
var checkR [32]byte
125215
R.ToBytes(&checkR)
126-
return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1
216+
return bytes.Equal(sig[:32], checkR[:])
127217
}

0 commit comments

Comments
 (0)