func SignMessage(privKey string, message string, compress bool) string { prefixBytes := []byte("Bitcoin Signed Message:\n") messageBytes := []byte(message) bytes := []byte{} bytes = append(bytes, byte(len(prefixBytes))) bytes = append(bytes, prefixBytes...) bytes = append(bytes, byte(len(messageBytes))) bytes = append(bytes, messageBytes...) privKeyBytes := HexDecode(privKey) x, y := btcec.S256().ScalarBaseMult(privKeyBytes) ecdsaPubKey := ecdsa.PublicKey{ Curve: btcec.S256(), X: x, Y: y, } ecdsaPrivKey := &ecdsa.PrivateKey{ PublicKey: ecdsaPubKey, D: new(big.Int).SetBytes(privKeyBytes), } sigbytes, err := btcec.SignCompact(btcec.S256(), ecdsaPrivKey, btcwire.DoubleSha256(bytes), compress) if err != nil { panic(err) } return base64.StdEncoding.EncodeToString(sigbytes) }
func TestEncodeDecodeWIF(t *testing.T) { priv1, _ := btcec.PrivKeyFromBytes(btcec.S256(), []byte{ 0x0c, 0x28, 0xfc, 0xa3, 0x86, 0xc7, 0xa2, 0x27, 0x60, 0x0b, 0x2f, 0xe5, 0x0b, 0x7c, 0xae, 0x11, 0xec, 0x86, 0xd3, 0xbf, 0x1f, 0xbe, 0x47, 0x1b, 0xe8, 0x98, 0x27, 0xe1, 0x9d, 0x72, 0xaa, 0x1d}) priv2, _ := btcec.PrivKeyFromBytes(btcec.S256(), []byte{ 0xdd, 0xa3, 0x5a, 0x14, 0x88, 0xfb, 0x97, 0xb6, 0xeb, 0x3f, 0xe6, 0xe9, 0xef, 0x2a, 0x25, 0x81, 0x4e, 0x39, 0x6f, 0xb5, 0xdc, 0x29, 0x5f, 0xe9, 0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98}) wif1, err := NewWIF(priv1, &btcnet.MainNetParams, false) if err != nil { t.Fatal(err) } wif2, err := NewWIF(priv2, &btcnet.TestNet3Params, true) if err != nil { t.Fatal(err) } tests := []struct { wif *WIF encoded string }{ { wif1, "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ", }, { wif2, "cV1Y7ARUr9Yx7BR55nTdnR7ZXNJphZtCCMBTEZBJe1hXt2kB684q", }, } for _, test := range tests { // Test that encoding the WIF structure matches the expected string. s := test.wif.String() if s != test.encoded { t.Errorf("TestEncodeDecodePrivateKey failed: want '%s', got '%s'", test.encoded, s) continue } // Test that decoding the expected string results in the original WIF // structure. w, err := DecodeWIF(test.encoded) if err != nil { t.Error(err) continue } if got := w.String(); got != test.encoded { t.Errorf("NewWIF failed: want '%v', got '%v'", test.wif, got) } } }
// Verifies a hash using DER encoded signature func Verify(pubKey, signature, hash []byte) (bool, error) { sig, err := btcec.ParseDERSignature(signature, btcec.S256()) if err != nil { return false, err } pk, err := btcec.ParsePubKey(pubKey, btcec.S256()) if err != nil { return false, nil } return sig.Verify(hash, pk), nil }
func TestPrivKeys(t *testing.T) { for _, test := range privKeyTests { _, pub := btcec.PrivKeyFromBytes(btcec.S256(), test.key) _, err := btcec.ParsePubKey( pub.SerializeUncompressed(), btcec.S256()) if err != nil { t.Errorf("%s privkey: %v", test.name, err) continue } } }
func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyBytes []byte) { x, y := btcec.S256().ScalarBaseMult(privKeyBytes) pub := (*btcec.PublicKey)(&ecdsa.PublicKey{ Curve: btcec.S256(), X: x, Y: y, }) if compress { return pub.SerializeCompressed() } return pub.SerializeUncompressed() }
// NewKeyFromString returns a new extended key instance from a base58-encoded // extended key. func NewKeyFromString(key string) (*ExtendedKey, error) { // The base58-decoded extended key must consist of a serialized payload // plus an additional 4 bytes for the checksum. decoded := btcutil.Base58Decode(key) if len(decoded) != serializedKeyLen+4 { return nil, ErrInvalidKeyLen } // The serialized format is: // version (4) || depth (1) || parent fingerprint (4)) || // child num (4) || chain code (32) || key data (33) || checksum (4) // Split the payload and checksum up and ensure the checksum matches. payload := decoded[:len(decoded)-4] checkSum := decoded[len(decoded)-4:] expectedCheckSum := btcwire.DoubleSha256(payload)[:4] if !bytes.Equal(checkSum, expectedCheckSum) { return nil, ErrBadChecksum } // Deserialize each of the payload fields. version := payload[:4] depth := uint16(payload[4:5][0]) parentFP := payload[5:9] childNum := binary.BigEndian.Uint32(payload[9:13]) chainCode := payload[13:45] keyData := payload[45:78] // The key data is a private key if it starts with 0x00. Serialized // compressed pubkeys either start with 0x02 or 0x03. isPrivate := keyData[0] == 0x00 if isPrivate { // Ensure the private key is valid. It must be within the range // of the order of the secp256k1 curve and not be 0. keyData = keyData[1:] keyNum := new(big.Int).SetBytes(keyData) if keyNum.Cmp(btcec.S256().N) >= 0 || keyNum.Sign() == 0 { return nil, ErrUnusableSeed } } else { // Ensure the public key parses correctly and is actually on the // secp256k1 curve. _, err := btcec.ParsePubKey(keyData, btcec.S256()) if err != nil { return nil, err } } return newExtendedKey(version, keyData, chainCode, parentFP, depth, childNum, isPrivate), nil }
func TestPrivKeys(t *testing.T) { for _, test := range privKeyTests { x, y := btcec.S256().ScalarBaseMult(test.key) pub := (*btcec.PublicKey)(&ecdsa.PublicKey{ Curve: btcec.S256(), X: x, Y: y, }) _, err := btcec.ParsePubKey(pub.SerializeUncompressed(), btcec.S256()) if err != nil { t.Errorf("%s privkey: %v", test.name, err) continue } } }
// NewAddressPubKey returns a new AddressPubKey which represents a pay-to-pubkey // address. The serializedPubKey parameter must be a valid pubkey and can be // uncompressed, compressed, or hybrid. The net parameter must be // btcwire.MainNet or btcwire.TestNet3. func NewAddressPubKey(serializedPubKey []byte, net btcwire.BitcoinNet) (*AddressPubKey, error) { pubKey, err := btcec.ParsePubKey(serializedPubKey, btcec.S256()) if err != nil { return nil, err } // Set the format of the pubkey. This probably should be returned // from btcec, but do it here to avoid API churn. We already know the // pubkey is valid since it parsed above, so it's safe to simply examine // the leading byte to get the format. pkFormat := PKFUncompressed switch serializedPubKey[0] { case 0x02: fallthrough case 0x03: pkFormat = PKFCompressed case 0x06: fallthrough case 0x07: pkFormat = PKFHybrid } ecPubKey := (*btcec.PublicKey)(pubKey) addr := &AddressPubKey{pubKeyFormat: pkFormat, pubKey: ecPubKey, net: net} return addr, nil }
// pubKeyBytes returns bytes for the serialized compressed public key associated // with this extended key in an efficient manner including memoization as // necessary. // // When the extended key is already a public key, the key is simply returned as // is since it's already in the correct form. However, when the extended key is // a private key, the public key will be calculated and memoized so future // accesses can simply return the cached result. func (k *ExtendedKey) pubKeyBytes() []byte { // Just return the key if it's already an extended public key. if !k.isPrivate { return k.key } // This is a private extended key, so calculate and memoize the public // key if needed. if len(k.pubKey) == 0 { pkx, pky := btcec.S256().ScalarBaseMult(k.key) pubKey := btcec.PublicKey{Curve: btcec.S256(), X: pkx, Y: pky} k.pubKey = pubKey.SerializeCompressed() } return k.pubKey }
// BenchmarkSigVerify benchmarks how long it takes the secp256k1 curve to // verify signatures. func BenchmarkSigVerify(b *testing.B) { b.StopTimer() // Randomly generated keypair. // Private key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d pubKey := ecdsa.PublicKey{ Curve: btcec.S256(), X: fromHex("d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab"), Y: fromHex("ab65528eefbb8057aa85d597258a3fbd481a24633bc9b47a9aa045c91371de52"), } // Double sha256 of []byte{0x01, 0x02, 0x03, 0x04} msgHash := fromHex("8de472e2399610baaa7f84840547cd409434e31f5d3bd71e4d947f283874f9c0") sigR := fromHex("fef45d2892953aa5bbcdb057b5e98b208f1617a7498af7eb765574e29b5d9c2c") sigS := fromHex("d47563f52aac6b04b55de236b7c515eb9311757db01e02cff079c3ca6efb063f") if !ecdsa.Verify(&pubKey, msgHash.Bytes(), sigR, sigS) { b.Errorf("Signature failed to verify") return } b.StartTimer() for i := 0; i < b.N; i++ { ecdsa.Verify(&pubKey, msgHash.Bytes(), sigR, sigS) } }
// NewMaster creates a new master node for use in creating a hierarchical // deterministic key chain. The seed must be between 128 and 512 bits and // should be generated by a cryptographically secure random generation source. // // NOTE: There is an extremely small chance (< 1 in 2^127) the provided seed // will derive to an unusable secret key. The ErrUnusable error will be // returned if this should occur, so the caller must check for it and generate a // new seed accordingly. func NewMaster(seed []byte) (*ExtendedKey, error) { // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes { return nil, ErrInvalidSeedLen } // First take the HMAC-SHA512 of the master key and the seed data: // I = HMAC-SHA512(Key = "Bitcoin seed", Data = S) hmac512 := hmac.New(sha512.New, masterKey) hmac512.Write(seed) lr := hmac512.Sum(nil) // Split "I" into two 32-byte sequences Il and Ir where: // Il = master secret key // Ir = master chain code secretKey := lr[:len(lr)/2] chainCode := lr[len(lr)/2:] // Ensure the key in usable. secretKeyNum := new(big.Int).SetBytes(secretKey) if secretKeyNum.Cmp(btcec.S256().N) >= 0 || secretKeyNum.Sign() == 0 { return nil, ErrUnusableSeed } parentFP := []byte{0x00, 0x00, 0x00, 0x00} return newExtendedKey(btcnet.MainNetParams.HDPrivateKeyID[:], secretKey, chainCode, parentFP, 0, 0, true), nil }
// BechmarkScalarBaseMult benchmarks the secp256k1 curve ScalarBaseMult // function. func BechmarkScalarBaseMult(b *testing.B) { k := fromHex("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575") curve := btcec.S256() for i := 0; i < b.N; i++ { curve.ScalarBaseMult(k.Bytes()) } }
// 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 := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes) // Sign a message using the private key. message := "test message" messageHash := btcwire.DoubleSha256([]byte(message)) signature, err := privKey.Sign(messageHash) if err != nil { fmt.Println(err) return } // Serialize and display the signature. // // NOTE: This is commented out for the example since the signature // produced uses random numbers and therefore will always be different. //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: // Signature Verified? true }
func TestPubKeys(t *testing.T) { for _, test := range pubKeyTests { pk, err := btcec.ParsePubKey(test.key, btcec.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 btcec.TstPubkeyUncompressed: pkStr = (*btcec.PublicKey)(pk).SerializeUncompressed() case btcec.TstPubkeyCompressed: pkStr = (*btcec.PublicKey)(pk).SerializeCompressed() case btcec.TstPubkeyHybrid: pkStr = (*btcec.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) } } }
func TestVectors(t *testing.T) { sha := sha1.New() for i, test := range testVectors { pub := ecdsa.PublicKey{ Curve: btcec.S256(), X: fromHex(test.Qx), Y: fromHex(test.Qy), } msg, _ := hex.DecodeString(test.msg) sha.Reset() sha.Write(msg) hashed := sha.Sum(nil) r := fromHex(test.r) s := fromHex(test.s) if f**k := ecdsa.Verify(&pub, hashed, r, s); 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 } } }
/*- - Genrates randomized private key, ounce genrated you can call GetPublicKey to - retrive the public key. -*/ func GenRandPrivateKey() string { privateKeyStrut, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { panic("unable to genrate basic keys") } return base58CheckEncodeKey(0x80, privateKeyStrut.D.Bytes()) }
func newKey(priv, inc *big.Int, f genFunc) *baseKey { pk := big.NewInt(0).Set(priv) for ; f(pk); inc.Add(inc, one) { pk.SetBytes(Sha512Half(inc.Bytes())) } privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), pk.Bytes()) return &baseKey{*privKey} }
func addPoints(a []byte, b []byte) []byte { ap, err := btcec.ParsePubKey(a, btcec.S256()) if err != nil { panic(err) } bp, err := btcec.ParsePubKey(b, btcec.S256()) if err != nil { panic(err) } sumX, sumY := btcec.S256().Add(ap.X, ap.Y, bp.X, bp.Y) sum := (*btcec.PublicKey)(&ecdsa.PublicKey{ Curve: btcec.S256(), X: sumX, Y: sumY, }) return sum.SerializeCompressed() }
// ECPrivKey converts the extended key to a btcec private key and returns it. // As you might imagine this is only possible if the extended key is a private // extended key (as determined by the IsPrivate function). The ErrNotPrivExtKey // error will be returned if this function is called on a public extended key. func (k *ExtendedKey) ECPrivKey() (*btcec.PrivateKey, error) { if !k.isPrivate { return nil, ErrNotPrivExtKey } privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), k.key) return privKey, nil }
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 := btcec.PrivKeyFromBytes(btcec.S256(), test.key) _, err := btcec.ParsePubKey( pub.SerializeUncompressed(), btcec.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) } } }
// BenchmarkScalarMult benchmarks the secp256k1 curve ScalarMult function. func BenchmarkScalarMult(b *testing.B) { x := fromHex("34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6") y := fromHex("0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232") k := fromHex("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575") curve := btcec.S256() for i := 0; i < b.N; i++ { curve.ScalarMult(x, y, k.Bytes()) } }
//TODO: test more curves? func BenchmarkBaseMult(b *testing.B) { b.ResetTimer() s256 := btcec.S256() e := s256BaseMultTests[0] //TODO: check, used to be 25 instead of 0, but it's probably ok k, _ := new(big.Int).SetString(e.k, 16) b.StartTimer() for i := 0; i < b.N; i++ { s256.ScalarBaseMult(k.Bytes()) } }
func DecodeECDSAPublicKey(b []byte) (*ecdsa.PublicKey, error) { var p []big.Int buf := bytes.NewBuffer(b) dec := gob.NewDecoder(buf) err := dec.Decode(&p) if err != nil { return nil, err } return &ecdsa.PublicKey{Curve: btcec.S256(), X: &p[0], Y: &p[1]}, nil }
// TstAddressPubKey makes an AddressPubKey, setting the unexported fields with // the parameters. func TstAddressPubKey(serializedPubKey []byte, pubKeyFormat PubKeyFormat, net btcwire.BitcoinNet) *AddressPubKey { pubKey, _ := btcec.ParsePubKey(serializedPubKey, btcec.S256()) return &AddressPubKey{ pubKeyFormat: pubKeyFormat, pubKey: (*btcec.PublicKey)(pubKey), net: net, } }
// TstAddressPubKey makes an AddressPubKey, setting the unexported fields with // the parameters. func TstAddressPubKey(serializedPubKey []byte, pubKeyFormat PubKeyFormat, netID byte) *AddressPubKey { pubKey, _ := btcec.ParsePubKey(serializedPubKey, btcec.S256()) return &AddressPubKey{ pubKeyFormat: pubKeyFormat, pubKey: (*btcec.PublicKey)(pubKey), pubKeyHashID: netID, } }
func newKey(priv, inc *big.Int, f genFunc) (*baseKey, error) { pk := big.NewInt(0).Set(priv) for ; f(pk); inc.Add(inc, one) { b, err := Sha512Half(inc.Bytes()) if err != nil { return nil, err } pk.SetBytes(b) } privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), pk.Bytes()) return &baseKey{*privKey}, nil }
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, btcec.S256(), data, compressed) } }
func TestSignatures(t *testing.T) { for _, test := range signatureTests { var err error if test.der { _, err = btcec.ParseDERSignature(test.sig, btcec.S256()) } else { _, err = btcec.ParseSignature(test.sig, btcec.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) } } }
// 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 := btcec.ParsePubKey(pubKeyBytes, btcec.S256()) if err != nil { fmt.Println(err) return } // Decode hex-encoded serialized signature. sigBytes, err := hex.DecodeString("30450220090ebfb3690a0ff115bb1b38b" + "8b323a667b7653454f1bccb06d4bbdca42c2079022100ec95778b51e707" + "1cb1205f8bde9af6592fc978b0452dafe599481c46d6b2e479") if err != nil { fmt.Println(err) return } signature, err := btcec.ParseSignature(sigBytes, btcec.S256()) if err != nil { fmt.Println(err) return } // Verify the signature for the message using the public key. message := "test message" messageHash := btcwire.DoubleSha256([]byte(message)) verified := signature.Verify(messageHash, pubKey) fmt.Println("Signature Verified?", verified) // Output: // Signature Verified? true }
func DecodeECDSAPrivateKey(b []byte) (*ecdsa.PrivateKey, error) { var p []big.Int buf := bytes.NewBuffer(b) dec := gob.NewDecoder(buf) err := dec.Decode(&p) if err != nil { return nil, err } privateKey := new(ecdsa.PrivateKey) privateKey.PublicKey.Curve = btcec.S256() privateKey.PublicKey.X = &p[0] privateKey.PublicKey.Y = &p[1] privateKey.D = &p[2] return privateKey, nil }