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 TestGenerateSharedSecret(t *testing.T) { c := secp256k1.S256() privKey1, err := secp256k1.GeneratePrivateKey(secp256k1.S256()) if err != nil { t.Errorf("private key generation error: %s", err) return } privKey2, err := secp256k1.GeneratePrivateKey(secp256k1.S256()) if err != nil { t.Errorf("private key generation error: %s", err) return } pk1x, pk1y := privKey1.Public() pk1 := secp256k1.NewPublicKey(c, pk1x, pk1y) pk2x, pk2y := privKey2.Public() pk2 := secp256k1.NewPublicKey(c, pk2x, pk2y) secret1 := secp256k1.GenerateSharedSecret(privKey1, pk2) secret2 := secp256k1.GenerateSharedSecret(privKey2, pk1) if !bytes.Equal(secret1, secret2) { t.Errorf("ECDH failed, secrets mismatch - first: %x, second: %x", secret1, secret2) } }
// Test 1: Encryption and decryption func TestCipheringBasic(t *testing.T) { c := secp256k1.S256() privkey, err := secp256k1.GeneratePrivateKey(secp256k1.S256()) if err != nil { t.Fatal("failed to generate private key") } in := []byte("Hey there dude. How are you doing? This is a test.") pk1x, pk1y := privkey.Public() pk1 := secp256k1.NewPublicKey(c, pk1x, pk1y) out, err := secp256k1.Encrypt(pk1, in) if err != nil { t.Fatal("failed to encrypt:", err) } dec, err := secp256k1.Decrypt(privkey, out) if err != nil { t.Fatal("failed to decrypt:", err) } if !bytes.Equal(in, dec) { t.Error("decrypted data doesn't match original") } }
func TestScalarMult(t *testing.T) { // Strategy for this test: // Get a random exponent from the generator point at first // This creates a new point which is used in the next iteration // Use another random exponent on the new point. // We use BaseMult to verify by multiplying the previous exponent // and the new random exponent together (mod N) s256 := secp256k1.S256() x, y := s256.Gx, s256.Gy exponent := big.NewInt(1) for i := 0; i < 1024; i++ { data := make([]byte, 32) _, err := rand.Read(data) if err != nil { t.Fatalf("failed to read random data at %d", i) break } x, y = s256.ScalarMult(x, y, data) exponent.Mul(exponent, new(big.Int).SetBytes(data)) xWant, yWant := s256.ScalarBaseMult(exponent.Bytes()) if x.Cmp(xWant) != 0 || y.Cmp(yWant) != 0 { t.Fatalf("%d: bad output for %X: got (%X, %X), want (%X, %X)", i, data, x, y, xWant, yWant) break } } }
func benchmarkSigning(b *testing.B) { curve := secp256k1.S256() r := rand.New(rand.NewSource(54321)) msg := []byte{ 0xbe, 0x13, 0xae, 0xf4, 0xe8, 0xa2, 0x00, 0xb6, 0x45, 0x81, 0xc4, 0xd1, 0x0c, 0xf4, 0x1b, 0x5b, 0xe1, 0xd1, 0x81, 0xa7, 0xd3, 0xdc, 0x37, 0x55, 0x58, 0xc1, 0xbd, 0xa2, 0x98, 0x2b, 0xd9, 0xfb, } numKeys := 1024 privKeyList := randPrivKeyList(curve, numKeys) for n := 0; n < b.N; n++ { randIndex := r.Intn(numKeys - 1) _, _, err := Sign(curve, privKeyList[randIndex], msg) if err != nil { panic("sign failure") } } }
// This example demonstrates decrypting a message using a private key that is // first parsed from raw bytes. func Example_decryptMessage() { // Decode the hex-encoded private key. pkBytes, err := hex.DecodeString("a11b0a4e1a132305652ee7a8eb7848f6ad" + "5ea381e3ce20a2c086a2e388230811") if err != nil { fmt.Println(err) return } privKey, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), pkBytes) ciphertext, err := hex.DecodeString("35f644fbfb208bc71e57684c3c8b437402ca" + "002047a2f1b38aa1a8f1d5121778378414f708fe13ebf7b4a7bb74407288c1958969" + "00207cf4ac6057406e40f79961c973309a892732ae7a74ee96cd89823913b8b8d650" + "a44166dc61ea1c419d47077b748a9c06b8d57af72deb2819d98a9d503efc59fc8307" + "d14174f8b83354fac3ff56075162") // Try decrypting the message. plaintext, err := secp256k1.Decrypt(privKey, ciphertext) if err != nil { fmt.Println(err) return } fmt.Println(string(plaintext)) // Output: // test message }
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 signing a message with a secp256k1 private key that // is first parsed form raw bytes and serializing the generated signature. func Example_signMessage() { // Decode a hex-encoded private key. pkBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2d4f87" + "20ee63e502ee2869afab7de234b80c") if err != nil { fmt.Println(err) return } privKey, pubKey := secp256k1.PrivKeyFromBytes(secp256k1.S256(), pkBytes) // Sign a message using the private key. message := "test message" messageHash := chainhash.HashFuncB([]byte(message)) signature, err := privKey.Sign(messageHash) if err != nil { fmt.Println(err) return } // Serialize and display the signature. fmt.Printf("Serialized Signature: %x\n", signature.Serialize()) // Verify the signature for the message using the public key. verified := signature.Verify(messageHash, pubKey) fmt.Printf("Signature Verified? %v\n", verified) // Output: // Serialized Signature: 3045022100fcc0a8768cfbcefcf2cadd7cfb0fb18ed08dd2e2ae84bef1a474a3d351b26f0302200fc1a350b45f46fa00101391302818d748c2b22615511a3ffd5bb638bd777207 // Signature Verified? true }
// 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) } } }
// Use our actual hashing algorithm here. func TestSignaturesAndRecovery(t *testing.T) { curve := secp256k1.S256() r := rand.New(rand.NewSource(54321)) numSigs := 128 sigList := randSigList(curve, numSigs) for _, tv := range sigList { pubkey := tv.pubkey sig := tv.sig // Make sure we can verify the original signature. _, err := schnorrVerify(curve, sig.Serialize(), pubkey, tv.msg, chainhash.HashFuncB) assert.NoError(t, err) ok := Verify(curve, pubkey, tv.msg, sig.R, sig.S) assert.Equal(t, true, ok) // See if we can recover the public keys OK. var pkRecover *secp256k1.PublicKey pkRecover, _, err = schnorrRecover(curve, sig.Serialize(), tv.msg, chainhash.HashFuncB) assert.NoError(t, err) if err == nil { assert.Equal(t, pubkey.Serialize(), pkRecover.Serialize()) } // Screw up the signature at some random bits and make sure // that breaks it. numBadBits := r.Intn(2) sigBad := sig.Serialize() // (numBadBits*2)+1 --> always odd so at least one bit is different for i := 0; i < (numBadBits*2)+1; i++ { pos := r.Intn(63) bitPos := r.Intn(7) sigBad[pos] ^= 1 << uint8(bitPos) } _, err = schnorrVerify(curve, sigBad, pubkey, tv.msg, chainhash.HashFuncB) assert.Error(t, err) // Make sure it breaks pubkey recovery too. valid := false pkRecover, valid, err = schnorrRecover(curve, sigBad, tv.msg, testSchnorrHash) if valid { assert.NotEqual(t, pubkey.Serialize(), pkRecover.Serialize()) } else { assert.Error(t, err) } } }
func TestSignCompact(t *testing.T) { for i := 0; i < 256; i++ { name := fmt.Sprintf("test %d", i) data := make([]byte, 32) _, err := rand.Read(data) if err != nil { t.Errorf("failed to read random data for %s", name) continue } compressed := i%2 != 0 testSignCompact(t, name, secp256k1.S256(), data, compressed) } }
// 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 TestSignatures(t *testing.T) { for _, test := range signatureTests { var err error if test.der { _, err = secp256k1.ParseDERSignature(test.sig, secp256k1.S256()) } else { _, err = secp256k1.ParseSignature(test.sig, secp256k1.S256()) } if err != nil { if test.isValid { t.Errorf("%s signature failed when shouldn't %v", test.name, err) } /* else { t.Errorf("%s got error %v", test.name, err) } */ continue } if !test.isValid { t.Errorf("%s counted as valid when it should fail", test.name) } } }
func TestSchnorrSigning(t *testing.T) { tRand := rand.New(rand.NewSource(54321)) curve := secp256k1.S256() tvs := GetSigningTestVectors() for _, tv := range tvs { _, pubkey := secp256k1.PrivKeyFromBytes(curve, tv.priv) sig, err := schnorrSign(curve, tv.msg, tv.priv, tv.nonce, nil, nil, testSchnorrHash) assert.NoError(t, err) assert.Equal(t, sig.Serialize(), tv.sig) // Make sure they verify too while we're at it. _, err = schnorrVerify(curve, sig.Serialize(), pubkey, tv.msg, testSchnorrHash) assert.NoError(t, err) // See if we can recover the public keys OK. var pkRecover *secp256k1.PublicKey pkRecover, _, err = schnorrRecover(curve, sig.Serialize(), tv.msg, testSchnorrHash) assert.NoError(t, err) if err == nil { assert.Equal(t, pubkey.Serialize(), pkRecover.Serialize()) } // Screw up the signature at a random bit and make sure that breaks it. sigBad := sig.Serialize() pos := tRand.Intn(63) bitPos := tRand.Intn(7) sigBad[pos] ^= 1 << uint8(bitPos) _, err = schnorrVerify(curve, sigBad, pubkey, tv.msg, testSchnorrHash) assert.Error(t, err) // Make sure it breaks pubkey recovery too. valid := false pkRecover, valid, err = schnorrRecover(curve, sigBad, tv.msg, testSchnorrHash) if valid { assert.NotEqual(t, pubkey.Serialize(), pkRecover.Serialize()) } else { assert.Error(t, err) } } }
//TODO: test different curves as well? func TestBaseMult(t *testing.T) { s256 := secp256k1.S256() for i, e := range s256BaseMultTests { k, ok := new(big.Int).SetString(e.k, 16) if !ok { t.Errorf("%d: bad value for k: %s", i, e.k) } x, y := s256.ScalarBaseMult(k.Bytes()) if fmt.Sprintf("%X", x) != e.x || fmt.Sprintf("%X", y) != e.y { t.Errorf("%d: bad output for k=%s: got (%X, %X), want (%s, %s)", i, e.k, x, y, e.x, e.y) } if testing.Short() && i > 5 { break } } }
func benchmarkVerification(b *testing.B) { curve := secp256k1.S256() r := rand.New(rand.NewSource(54321)) numSigs := 1024 sigList := randSigList(curve, numSigs) for n := 0; n < b.N; n++ { randIndex := r.Intn(numSigs - 1) ver := Verify(curve, sigList[randIndex].pubkey, sigList[randIndex].msg, sigList[randIndex].sig.R, sigList[randIndex].sig.S) if ver != true { panic("made invalid sig") } } }
func TestBaseMultVerify(t *testing.T) { s256 := secp256k1.S256() for bytes := 1; bytes < 40; bytes++ { for i := 0; i < 30; i++ { data := make([]byte, bytes) _, err := rand.Read(data) if err != nil { t.Errorf("failed to read random data for %d", i) continue } x, y := s256.ScalarBaseMult(data) xWant, yWant := s256.ScalarMult(s256.Gx, s256.Gy, data) if x.Cmp(xWant) != 0 || y.Cmp(yWant) != 0 { t.Errorf("%d: bad output for %X: got (%X, %X), want (%X, %X)", i, data, x, y, xWant, yWant) } if testing.Short() && i > 2 { break } } } }
// Test 2: Byte compatibility with Pyelliptic func TestCiphering(t *testing.T) { pb, _ := hex.DecodeString("fe38240982f313ae5afb3e904fb8215fb11af1200592b" + "fca26c96c4738e4bf8f") privkey, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), pb) in := []byte("This is just a test.") out, _ := hex.DecodeString("b0d66e5adaa5ed4e2f0ca68e17b8f2fc02ca002009e3" + "3487e7fa4ab505cf34d98f131be7bd258391588ca7804acb30251e71a04e0020ecf" + "df0f84608f8add82d7353af780fbb28868c713b7813eb4d4e61f7b75d7534dd9856" + "9b0ba77cf14348fcff80fee10e11981f1b4be372d93923e9178972f69937ec850ed" + "6c3f11ff572ddd5b2bedf9f9c0b327c54da02a28fcdce1f8369ffec") dec, err := secp256k1.Decrypt(privkey, out) if err != nil { t.Fatal("failed to decrypt:", err) } if !bytes.Equal(in, dec) { t.Error("decrypted data doesn't match original") } }
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 }
func TestVectors(t *testing.T) { sha := sha1.New() for i, test := range testVectors { pub := secp256k1.PublicKey{ Curve: secp256k1.S256(), X: fromHex(test.Qx), Y: fromHex(test.Qy), } msg, _ := hex.DecodeString(test.msg) sha.Reset() sha.Write(msg) hashed := sha.Sum(nil) sig := secp256k1.Signature{R: fromHex(test.r), S: fromHex(test.s)} if f**k := sig.Verify(hashed, &pub); f**k != test.ok { //t.Errorf("%d: bad result %v %v", i, pub, hashed) t.Errorf("%d: bad result %v instead of %v", i, f**k, test.ok) } if testing.Short() { break } } }
func TestSignAndVerify(t *testing.T) { testSignAndVerify(t, secp256k1.S256(), "S256") }
func TestSchnorrThreshold(t *testing.T) { tRand := rand.New(rand.NewSource(54321)) maxSignatories := 10 numTests := 100 numSignatories := maxSignatories * numTests curve := secp256k1.S256() msg, _ := hex.DecodeString( "07BE073995BF78D440B660AF7B06DC0E9BA120A8D686201989BA99AA384ADF12") privkeys := randPrivKeyList(curve, numSignatories) for i := 0; i < numTests; i++ { numKeysForTest := tRand.Intn(maxSignatories-2) + 2 keyIndex := i * maxSignatories keysToUse := make([]*secp256k1.PrivateKey, numKeysForTest, numKeysForTest) for j := 0; j < numKeysForTest; j++ { keysToUse[j] = privkeys[j+keyIndex] } pubKeysToUse := make([]*secp256k1.PublicKey, numKeysForTest, numKeysForTest) for j := 0; j < numKeysForTest; j++ { _, pubkey := secp256k1.PrivKeyFromBytes(curve, keysToUse[j].Serialize()) pubKeysToUse[j] = pubkey } privNoncesToUse := make([]*secp256k1.PrivateKey, numKeysForTest, numKeysForTest) pubNoncesToUse := make([]*secp256k1.PublicKey, numKeysForTest, numKeysForTest) for j := 0; j < numKeysForTest; j++ { nonce := nonceRFC6979(keysToUse[j].Serialize(), msg, nil, BlakeVersionStringRFC6979) privNonce, pubNonce := secp256k1.PrivKeyFromBytes(curve, nonce) privNoncesToUse[j] = privNonce pubNoncesToUse[j] = pubNonce } partialSignatures := make([]*Signature, numKeysForTest, numKeysForTest) // Partial signature generation. for j := range keysToUse { thisPubNonce := pubNoncesToUse[j] localPubNonces := make([]*secp256k1.PublicKey, numKeysForTest-1, numKeysForTest-1) itr := 0 for _, pubNonce := range pubNoncesToUse { if bytes.Equal(thisPubNonce.Serialize(), pubNonce.Serialize()) { continue } localPubNonces[itr] = pubNonce itr++ } publicNonceSum := CombinePubkeys(curve, localPubNonces) sig, err := schnorrPartialSign(curve, msg, keysToUse[j].Serialize(), privNoncesToUse[j].Serialize(), publicNonceSum, chainhash.HashFuncB) assert.NoError(t, err) partialSignatures[j] = sig } // Combine signatures. combinedSignature, err := CombineSigs(curve, partialSignatures) assert.NoError(t, err) // Combine pubkeys. allPubkeys := make([]*secp256k1.PublicKey, numKeysForTest, numKeysForTest) for j, pubkey := range pubKeysToUse { allPubkeys[j] = pubkey } allPksSum := CombinePubkeys(curve, allPubkeys) // Verify the combined signature and public keys. ok, err := schnorrVerify(curve, combinedSignature.Serialize(), allPksSum, msg, chainhash.HashFuncB) assert.NoError(t, err) assert.Equal(t, true, ok) // Corrupt some memory and make sure it breaks something. corruptWhat := tRand.Intn(3) randItem := tRand.Intn(numKeysForTest - 1) // Corrupt private key. if corruptWhat == 0 { privSerCorrupt := keysToUse[randItem].Serialize() pos := tRand.Intn(31) bitPos := tRand.Intn(7) privSerCorrupt[pos] ^= 1 << uint8(bitPos) keysToUse[randItem].D.SetBytes(privSerCorrupt) } // Corrupt public key. if corruptWhat == 1 { pubXCorrupt := BigIntToEncodedBytes(pubKeysToUse[randItem].GetX()) pos := tRand.Intn(31) bitPos := tRand.Intn(7) pubXCorrupt[pos] ^= 1 << uint8(bitPos) pubKeysToUse[randItem].GetX().SetBytes(pubXCorrupt[:]) } // Corrupt private nonce. if corruptWhat == 2 { privSerCorrupt := privNoncesToUse[randItem].Serialize() pos := tRand.Intn(31) bitPos := tRand.Intn(7) privSerCorrupt[pos] ^= 1 << uint8(bitPos) privNoncesToUse[randItem].D.SetBytes(privSerCorrupt) } // Corrupt public nonce. if corruptWhat == 3 { pubXCorrupt := BigIntToEncodedBytes(pubNoncesToUse[randItem].GetX()) pos := tRand.Intn(31) bitPos := tRand.Intn(7) pubXCorrupt[pos] ^= 1 << uint8(bitPos) pubNoncesToUse[randItem].GetX().SetBytes(pubXCorrupt[:]) } for j := range keysToUse { thisPubNonce := pubNoncesToUse[j] localPubNonces := make([]*secp256k1.PublicKey, numKeysForTest-1, numKeysForTest-1) itr := 0 for _, pubNonce := range pubNoncesToUse { if bytes.Equal(thisPubNonce.Serialize(), pubNonce.Serialize()) { continue } localPubNonces[itr] = pubNonce itr++ } publicNonceSum := CombinePubkeys(curve, localPubNonces) sig, _ := schnorrPartialSign(curve, msg, keysToUse[j].Serialize(), privNoncesToUse[j].Serialize(), publicNonceSum, chainhash.HashFuncB) partialSignatures[j] = sig } // Combine signatures. combinedSignature, _ = CombineSigs(curve, partialSignatures) // Combine pubkeys. allPubkeys = make([]*secp256k1.PublicKey, numKeysForTest, numKeysForTest) for j, pubkey := range pubKeysToUse { allPubkeys[j] = pubkey } allPksSum = CombinePubkeys(curve, allPubkeys) // Nothing that makes it here should be valid. if allPksSum != nil && combinedSignature != nil { ok, _ = schnorrVerify(curve, combinedSignature.Serialize(), allPksSum, msg, chainhash.HashFuncB) assert.Equal(t, false, ok) } } }
func TestSchnorrThresholdRef(t *testing.T) { curve := secp256k1.S256() tvs := GetThresholdTestVectors() for _, tv := range tvs { partialSignatures := make([]*Signature, len(tv.signers), len(tv.signers)) // Ensure all the pubkey and nonce derivation is correct. for i, signer := range tv.signers { nonce := nonceRFC6979(signer.privkey, tv.msg, nil, Sha256VersionStringRFC6979) assert.Equal(t, nonce, signer.privateNonce) _, pubkey := secp256k1.PrivKeyFromBytes(curve, signer.privkey) assert.Equal(t, pubkey.Serialize(), signer.pubkey.Serialize()) _, pubNonce := secp256k1.PrivKeyFromBytes(curve, nonce) assert.Equal(t, pubNonce.Serialize(), signer.publicNonce.Serialize()) // Calculate the public nonce sum. pubKeys := make([]*secp256k1.PublicKey, len(tv.signers)-1, len(tv.signers)-1) itr := 0 for _, signer := range tv.signers { if bytes.Equal(signer.publicNonce.Serialize(), tv.signers[i].publicNonce.Serialize()) { continue } pubKeys[itr] = signer.publicNonce itr++ } publicNonceSum := CombinePubkeys(curve, pubKeys) assert.Equal(t, publicNonceSum, signer.pubKeySumLocal) sig, err := schnorrPartialSign(curve, tv.msg, signer.privkey, nonce, publicNonceSum, testSchnorrSha256Hash) assert.NoError(t, err) assert.Equal(t, sig.Serialize(), signer.partialSignature) partialSignatures[i] = sig } // Combine signatures. combinedSignature, err := CombineSigs(curve, partialSignatures) assert.NoError(t, err) assert.Equal(t, combinedSignature.Serialize(), tv.combinedSignature) // Combine pubkeys. allPubkeys := make([]*secp256k1.PublicKey, len(tv.signers), len(tv.signers)) for i, signer := range tv.signers { allPubkeys[i] = signer.pubkey } allPksSum := CombinePubkeys(curve, allPubkeys) // Verify the combined signature and public keys. ok, err := schnorrVerify(curve, combinedSignature.Serialize(), allPksSum, tv.msg, testSchnorrSha256Hash) assert.NoError(t, err) assert.Equal(t, true, ok) } }
parseSignature func(sigStr []byte) (Signature, error) recoverCompact func(signature, hash []byte) (PublicKey, bool, error) // ECDSA generateKey func(rand io.Reader) ([]byte, *big.Int, *big.Int, error) sign func(priv PrivateKey, hash []byte) (r, s *big.Int, err error) verify func(pub PublicKey, hash []byte, r, s *big.Int) bool // Symmetric cipher encryption generateSharedSecret func(privkey []byte, x, y *big.Int) []byte encrypt func(x, y *big.Int, in []byte) ([]byte, error) decrypt func(privkey []byte, in []byte) ([]byte, error) } var ( secp256k1Curve = secp256k1.S256() ) // Boilerplate exported functions to make the struct interact with the interface. // Constants func (sp secp256k1DSA) GetP() *big.Int { return sp.getP() } func (sp secp256k1DSA) GetN() *big.Int { return sp.getN() } // EC Math func (sp secp256k1DSA) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { return sp.add(x1, y1, x2, y2) }
// TestSignatureSerialize ensures that serializing signatures works as expected. func TestSignatureSerialize(t *testing.T) { tests := []struct { name string ecsig *secp256k1.Signature expected []byte }{ // signature from decred blockchain tx // 0437cd7f8525ceed2324359c2d0ba26006d92d85 { "valid 1 - r and s most significant bits are zero", &secp256k1.Signature{ R: fromHex("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"), S: fromHex("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"), }, []byte{ 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd, 0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, }, }, // signature from decred blockchain tx // cb00f8a0573b18faa8c4f467b049f5d202bf1101d9ef2633bc611be70376a4b4 { "valid 2 - r most significant bit is one", &secp256k1.Signature{ R: fromHex("0082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"), S: fromHex("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"), }, []byte{ 0x30, 0x45, 0x02, 0x21, 0x00, 0x82, 0x23, 0x5e, 0x21, 0xa2, 0x30, 0x00, 0x22, 0x73, 0x8d, 0xab, 0xb8, 0xe1, 0xbb, 0xd9, 0xd1, 0x9c, 0xfb, 0x1e, 0x7a, 0xb8, 0xc3, 0x0a, 0x23, 0xb0, 0xaf, 0xbb, 0x8d, 0x17, 0x8a, 0xbc, 0xf3, 0x02, 0x20, 0x24, 0xbf, 0x68, 0xe2, 0x56, 0xc5, 0x34, 0xdd, 0xfa, 0xf9, 0x66, 0xbf, 0x90, 0x8d, 0xeb, 0x94, 0x43, 0x05, 0x59, 0x6f, 0x7b, 0xdc, 0xc3, 0x8d, 0x69, 0xac, 0xad, 0x7f, 0x9c, 0x86, 0x87, 0x24, }, }, // signature from decred blockchain tx // fda204502a3345e08afd6af27377c052e77f1fefeaeb31bdd45f1e1237ca5470 { "valid 3 - s most significant bit is one", &secp256k1.Signature{ R: fromHex("1cadddc2838598fee7dc35a12b340c6bde8b389f7bfd19a1252a17c4b5ed2d71"), S: new(big.Int).Add(fromHex("00c1a251bbecb14b058a8bd77f65de87e51c47e95904f4c0e9d52eddc21c1415ac"), secp256k1.S256().N), }, []byte{ 0x30, 0x45, 0x02, 0x20, 0x1c, 0xad, 0xdd, 0xc2, 0x83, 0x85, 0x98, 0xfe, 0xe7, 0xdc, 0x35, 0xa1, 0x2b, 0x34, 0x0c, 0x6b, 0xde, 0x8b, 0x38, 0x9f, 0x7b, 0xfd, 0x19, 0xa1, 0x25, 0x2a, 0x17, 0xc4, 0xb5, 0xed, 0x2d, 0x71, 0x02, 0x21, 0x00, 0xc1, 0xa2, 0x51, 0xbb, 0xec, 0xb1, 0x4b, 0x05, 0x8a, 0x8b, 0xd7, 0x7f, 0x65, 0xde, 0x87, 0xe5, 0x1c, 0x47, 0xe9, 0x59, 0x04, 0xf4, 0xc0, 0xe9, 0xd5, 0x2e, 0xdd, 0xc2, 0x1c, 0x14, 0x15, 0xac, }, }, { "zero signature", &secp256k1.Signature{ R: big.NewInt(0), S: big.NewInt(0), }, []byte{0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00}, }, } for i, test := range tests { result := test.ecsig.Serialize() if !bytes.Equal(result, test.expected) { t.Errorf("Serialize #%d (%s) unexpected result:\n"+ "got: %x\nwant: %x", i, test.name, result, test.expected) } } }
func TestRFC6979(t *testing.T) { // Test vectors matching Trezor and CoreBitcoin implementations. // - https://github.com/trezor/trezor-crypto/blob/9fea8f8ab377dc514e40c6fd1f7c89a74c1d8dc6/tests.c#L432-L453 // - https://github.com/oleganza/CoreBitcoin/blob/e93dd71207861b5bf044415db5fa72405e7d8fbc/CoreBitcoin/BTCKey%2BTests.m#L23-L49 tests := []struct { key string msg string nonce string signature string }{ { "cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50", "sample", "2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3", "3045022100af340daf02cc15c8d5d08d7735dfe6b98a474ed373bdb5fbecf7571be52b384202205009fb27f37034a9b24b707b7c6b79ca23ddef9e25f7282e8a797efe53a8f124", }, { // This signature hits the case when S is higher than halforder. // If S is not canonicalized (lowered by halforder), this test will fail. "0000000000000000000000000000000000000000000000000000000000000001", "Satoshi Nakamoto", "8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15", "3045022100934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d802202442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5", }, { "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "Satoshi Nakamoto", "33a19b60e25fb6f4435af53a3d42d493644827367e6453928554f43e49aa6f90", "3045022100fd567d121db66e382991534ada77a6bd3106f0a1098c231e47993447cd6af2d002206b39cd0eb1bc8603e159ef5c20a5c8ad685a45b06ce9bebed3f153d10d93bed5", }, { "f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181", "Alan Turing", "525a82b70e67874398067543fd84c83d30c175fdc45fdeee082fe13b1d7cfdf1", "304402207063ae83e7f62bbb171798131b4a0564b956930092b33b07b395615d9ec7e15c022058dfcc1e00a35e1572f366ffe34ba0fc47db1e7189759b9fb233c5b05ab388ea", }, { "0000000000000000000000000000000000000000000000000000000000000001", "All those moments will be lost in time, like tears in rain. Time to die...", "38aa22d72376b4dbc472e06c3ba403ee0a394da63fc58d88686c611aba98d6b3", "30450221008600dbd41e348fe5c9465ab92d23e3db8b98b873beecd930736488696438cb6b0220547fe64427496db33bf66019dacbf0039c04199abb0122918601db38a72cfc21", }, { "e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2", "There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!", "1f4b84c23a86a221d233f2521be018d9318639d5b8bbd6374a8a59232d16ad3d", "3045022100b552edd27580141f3b2a5463048cb7cd3e047b97c9f98076c32dbdf85a68718b0220279fa72dd19bfae05577e06c7c0c1900c371fcd5893f7e1d56a37d30174671f6", }, } for i, test := range tests { privKey, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), decodeHex(test.key)) hash := sha256.Sum256([]byte(test.msg)) // Ensure deterministically generated nonce is the expected value. gotNonce := secp256k1.TstNonceRFC6979(privKey.D, hash[:]).Bytes() wantNonce := decodeHex(test.nonce) if !bytes.Equal(gotNonce, wantNonce) { t.Errorf("NonceRFC6979 #%d (%s): Nonce is incorrect: "+ "%x (expected %x)", i, test.msg, gotNonce, wantNonce) continue } // Ensure deterministically generated signature is the expected value. gotSig, err := privKey.Sign(hash[:]) if err != nil { t.Errorf("Sign #%d (%s): unexpected error: %v", i, test.msg, err) continue } gotSigBytes := gotSig.Serialize() wantSigBytes := decodeHex(test.signature) if !bytes.Equal(gotSigBytes, wantSigBytes) { t.Errorf("Sign #%d (%s): mismatched signature: %x "+ "(expected %x)", i, test.msg, gotSigBytes, wantSigBytes) continue } } }
func TestKeyGeneration(t *testing.T) { testKeyGeneration(t, secp256k1.S256(), "S256") }
func TestCipheringErrors(t *testing.T) { privkey, err := secp256k1.GeneratePrivateKey(secp256k1.S256()) if err != nil { t.Fatal("failed to generate private key") } tests1 := []struct { ciphertext []byte // input ciphertext }{ {bytes.Repeat([]byte{0x00}, 133)}, // errInputTooShort {bytes.Repeat([]byte{0x00}, 134)}, // errUnsupportedCurve {bytes.Repeat([]byte{0x02, 0xCA}, 134)}, // errInvalidXLength {bytes.Repeat([]byte{0x02, 0xCA, 0x00, 0x20}, 134)}, // errInvalidYLength {[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xCA, 0x00, 0x20, // curve and X length 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, // Y length 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Y 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ciphertext 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MAC 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}, // invalid pubkey {[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xCA, 0x00, 0x20, // curve and X length 0x11, 0x5C, 0x42, 0xE7, 0x57, 0xB2, 0xEF, 0xB7, // X 0x67, 0x1C, 0x57, 0x85, 0x30, 0xEC, 0x19, 0x1A, 0x13, 0x59, 0x38, 0x1E, 0x6A, 0x71, 0x12, 0x7A, 0x9D, 0x37, 0xC4, 0x86, 0xFD, 0x30, 0xDA, 0xE5, 0x00, 0x20, // Y length 0x7E, 0x76, 0xDC, 0x58, 0xF6, 0x93, 0xBD, 0x7E, // Y 0x70, 0x10, 0x35, 0x8C, 0xE6, 0xB1, 0x65, 0xE4, 0x83, 0xA2, 0x92, 0x10, 0x10, 0xDB, 0x67, 0xAC, 0x11, 0xB1, 0xB5, 0x1B, 0x65, 0x19, 0x53, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ciphertext // padding not aligned to 16 bytes 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MAC 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}, // errInvalidPadding {[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xCA, 0x00, 0x20, // curve and X length 0x11, 0x5C, 0x42, 0xE7, 0x57, 0xB2, 0xEF, 0xB7, // X 0x67, 0x1C, 0x57, 0x85, 0x30, 0xEC, 0x19, 0x1A, 0x13, 0x59, 0x38, 0x1E, 0x6A, 0x71, 0x12, 0x7A, 0x9D, 0x37, 0xC4, 0x86, 0xFD, 0x30, 0xDA, 0xE5, 0x00, 0x20, // Y length 0x7E, 0x76, 0xDC, 0x58, 0xF6, 0x93, 0xBD, 0x7E, // Y 0x70, 0x10, 0x35, 0x8C, 0xE6, 0xB1, 0x65, 0xE4, 0x83, 0xA2, 0x92, 0x10, 0x10, 0xDB, 0x67, 0xAC, 0x11, 0xB1, 0xB5, 0x1B, 0x65, 0x19, 0x53, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ciphertext 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MAC 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}, // ErrInvalidMAC } for i, test := range tests1 { _, err = secp256k1.Decrypt(privkey, test.ciphertext) if err == nil { t.Errorf("Decrypt #%d did not get error", i) } } // test error from removePKCSPadding tests2 := []struct { in []byte // input data }{ {bytes.Repeat([]byte{0x11}, 17)}, {bytes.Repeat([]byte{0x07}, 15)}, } for i, test := range tests2 { _, err = secp256k1.TstRemovePKCSPadding(test.in) if err == nil { t.Errorf("removePKCSPadding #%d did not get error", i) } } }
func TestOnCurve(t *testing.T) { s256 := secp256k1.S256() if !s256.IsOnCurve(s256.Params().Gx, s256.Params().Gy) { t.Errorf("FAIL S256") } }