Skip to content

Commit 2dfff36

Browse files
lukechampinemvdan
authored andcommitted
crypto/ed25519: outline NewKeyFromSeed and Sign
This allows the returned key/signature to be stack-allocated where possible. name old time/op new time/op delta NewKeyFromSeed-4 61.8µs ± 8% 57.2µs ±11% ~ (p=0.056 n=5+5) Signing-4 56.6µs ± 3% 67.8µs ±38% ~ (p=1.000 n=5+5) name old alloc/op new alloc/op delta NewKeyFromSeed-4 64.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) Signing-4 512B ± 0% 448B ± 0% -12.50% (p=0.008 n=5+5) name old allocs/op new allocs/op delta NewKeyFromSeed-4 1.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) Signing-4 6.00 ± 0% 5.00 ± 0% -16.67% (p=0.008 n=5+5) Change-Id: I7dc6a1b8a483c4b213f380ac7c30cefc5caca0f9 GitHub-Last-Rev: 0dd2e0f GitHub-Pull-Request: #34357 Reviewed-on: https://go-review.googlesource.com/c/go/+/195980 Reviewed-by: Filippo Valsorda <[email protected]> Run-TryBot: Filippo Valsorda <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 39ab8db commit 2dfff36

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

src/crypto/ed25519/ed25519.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
9696
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
9797
// package.
9898
func NewKeyFromSeed(seed []byte) PrivateKey {
99+
// Outline the function body so that the returned key can be stack-allocated.
100+
privateKey := make([]byte, PrivateKeySize)
101+
newKeyFromSeed(privateKey, seed)
102+
return privateKey
103+
}
104+
105+
func newKeyFromSeed(privateKey, seed []byte) {
99106
if l := len(seed); l != SeedSize {
100107
panic("ed25519: bad seed length: " + strconv.Itoa(l))
101108
}
@@ -112,16 +119,21 @@ func NewKeyFromSeed(seed []byte) PrivateKey {
112119
var publicKeyBytes [32]byte
113120
A.ToBytes(&publicKeyBytes)
114121

115-
privateKey := make([]byte, PrivateKeySize)
116122
copy(privateKey, seed)
117123
copy(privateKey[32:], publicKeyBytes[:])
118-
119-
return privateKey
120124
}
121125

122126
// Sign signs the message with privateKey and returns a signature. It will
123127
// panic if len(privateKey) is not PrivateKeySize.
124128
func Sign(privateKey PrivateKey, message []byte) []byte {
129+
// Outline the function body so that the returned signature can be
130+
// stack-allocated.
131+
signature := make([]byte, SignatureSize)
132+
sign(signature, privateKey, message)
133+
return signature
134+
}
135+
136+
func sign(signature, privateKey, message []byte) {
125137
if l := len(privateKey); l != PrivateKeySize {
126138
panic("ed25519: bad private key length: " + strconv.Itoa(l))
127139
}
@@ -161,11 +173,8 @@ func Sign(privateKey PrivateKey, message []byte) []byte {
161173
var s [32]byte
162174
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
163175

164-
signature := make([]byte, SignatureSize)
165176
copy(signature[:], encodedR[:])
166177
copy(signature[32:], s[:])
167-
168-
return signature
169178
}
170179

171180
// Verify reports whether sig is a valid signature of message by publicKey. It

src/crypto/ed25519/ed25519_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,22 @@ func BenchmarkKeyGeneration(b *testing.B) {
191191
}
192192
}
193193

194+
func BenchmarkNewKeyFromSeed(b *testing.B) {
195+
seed := make([]byte, SeedSize)
196+
b.ReportAllocs()
197+
for i := 0; i < b.N; i++ {
198+
_ = NewKeyFromSeed(seed)
199+
}
200+
}
201+
194202
func BenchmarkSigning(b *testing.B) {
195203
var zero zeroReader
196204
_, priv, err := GenerateKey(zero)
197205
if err != nil {
198206
b.Fatal(err)
199207
}
200208
message := []byte("Hello, world!")
209+
b.ReportAllocs()
201210
b.ResetTimer()
202211
for i := 0; i < b.N; i++ {
203212
Sign(priv, message)

0 commit comments

Comments
 (0)