diff options
Diffstat (limited to 'libgo/go/crypto/ecdsa/ecdsa.go')
-rw-r--r-- | libgo/go/crypto/ecdsa/ecdsa.go | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go index 8d66477fd10..0731f2b6703 100644 --- a/libgo/go/crypto/ecdsa/ecdsa.go +++ b/libgo/go/crypto/ecdsa/ecdsa.go @@ -27,6 +27,17 @@ import ( "math/big" ) +// A invertible implements fast inverse mod Curve.Params().N +type invertible interface { + // Inverse returns the inverse of k in GF(P) + Inverse(k *big.Int) *big.Int +} + +// combinedMult implements fast multiplication S1*g + S2*p (g - generator, p - arbitrary point) +type combinedMult interface { + CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) +} + const ( aesIV = "IV for ECDSA CTR" ) @@ -179,7 +190,12 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err return } - kInv = fermatInverse(k, N) + if in, ok := priv.Curve.(invertible); ok { + kInv = in.Inverse(k) + } else { + kInv = fermatInverse(k, N) + } + r, _ = priv.Curve.ScalarBaseMult(k.Bytes()) r.Mod(r, N) if r.Sign() != 0 { @@ -214,16 +230,29 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { return false } e := hashToInt(hash, c) - w := new(big.Int).ModInverse(s, N) + + var w *big.Int + if in, ok := c.(invertible); ok { + w = in.Inverse(s) + } else { + w = new(big.Int).ModInverse(s, N) + } u1 := e.Mul(e, w) u1.Mod(u1, N) u2 := w.Mul(r, w) u2.Mod(u2, N) - x1, y1 := c.ScalarBaseMult(u1.Bytes()) - x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes()) - x, y := c.Add(x1, y1, x2, y2) + // Check if implements S1*g + S2*p + var x, y *big.Int + if opt, ok := c.(combinedMult); ok { + x, y = opt.CombinedMult(pub.X, pub.Y, u1.Bytes(), u2.Bytes()) + } else { + x1, y1 := c.ScalarBaseMult(u1.Bytes()) + x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes()) + x, y = c.Add(x1, y1, x2, y2) + } + if x.Sign() == 0 && y.Sign() == 0 { return false } |