diff options
Diffstat (limited to 'src/pkg/crypto/ecdsa')
-rw-r--r-- | src/pkg/crypto/ecdsa/ecdsa.go | 165 | ||||
-rw-r--r-- | src/pkg/crypto/ecdsa/ecdsa_test.go | 191 | ||||
-rw-r--r-- | src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 | bin | 95485 -> 0 bytes |
3 files changed, 0 insertions, 356 deletions
diff --git a/src/pkg/crypto/ecdsa/ecdsa.go b/src/pkg/crypto/ecdsa/ecdsa.go deleted file mode 100644 index 1bec7437a..000000000 --- a/src/pkg/crypto/ecdsa/ecdsa.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as -// defined in FIPS 186-3. -package ecdsa - -// References: -// [NSA]: Suite B implementer's guide to FIPS 186-3, -// http://www.nsa.gov/ia/_files/ecdsa.pdf -// [SECG]: SECG, SEC1 -// http://www.secg.org/download/aid-780/sec1-v2.pdf - -import ( - "crypto/elliptic" - "io" - "math/big" -) - -// PublicKey represents an ECDSA public key. -type PublicKey struct { - elliptic.Curve - X, Y *big.Int -} - -// PrivateKey represents a ECDSA private key. -type PrivateKey struct { - PublicKey - D *big.Int -} - -var one = new(big.Int).SetInt64(1) - -// randFieldElement returns a random element of the field underlying the given -// curve using the procedure given in [NSA] A.2.1. -func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) { - params := c.Params() - b := make([]byte, params.BitSize/8+8) - _, err = io.ReadFull(rand, b) - if err != nil { - return - } - - k = new(big.Int).SetBytes(b) - n := new(big.Int).Sub(params.N, one) - k.Mod(k, n) - k.Add(k, one) - return -} - -// GenerateKey generates a public and private key pair. -func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error) { - k, err := randFieldElement(c, rand) - if err != nil { - return - } - - priv = new(PrivateKey) - priv.PublicKey.Curve = c - priv.D = k - priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) - return -} - -// hashToInt converts a hash value to an integer. There is some disagreement -// about how this is done. [NSA] suggests that this is done in the obvious -// manner, but [SECG] truncates the hash to the bit-length of the curve order -// first. We follow [SECG] because that's what OpenSSL does. Additionally, -// OpenSSL right shifts excess bits from the number if the hash is too large -// and we mirror that too. -func hashToInt(hash []byte, c elliptic.Curve) *big.Int { - orderBits := c.Params().N.BitLen() - orderBytes := (orderBits + 7) / 8 - if len(hash) > orderBytes { - hash = hash[:orderBytes] - } - - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - orderBits - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - -// fermatInverse calculates the inverse of k in GF(P) using Fermat's method. -// This has better constant-time properties than Euclid's method (implemented -// in math/big.Int.ModInverse) although math/big itself isn't strictly -// constant-time so it's not perfect. -func fermatInverse(k, N *big.Int) *big.Int { - two := big.NewInt(2) - nMinus2 := new(big.Int).Sub(N, two) - return new(big.Int).Exp(k, nMinus2, N) -} - -// Sign signs an arbitrary length hash (which should be the result of hashing a -// larger message) using the private key, priv. It returns the signature as a -// pair of integers. The security of the private key depends on the entropy of -// rand. -func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { - // See [NSA] 3.4.1 - c := priv.PublicKey.Curve - N := c.Params().N - - var k, kInv *big.Int - for { - for { - k, err = randFieldElement(c, rand) - if err != nil { - r = nil - return - } - - kInv = fermatInverse(k, N) - r, _ = priv.Curve.ScalarBaseMult(k.Bytes()) - r.Mod(r, N) - if r.Sign() != 0 { - break - } - } - - e := hashToInt(hash, c) - s = new(big.Int).Mul(priv.D, r) - s.Add(s, e) - s.Mul(s, kInv) - s.Mod(s, N) - if s.Sign() != 0 { - break - } - } - - return -} - -// Verify verifies the signature in r, s of hash using the public key, pub. Its -// return value records whether the signature is valid. -func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { - // See [NSA] 3.4.2 - c := pub.Curve - N := c.Params().N - - if r.Sign() == 0 || s.Sign() == 0 { - return false - } - if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 { - return false - } - e := hashToInt(hash, c) - 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) - if x.Sign() == 0 && y.Sign() == 0 { - return false - } - x.Mod(x, N) - return x.Cmp(r) == 0 -} diff --git a/src/pkg/crypto/ecdsa/ecdsa_test.go b/src/pkg/crypto/ecdsa/ecdsa_test.go deleted file mode 100644 index 0c0643193..000000000 --- a/src/pkg/crypto/ecdsa/ecdsa_test.go +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ecdsa - -import ( - "bufio" - "compress/bzip2" - "crypto/elliptic" - "crypto/rand" - "crypto/sha1" - "crypto/sha256" - "crypto/sha512" - "encoding/hex" - "hash" - "io" - "math/big" - "os" - "strings" - "testing" -) - -func testKeyGeneration(t *testing.T, c elliptic.Curve, tag string) { - priv, err := GenerateKey(c, rand.Reader) - if err != nil { - t.Errorf("%s: error: %s", tag, err) - return - } - if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) { - t.Errorf("%s: public key invalid: %s", tag, err) - } -} - -func TestKeyGeneration(t *testing.T) { - testKeyGeneration(t, elliptic.P224(), "p224") - if testing.Short() { - return - } - testKeyGeneration(t, elliptic.P256(), "p256") - testKeyGeneration(t, elliptic.P384(), "p384") - testKeyGeneration(t, elliptic.P521(), "p521") -} - -func testSignAndVerify(t *testing.T, c elliptic.Curve, tag string) { - priv, _ := GenerateKey(c, rand.Reader) - - hashed := []byte("testing") - r, s, err := Sign(rand.Reader, priv, hashed) - if err != nil { - t.Errorf("%s: error signing: %s", tag, err) - return - } - - if !Verify(&priv.PublicKey, hashed, r, s) { - t.Errorf("%s: Verify failed", tag) - } - - hashed[0] ^= 0xff - if Verify(&priv.PublicKey, hashed, r, s) { - t.Errorf("%s: Verify always works!", tag) - } -} - -func TestSignAndVerify(t *testing.T) { - testSignAndVerify(t, elliptic.P224(), "p224") - if testing.Short() { - return - } - testSignAndVerify(t, elliptic.P256(), "p256") - testSignAndVerify(t, elliptic.P384(), "p384") - testSignAndVerify(t, elliptic.P521(), "p521") -} - -func fromHex(s string) *big.Int { - r, ok := new(big.Int).SetString(s, 16) - if !ok { - panic("bad hex") - } - return r -} - -func TestVectors(t *testing.T) { - // This test runs the full set of NIST test vectors from - // http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip - // - // The SigVer.rsp file has been edited to remove test vectors for - // unsupported algorithms and has been compressed. - - if testing.Short() { - return - } - - f, err := os.Open("testdata/SigVer.rsp.bz2") - if err != nil { - t.Fatal(err) - } - - buf := bufio.NewReader(bzip2.NewReader(f)) - - lineNo := 1 - var h hash.Hash - var msg []byte - var hashed []byte - var r, s *big.Int - pub := new(PublicKey) - - for { - line, err := buf.ReadString('\n') - if len(line) == 0 { - if err == io.EOF { - break - } - t.Fatalf("error reading from input: %s", err) - } - lineNo++ - // Need to remove \r\n from the end of the line. - if !strings.HasSuffix(line, "\r\n") { - t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo) - } - line = line[:len(line)-2] - - if len(line) == 0 || line[0] == '#' { - continue - } - - if line[0] == '[' { - line = line[1 : len(line)-1] - parts := strings.SplitN(line, ",", 2) - - switch parts[0] { - case "P-224": - pub.Curve = elliptic.P224() - case "P-256": - pub.Curve = elliptic.P256() - case "P-384": - pub.Curve = elliptic.P384() - case "P-521": - pub.Curve = elliptic.P521() - default: - pub.Curve = nil - } - - switch parts[1] { - case "SHA-1": - h = sha1.New() - case "SHA-224": - h = sha256.New224() - case "SHA-256": - h = sha256.New() - case "SHA-384": - h = sha512.New384() - case "SHA-512": - h = sha512.New() - default: - h = nil - } - - continue - } - - if h == nil || pub.Curve == nil { - continue - } - - switch { - case strings.HasPrefix(line, "Msg = "): - if msg, err = hex.DecodeString(line[6:]); err != nil { - t.Fatalf("failed to decode message on line %d: %s", lineNo, err) - } - case strings.HasPrefix(line, "Qx = "): - pub.X = fromHex(line[5:]) - case strings.HasPrefix(line, "Qy = "): - pub.Y = fromHex(line[5:]) - case strings.HasPrefix(line, "R = "): - r = fromHex(line[4:]) - case strings.HasPrefix(line, "S = "): - s = fromHex(line[4:]) - case strings.HasPrefix(line, "Result = "): - expected := line[9] == 'P' - h.Reset() - h.Write(msg) - hashed := h.Sum(hashed[:0]) - if Verify(pub, hashed, r, s) != expected { - t.Fatalf("incorrect result on line %d", lineNo) - } - default: - t.Fatalf("unknown variable on line %d: %s", lineNo, line) - } - } -} diff --git a/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 b/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 Binary files differdeleted file mode 100644 index 09fe2b427..000000000 --- a/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 +++ /dev/null |