func testSignCompact(t *testing.T, tag string, curve *secp256k1.KoblitzCurve, data []byte, isCompressed bool) { tmp, _ := secp256k1.GeneratePrivateKey(curve) priv := (*secp256k1.PrivateKey)(tmp) hashed := []byte("testing") sig, err := secp256k1.SignCompact(curve, priv, hashed, isCompressed) if err != nil { t.Errorf("%s: error signing: %s", tag, err) return } pk, wasCompressed, err := secp256k1.RecoverCompact(curve, sig, hashed) if err != nil { t.Errorf("%s: error recovering: %s", tag, err) return } if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 { t.Errorf("%s: recovered pubkey doesn't match original "+ "(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y) return } if wasCompressed != isCompressed { t.Errorf("%s: recovered pubkey doesn't match compressed state "+ "(%v vs %v)", tag, isCompressed, wasCompressed) return } // If we change the compressed bit we should get the same key back, // but the compressed flag should be reversed. if isCompressed { sig[0] -= 4 } else { sig[0] += 4 } pk, wasCompressed, err = secp256k1.RecoverCompact(curve, sig, hashed) if err != nil { t.Errorf("%s: error recovering (2): %s", tag, err) return } if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 { t.Errorf("%s: recovered pubkey (2) doesn't match original "+ "(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y) return } if wasCompressed == isCompressed { t.Errorf("%s: recovered pubkey doesn't match reversed "+ "compressed state (%v vs %v)", tag, isCompressed, wasCompressed) return } }
// newSecp256k1DSA instatiates a function DSA subsystem over the secp256k1 // curve. A caveat for the functions below is that they're all routed through // interfaces, and nil returns from the library itself for interfaces must // ALWAYS be checked by checking the return value by attempted dereference // (== nil). func newSecp256k1DSA() DSA { var secp DSA = &secp256k1DSA{ // Constants getP: func() *big.Int { return secp256k1Curve.P }, getN: func() *big.Int { return secp256k1Curve.N }, // EC Math add: func(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { return secp256k1Curve.Add(x1, y1, x2, y2) }, isOnCurve: func(x, y *big.Int) bool { return secp256k1Curve.IsOnCurve(x, y) }, scalarMult: func(x, y *big.Int, k []byte) (*big.Int, *big.Int) { return secp256k1Curve.ScalarMult(x, y, k) }, scalarBaseMult: func(k []byte) (*big.Int, *big.Int) { return secp256k1Curve.ScalarBaseMult(k) }, // Private keys newPrivateKey: func(d *big.Int) PrivateKey { if d == nil { return nil } pk := secp256k1.NewPrivateKey(secp256k1Curve, d) if pk != nil { return PrivateKey(pk) } return nil }, privKeyFromBytes: func(pk []byte) (PrivateKey, PublicKey) { priv, pub := secp256k1.PrivKeyFromBytes(secp256k1Curve, pk) if priv == nil { return nil, nil } if pub == nil { return nil, nil } tpriv := PrivateKey(priv) tpub := PublicKey(pub) return tpriv, tpub }, privKeyFromScalar: func(pk []byte) (PrivateKey, PublicKey) { priv, pub := secp256k1.PrivKeyFromScalar(secp256k1Curve, pk) if priv == nil { return nil, nil } if pub == nil { return nil, nil } tpriv := PrivateKey(priv) tpub := PublicKey(pub) return tpriv, tpub }, privKeyBytesLen: func() int { return secp256k1.PrivKeyBytesLen }, // Public keys newPublicKey: func(x *big.Int, y *big.Int) PublicKey { pk := secp256k1.NewPublicKey(secp256k1Curve, x, y) tpk := PublicKey(pk) return tpk }, parsePubKey: func(pubKeyStr []byte) (PublicKey, error) { pk, err := secp256k1.ParsePubKey(pubKeyStr, secp256k1Curve) if err != nil { return nil, err } tpk := PublicKey(pk) return tpk, err }, pubKeyBytesLen: func() int { return secp256k1.PubKeyBytesLenCompressed }, pubKeyBytesLenUncompressed: func() int { return secp256k1.PubKeyBytesLenUncompressed }, pubKeyBytesLenCompressed: func() int { return secp256k1.PubKeyBytesLenCompressed }, pubKeyBytesLenHybrid: func() int { return secp256k1.PubKeyBytesLenHybrid }, // Signatures newSignature: func(r *big.Int, s *big.Int) Signature { sig := secp256k1.NewSignature(r, s) ts := Signature(sig) return ts }, parseDERSignature: func(sigStr []byte) (Signature, error) { sig, err := secp256k1.ParseDERSignature(sigStr, secp256k1Curve) if err != nil { return nil, err } ts := Signature(sig) return ts, err }, parseSignature: func(sigStr []byte) (Signature, error) { sig, err := secp256k1.ParseSignature(sigStr, secp256k1Curve) if err != nil { return nil, err } ts := Signature(sig) return ts, err }, recoverCompact: func(signature, hash []byte) (PublicKey, bool, error) { pk, bl, err := secp256k1.RecoverCompact(secp256k1Curve, signature, hash) tpk := PublicKey(pk) return tpk, bl, err }, // ECDSA generateKey: func(rand io.Reader) ([]byte, *big.Int, *big.Int, error) { return secp256k1.GenerateKey(secp256k1Curve, rand) }, sign: func(priv PrivateKey, hash []byte) (r, s *big.Int, err error) { if priv.GetType() != ECTypeSecp256k1 { return nil, nil, errors.New("wrong type") } spriv, ok := priv.(*secp256k1.PrivateKey) if !ok { return nil, nil, errors.New("wrong type") } sig, err := spriv.Sign(hash) if sig != nil { r = sig.GetR() s = sig.GetS() } return }, verify: func(pub PublicKey, hash []byte, r, s *big.Int) bool { spub := secp256k1.NewPublicKey(secp256k1Curve, pub.GetX(), pub.GetY()) ssig := secp256k1.NewSignature(r, s) return ssig.Verify(hash, spub) }, // Symmetric cipher encryption generateSharedSecret: func(privkey []byte, x, y *big.Int) []byte { sprivkey, _ := secp256k1.PrivKeyFromBytes(secp256k1Curve, privkey) if sprivkey == nil { return nil } spubkey := secp256k1.NewPublicKey(secp256k1Curve, x, y) return secp256k1.GenerateSharedSecret(sprivkey, spubkey) }, encrypt: func(x, y *big.Int, in []byte) ([]byte, error) { spubkey := secp256k1.NewPublicKey(secp256k1Curve, x, y) return secp256k1.Encrypt(spubkey, in) }, decrypt: func(privkey []byte, in []byte) ([]byte, error) { sprivkey, _ := secp256k1.PrivKeyFromBytes(secp256k1Curve, privkey) if sprivkey == nil { return nil, fmt.Errorf("failure deserializing privkey") } return secp256k1.Decrypt(sprivkey, in) }, } return secp.(DSA) }