From: lukechampine Date: Fri, 20 Sep 2019 17:25:07 +0000 (+0000) Subject: crypto/ed25519: outline NewKeyFromSeed and Sign X-Git-Tag: go1.14beta1~1004 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2dfff3633b839a913bd2f427cd362ab07194b052;p=gostls13.git 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: 0dd2e0f93e9cd1410760544be638238f18fa5cd4 GitHub-Pull-Request: golang/go#34357 Reviewed-on: https://go-review.googlesource.com/c/go/+/195980 Reviewed-by: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Gobot Gobot --- diff --git a/src/crypto/ed25519/ed25519.go b/src/crypto/ed25519/ed25519.go index dc47e5585d..dcb4f9544f 100644 --- a/src/crypto/ed25519/ed25519.go +++ b/src/crypto/ed25519/ed25519.go @@ -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 diff --git a/src/crypto/ed25519/ed25519_test.go b/src/crypto/ed25519/ed25519_test.go index 9c980fceff..cacd281f1c 100644 --- a/src/crypto/ed25519/ed25519_test.go +++ b/src/crypto/ed25519/ed25519_test.go @@ -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)