crypto/elliptic: add constant-time, P-256 implementation.

On my 64-bit machine, despite being 32-bit code, fixed-base
multiplications are 7.1x faster and arbitary multiplications are 2.6x
faster.

It is difficult to review this change. However, the code is essentially
the same as code that has been open-sourced in Chromium. There it has
been successfully performing P-256 operations for several months on
many machines so the arithmetic of the code should be sound.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/10551044
This commit is contained in:
Adam Langley 2013-06-27 13:31:05 -04:00
parent 7ebb187e8e
commit d2a19e9fd1
3 changed files with 1243 additions and 12 deletions

View File

@ -322,7 +322,6 @@ func Unmarshal(curve Curve, data []byte) (x, y *big.Int) {
}
var initonce sync.Once
var p256 *CurveParams
var p384 *CurveParams
var p521 *CurveParams
@ -333,17 +332,6 @@ func initAll() {
initP521()
}
func initP256() {
// See FIPS 186-3, section D.2.3
p256 = new(CurveParams)
p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
p256.BitSize = 256
}
func initP384() {
// See FIPS 186-3, section D.2.4
p384 = new(CurveParams)

View File

@ -322,6 +322,52 @@ func TestGenericBaseMult(t *testing.T) {
}
}
func TestP256BaseMult(t *testing.T) {
p256 := P256()
p256Generic := p256.Params()
scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1)
for _, e := range p224BaseMultTests {
k, _ := new(big.Int).SetString(e.k, 10)
scalars = append(scalars, k)
}
k := new(big.Int).SetInt64(1)
k.Lsh(k, 500)
scalars = append(scalars, k)
for i, k := range scalars {
x, y := p256.ScalarBaseMult(k.Bytes())
x2, y2 := p256Generic.ScalarBaseMult(k.Bytes())
if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 {
t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, x, y, x2, y2)
}
if testing.Short() && i > 5 {
break
}
}
}
func TestP256Mult(t *testing.T) {
p256 := P256()
p256Generic := p256.Params()
for i, e := range p224BaseMultTests {
x, _ := new(big.Int).SetString(e.x, 16)
y, _ := new(big.Int).SetString(e.y, 16)
k, _ := new(big.Int).SetString(e.k, 10)
xx, yy := p256.ScalarMult(x, y, k.Bytes())
xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes())
if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 {
t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2)
}
if testing.Short() && i > 5 {
break
}
}
}
func TestInfinity(t *testing.T) {
tests := []struct {
name string
@ -371,6 +417,17 @@ func BenchmarkBaseMult(b *testing.B) {
}
}
func BenchmarkBaseMultP256(b *testing.B) {
b.ResetTimer()
p256 := P256()
e := p224BaseMultTests[25]
k, _ := new(big.Int).SetString(e.k, 10)
b.StartTimer()
for i := 0; i < b.N; i++ {
p256.ScalarBaseMult(k.Bytes())
}
}
func TestMarshal(t *testing.T) {
p224 := P224()
_, x, y, err := GenerateKey(p224, rand.Reader)

File diff suppressed because it is too large Load Diff