func TestPublicKeyIsEqual(t *testing.T) { pubKey1, err := secp256k1.ParsePubKey( []byte{0x03, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33, 0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34, 0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4, 0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e, }, secp256k1.S256(), ) if err != nil { t.Fatalf("failed to parse raw bytes for pubKey1: %v", err) } pubKey2, err := secp256k1.ParsePubKey( []byte{0x02, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b, 0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1, 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21, 0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d, }, secp256k1.S256(), ) if err != nil { t.Fatalf("failed to parse raw bytes for pubKey2: %v", err) } if !pubKey1.IsEqual(pubKey1) { t.Fatalf("value of IsEqual is incorrect, %v is "+ "equal to %v", pubKey1, pubKey1) } if pubKey1.IsEqual(pubKey2) { t.Fatalf("value of IsEqual is incorrect, %v is not "+ "equal to %v", pubKey1, pubKey2) } }
func TestPubKeys(t *testing.T) { for _, test := range pubKeyTests { pk, err := secp256k1.ParsePubKey(test.key, secp256k1.S256()) if err != nil { if test.isValid { t.Errorf("%s pubkey failed when shouldn't %v", test.name, err) } continue } if !test.isValid { t.Errorf("%s counted as valid when it should fail", test.name) continue } var pkStr []byte switch test.format { case secp256k1.TstPubkeyUncompressed: pkStr = (*secp256k1.PublicKey)(pk).SerializeUncompressed() case secp256k1.TstPubkeyCompressed: pkStr = (*secp256k1.PublicKey)(pk).SerializeCompressed() case secp256k1.TstPubkeyHybrid: pkStr = (*secp256k1.PublicKey)(pk).SerializeHybrid() } if !bytes.Equal(test.key, pkStr) { t.Errorf("%s pubkey: serialized keys do not match.", test.name) spew.Dump(test.key) spew.Dump(pkStr) } } }
// This example demonstrates encrypting a message for a public key that is first // parsed from raw bytes, then decrypting it using the corresponding private key. func Example_encryptMessage() { // Decode the hex-encoded pubkey of the recipient. pubKeyBytes, err := hex.DecodeString("04115c42e757b2efb7671c578530ec191a1" + "359381e6a71127a9d37c486fd30dae57e76dc58f693bd7e7010358ce6b165e483a29" + "21010db67ac11b1b51b651953d2") // uncompressed pubkey if err != nil { fmt.Println(err) return } pubKey, err := secp256k1.ParsePubKey(pubKeyBytes, secp256k1.S256()) if err != nil { fmt.Println(err) return } // Encrypt a message decryptable by the private key corresponding to pubKey message := "test message" ciphertext, err := secp256k1.Encrypt(pubKey, []byte(message)) if err != nil { fmt.Println(err) return } // Decode the hex-encoded private key. pkBytes, err := hex.DecodeString("a11b0a4e1a132305652ee7a8eb7848f6ad" + "5ea381e3ce20a2c086a2e388230811") if err != nil { fmt.Println(err) return } // note that we already have corresponding pubKey privKey, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), pkBytes) // Try decrypting and verify if it's the same message. plaintext, err := secp256k1.Decrypt(privKey, ciphertext) if err != nil { fmt.Println(err) return } fmt.Println(string(plaintext)) // Output: // test message }
func TestPrivKeys(t *testing.T) { tests := []struct { name string key []byte }{ { name: "check curve", key: []byte{ 0xea, 0xf0, 0x2c, 0xa3, 0x48, 0xc5, 0x24, 0xe6, 0x39, 0x26, 0x55, 0xba, 0x4d, 0x29, 0x60, 0x3c, 0xd1, 0xa7, 0x34, 0x7d, 0x9d, 0x65, 0xcf, 0xe9, 0x3c, 0xe1, 0xeb, 0xff, 0xdc, 0xa2, 0x26, 0x94, }, }, } for _, test := range tests { priv, pub := secp256k1.PrivKeyFromBytes(secp256k1.S256(), test.key) _, err := secp256k1.ParsePubKey( pub.SerializeUncompressed(), secp256k1.S256()) if err != nil { t.Errorf("%s privkey: %v", test.name, err) continue } hash := []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9} sig, err := priv.Sign(hash) if err != nil { t.Errorf("%s could not sign: %v", test.name, err) continue } if !sig.Verify(hash, pub) { t.Errorf("%s could not verify: %v", test.name, err) continue } serializedKey := priv.Serialize() if !bytes.Equal(serializedKey, test.key) { t.Errorf("%s unexpected serialized bytes - got: %x, "+ "want: %x", test.name, serializedKey, test.key) } } }
// ParsePubKey parses a public key for a koblitz curve from a bytestring into a // ecdsa.Publickey, verifying that it is valid. It supports compressed, // uncompressed and hybrid signature formats. func ParsePubKey(curve *secp256k1.KoblitzCurve, pubKeyStr []byte) (key *secp256k1.PublicKey, err error) { if pubKeyStr == nil { err = fmt.Errorf("nil pubkey byte string") return } if len(pubKeyStr) != PubKeyBytesLen { err = fmt.Errorf("bad pubkey byte string size (want %v, have %v)", PubKeyBytesLen, len(pubKeyStr)) return } format := pubKeyStr[0] format &= ^byte(0x1) if format != pubkeyCompressed { err = fmt.Errorf("wrong pubkey type (not compressed)") return } return secp256k1.ParsePubKey(pubKeyStr, curve) }
// This example demonstrates verifying a secp256k1 signature against a public // key that is first parsed from raw bytes. The signature is also parsed from // raw bytes. func Example_verifySignature() { // Decode hex-encoded serialized public key. pubKeyBytes, err := hex.DecodeString("02a673638cb9587cb68ea08dbef685c" + "6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5") if err != nil { fmt.Println(err) return } pubKey, err := secp256k1.ParsePubKey(pubKeyBytes, secp256k1.S256()) if err != nil { fmt.Println(err) return } // Decode hex-encoded serialized signature. sigBytes, err := hex.DecodeString("3045022100fcc0a8768cfbcefcf2cadd7cfb0" + "fb18ed08dd2e2ae84bef1a474a3d351b26f0302200fc1a350b45f46fa0010139130" + "2818d748c2b22615511a3ffd5bb638bd777207") if err != nil { fmt.Println(err) return } signature, err := secp256k1.ParseSignature(sigBytes, secp256k1.S256()) if err != nil { fmt.Println(err) return } // Verify the signature for the message using the public key. message := "test message" messageHash := chainhash.HashFuncB([]byte(message)) verified := signature.Verify(messageHash, pubKey) fmt.Println("Signature Verified?", verified) // Output: // Signature Verified? true }
func GetThresholdTestVectors() []*ThresholdTestVector { curve := secp256k1.S256() var tvs []*ThresholdTestVector for _, v := range thresholdTestVectorsHex { msg, _ := hex.DecodeString(v.msg) combSig, _ := hex.DecodeString(v.combinedSignature) signers := make([]signer, len(v.signersHex), len(v.signersHex)) for i, signerHex := range v.signersHex { privkeyB, _ := hex.DecodeString(signerHex.privkey) _, pubkey := secp256k1.PrivKeyFromBytes(curve, privkeyB) privateNonceB, _ := hex.DecodeString(signerHex.privateNonce) _, noncePub := secp256k1.PrivKeyFromBytes(curve, privateNonceB) pubKeySumLocalB, _ := hex.DecodeString(signerHex.pubKeySumLocal) pubKeySumLocal, _ := secp256k1.ParsePubKey(pubKeySumLocalB, curve) partialSignature, _ := hex.DecodeString(signerHex.partialSignature) signers[i].privkey = privkeyB signers[i].pubkey = pubkey signers[i].privateNonce = privateNonceB signers[i].publicNonce = noncePub signers[i].pubKeySumLocal = pubKeySumLocal signers[i].partialSignature = partialSignature } lv := ThresholdTestVector{ msg: msg, signers: signers, combinedSignature: combSig, } tvs = append(tvs, &lv) } return tvs }
// schnorrRecover recovers a public key using a signature, hash function, // and message. It also attempts to verify the signature against the // regenerated public key. func schnorrRecover(curve *secp256k1.KoblitzCurve, sig, msg []byte, hashFunc func([]byte) []byte) (*secp256k1.PublicKey, bool, error) { if len(msg) != scalarSize { str := fmt.Sprintf("wrong size for message (got %v, want %v)", len(msg), scalarSize) return nil, false, schnorrError(ErrBadInputSize, str) } if len(sig) != SignatureSize { str := fmt.Sprintf("wrong size for signature (got %v, want %v)", len(sig), SignatureSize) return nil, false, schnorrError(ErrBadInputSize, str) } sigR := sig[:32] sigS := sig[32:] sigRCopy := make([]byte, scalarSize, scalarSize) copy(sigRCopy, sigR) toHash := append(sigRCopy, msg...) h := hashFunc(toHash) hBig := new(big.Int).SetBytes(h) // If the hash ends up larger than the order of the curve, abort. // Same thing for hash == 0 (as unlikely as that is...). if hBig.Cmp(curve.N) >= 0 { str := fmt.Sprintf("hash of (R || m) too big") return nil, false, schnorrError(ErrSchnorrHashValue, str) } if hBig.Cmp(bigZero) == 0 { str := fmt.Sprintf("hash of (R || m) is zero value") return nil, false, schnorrError(ErrSchnorrHashValue, str) } // Convert s to big int. sBig := EncodedBytesToBigInt(copyBytes(sigS)) // We also can't have s greater than the order of the curve. if sBig.Cmp(curve.N) >= 0 { str := fmt.Sprintf("s value is too big") return nil, false, schnorrError(ErrInputValue, str) } // r can't be larger than the curve prime. rBig := EncodedBytesToBigInt(copyBytes(sigR)) if rBig.Cmp(curve.P) == 1 { str := fmt.Sprintf("given R was greater than curve prime") return nil, false, schnorrError(ErrBadSigRNotOnCurve, str) } // Decompress the Y value. We know that the first bit must // be even. Use the PublicKey struct to make it easier. compressedPoint := make([]byte, PubKeyBytesLen, PubKeyBytesLen) compressedPoint[0] = pubkeyCompressed copy(compressedPoint[1:], sigR) rPoint, err := secp256k1.ParsePubKey(compressedPoint, curve) if err != nil { str := fmt.Sprintf("bad r point") return nil, false, schnorrError(ErrRegenerateRPoint, str) } // Get the inverse of the hash. hInv := new(big.Int).ModInverse(hBig, curve.N) hInv.Mod(hInv, curve.N) // Negate s. sBig.Sub(curve.N, sBig) sBig.Mod(sBig, curve.N) // s' = -s * inverse(h). sBig.Mul(sBig, hInv) sBig.Mod(sBig, curve.N) // Q = h^(-1)R + s'G lx, ly := curve.ScalarMult(rPoint.GetX(), rPoint.GetY(), hInv.Bytes()) rx, ry := curve.ScalarBaseMult(sBig.Bytes()) pkx, pky := curve.Add(lx, ly, rx, ry) // Check if the public key is on the curve. if !curve.IsOnCurve(pkx, pky) { str := fmt.Sprintf("pubkey not on curve") return nil, false, schnorrError(ErrPubKeyOffCurve, str) } pubkey := secp256k1.NewPublicKey(curve, pkx, pky) // Verify this signature. Slow, lots of double checks, could be more // cheaply implemented as // hQ + sG - R == 0 // which this function checks. // This will sometimes pass even for corrupted signatures, but // this shouldn't be a concern because whoever is using the // results should be checking the returned public key against // some known one anyway. In the case of these Schnorr signatures, // relatively high numbers of corrupted signatures (50-70%) // seem to produce valid pubkeys and valid signatures. _, err = schnorrVerify(curve, sig, pubkey, msg, hashFunc) if err != nil { str := fmt.Sprintf("pubkey/sig pair could not be validated") return nil, false, schnorrError(ErrRegenSig, str) } return pubkey, true, nil }
// 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) }