1
0
mirror of https://github.com/golang/go synced 2024-09-29 22:34:33 -06:00

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: 0dd2e0f93e
GitHub-Pull-Request: golang/go#34357
Reviewed-on: https://go-review.googlesource.com/c/go/+/195980
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
lukechampine 2019-09-20 17:25:07 +00:00 committed by Daniel Martí
parent 39ab8db914
commit 2dfff3633b
2 changed files with 24 additions and 6 deletions

View File

@ -96,6 +96,13 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
// Outline the function body so that the returned key can be stack-allocated.
privateKey := make([]byte, PrivateKeySize)
newKeyFromSeed(privateKey, seed)
return privateKey
}
func newKeyFromSeed(privateKey, seed []byte) {
if l := len(seed); l != SeedSize {
panic("ed25519: bad seed length: " + strconv.Itoa(l))
}
@ -112,16 +119,21 @@ func NewKeyFromSeed(seed []byte) PrivateKey {
var publicKeyBytes [32]byte
A.ToBytes(&publicKeyBytes)
privateKey := make([]byte, PrivateKeySize)
copy(privateKey, seed)
copy(privateKey[32:], publicKeyBytes[:])
return privateKey
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
// Outline the function body so that the returned signature can be
// stack-allocated.
signature := make([]byte, SignatureSize)
sign(signature, privateKey, message)
return signature
}
func sign(signature, privateKey, message []byte) {
if l := len(privateKey); l != PrivateKeySize {
panic("ed25519: bad private key length: " + strconv.Itoa(l))
}
@ -161,11 +173,8 @@ func Sign(privateKey PrivateKey, message []byte) []byte {
var s [32]byte
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
signature := make([]byte, SignatureSize)
copy(signature[:], encodedR[:])
copy(signature[32:], s[:])
return signature
}
// Verify reports whether sig is a valid signature of message by publicKey. It

View File

@ -191,6 +191,14 @@ func BenchmarkKeyGeneration(b *testing.B) {
}
}
func BenchmarkNewKeyFromSeed(b *testing.B) {
seed := make([]byte, SeedSize)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = NewKeyFromSeed(seed)
}
}
func BenchmarkSigning(b *testing.B) {
var zero zeroReader
_, priv, err := GenerateKey(zero)
@ -198,6 +206,7 @@ func BenchmarkSigning(b *testing.B) {
b.Fatal(err)
}
message := []byte("Hello, world!")
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
Sign(priv, message)