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) } } }
// 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 }
// 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 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 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 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 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) } } }
/*- - Tx genrates a hex-encoded string that can be sent to a bitcoin node, or - blockchain.info/pushtx to broadcast and submite a transaction to the bitcoin - network. - Args: - fromPrivateKeyWif => is wallet owner's privateKey, Wif stand for - wallet import fromat. refer to https://lh4.googleusercontent.com - /-p8yVJXqY7fg/UuLaPjMDtyI/AAAAAAAAWYQ/QoenRIBO1O4/s2048/bitcoinkeys.png - for various key types in btc. - toAddress => reciver's address. Public key and address are the same. - amount => the amount to be debited from the owner, and sent to the reciver. -*/ func Tx(fromPrivateKeyWif string, toAddress string, amount float64) (string, error) { var signedScript bytes.Buffer transferAmount := uint64(amount * 100000000) /*- all required key types -*/ fromPrivateKeyBytes := base58CheckDecodeKey(fromPrivateKeyWif) fromPrivateKeyStruct, fromPublicKeyStruct := btcec.PrivKeyFromBytes( btcec.S256(), fromPrivateKeyBytes) fromPublicKeyBytes := publicKeyStructToPublicKeyBytes(fromPublicKeyStruct) fromPublicKeyBase58 := base58CheckEncodeKey(byte(0), publicKeyHash(fromPublicKeyBytes)) /*- build inputs and outputs -*/ input, change, err := getUnspent(fromPublicKeyBase58, transferAmount) if err != nil { return err.Error(), err } output := make([]*tx_out, 1, 2) output[0] = new(tx_out) output[0].address = toAddress output[0].amount = transferAmount /*- add the mining fees -*/ if change > miningFees { outputChange := new(tx_out) outputChange.address = fromPublicKeyBase58 outputChange.amount = change - miningFees output = append(output, outputChange) } else { output[0].amount -= miningFees } /*- build hash of raw transaction for signing -*/ rawTxTemp := makeRawTx(input, makeScriptPubKey(fromPublicKeyBase58), output) if rawTxTemp == nil { return "", errors.New("Deformed output address") } tx := append(rawTxTemp, uint32Bytes(1)...) tx_hash0 := sha256.Sum256(tx) tx_hash := sha256.Sum256(tx_hash0[:]) tempSig, _ := fromPrivateKeyStruct.Sign(tx_hash[:]) signature := append(tempSig.Serialize(), byte(1)) /*- build script_sig -*/ signedScript.Write(formatVarInt(len(signature))) signedScript.Write(signature) signedScript.Write(formatVarInt(len(fromPublicKeyBytes))) signedScript.Write(fromPublicKeyBytes) /*- return the hex-encoded signed transaction -*/ return hex.EncodeToString(makeRawTx(input, signedScript.Bytes(), output)), nil }
func main() { lines := bufio.NewReader(os.Stdin) hasher := fastsha256.New() for { line, _, err := lines.ReadLine() if err != nil { break } hasher.Reset() hasher.Write(line) sum := hasher.Sum(nil) _, pub := btcec.PrivKeyFromBytes(btcec.S256(), sum) var apk, _ = btcutil.NewAddressPubKey(pub.SerializeUncompressed(), btcwire.MainNet) fmt.Println(apk.EncodeAddress()) apk, _ = btcutil.NewAddressPubKey(pub.SerializeCompressed(), btcwire.MainNet) fmt.Println(apk.EncodeAddress()) } }
// DecodeWIF creates a new WIF structure by decoding the string encoding of // the import format. // // The WIF string must be a base58-encoded string of the following byte // sequence: // // * 1 byte to identify the network, must be 0x80 for mainnet or 0xef for // either testnet3 or the regression test network // * 32 bytes of a binary-encoded, big-endian, zero-padded private key // * Optional 1 byte (equal to 0x01) if the address being imported or exported // was created by taking the RIPEMD160 after SHA256 hash of a serialized // compressed (33-byte) public key // * 4 bytes of checksum, must equal the first four bytes of the double SHA256 // of every byte before the checksum in this sequence // // If the base58-decoded byte sequence does not match this, DecodeWIF will // return a non-nil error. ErrMalformedPrivateKey is returned when the WIF // is of an impossible length or the expected compressed pubkey magic number // does not equal the expected value of 0x01. ErrChecksumMismatch is returned // if the expected WIF checksum does not match the calculated checksum. func DecodeWIF(wif string) (*WIF, error) { decoded := Base58Decode(wif) decodedLen := len(decoded) var compress bool // Length of base58 decoded WIF must be 32 bytes + an optional 1 byte // (0x01) if compressed, plus 1 byte for netID + 4 bytes of checksum. switch decodedLen { case 1 + btcec.PrivKeyBytesLen + 1 + 4: if decoded[33] != compressMagic { return nil, ErrMalformedPrivateKey } compress = true case 1 + btcec.PrivKeyBytesLen + 4: compress = false default: return nil, ErrMalformedPrivateKey } // Checksum is first four bytes of double SHA256 of the identifier byte // and privKey. Verify this matches the final 4 bytes of the decoded // private key. var tosum []byte if compress { tosum = decoded[:1+btcec.PrivKeyBytesLen+1] } else { tosum = decoded[:1+btcec.PrivKeyBytesLen] } cksum := btcwire.DoubleSha256(tosum)[:4] if !bytes.Equal(cksum, decoded[decodedLen-4:]) { return nil, ErrChecksumMismatch } netID := decoded[0] privKeyBytes := decoded[1 : 1+btcec.PrivKeyBytesLen] privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) return &WIF{privKey, compress, netID}, nil }
/*- - Retrives the public key from the currusponding private key. Only one public key - exists for a private key. The public key would be the wallet owner's address. */ func GetPublicKey(privateKeyWif string) string { privateKeyBytes := base58CheckDecodeKey(privateKeyWif) _, publicKeyStrut := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes) publicKeyHash := publicKeyHash(publicKeyStructToPublicKeyBytes(publicKeyStrut)) return base58CheckEncodeKey(0, publicKeyHash) }
func TestWatchingWalletExport(t *testing.T) { const keypoolSize = 10 createdAt := &BlockStamp{} w, err := NewWallet("banana wallet", "A wallet for testing.", []byte("banana"), tstNetParams, createdAt, keypoolSize) if err != nil { t.Error("Error creating new wallet: " + err.Error()) return } // Maintain a set of the active addresses in the wallet. activeAddrs := make(map[addressKey]struct{}) // Add root address. activeAddrs[getAddressKey(w.LastChainedAddress())] = struct{}{} // Get as many new active addresses as necessary to deplete the keypool. // This is done as we will want to test that new addresses created by // the watching wallet do not pull from previous public keys in the // original keypool. for i := 0; i < keypoolSize; i++ { apkh, err := w.NextChainedAddress(createdAt, keypoolSize) if err != nil { t.Errorf("unable to get next address: %v", err) return } activeAddrs[getAddressKey(apkh)] = struct{}{} } // Create watching wallet from w. ww, err := w.ExportWatchingWallet() if err != nil { t.Errorf("Could not create watching wallet: %v", err) return } // Verify correctness of wallet flags. if ww.flags.useEncryption { t.Errorf("Watching wallet marked as using encryption (but nothing to encrypt).") return } if !ww.flags.watchingOnly { t.Errorf("Wallet should be watching-only but is not marked so.") return } // Verify that all flags are set as expected. if ww.keyGenerator.flags.encrypted { t.Errorf("Watching root address should not be encrypted (nothing to encrypt)") return } if ww.keyGenerator.flags.hasPrivKey { t.Errorf("Watching root address marked as having a private key.") return } if !ww.keyGenerator.flags.hasPubKey { t.Errorf("Watching root address marked as missing a public key.") return } if ww.keyGenerator.flags.createPrivKeyNextUnlock { t.Errorf("Watching root address marked as needing a private key to be generated later.") return } for apkh, waddr := range ww.addrMap { switch addr := waddr.(type) { case *btcAddress: if addr.flags.encrypted { t.Errorf("Chained address should not be encrypted (nothing to encrypt)") return } if addr.flags.hasPrivKey { t.Errorf("Chained address marked as having a private key.") return } if !addr.flags.hasPubKey { t.Errorf("Chained address marked as missing a public key.") return } if addr.flags.createPrivKeyNextUnlock { t.Errorf("Chained address marked as needing a private key to be generated later.") return } case *scriptAddress: t.Errorf("Chained address was a script!") return default: t.Errorf("Chained address unknown type!") return } if _, ok := activeAddrs[apkh]; !ok { t.Errorf("Address from watching wallet not found in original wallet.") return } delete(activeAddrs, apkh) } if len(activeAddrs) != 0 { t.Errorf("%v address(es) were not exported to watching wallet.", len(activeAddrs)) return } // Check that the new addresses created by each wallet match. The // original wallet is unlocked so the keypool is refilled and chained // addresses use the previous' privkey, not pubkey. if err := w.Unlock([]byte("banana")); err != nil { t.Errorf("Unlocking original wallet failed: %v", err) } for i := 0; i < keypoolSize; i++ { addr, err := w.NextChainedAddress(createdAt, keypoolSize) if err != nil { t.Errorf("Cannot get next chained address for original wallet: %v", err) return } waddr, err := ww.NextChainedAddress(createdAt, keypoolSize) if err != nil { t.Errorf("Cannot get next chained address for watching wallet: %v", err) return } if addr.EncodeAddress() != waddr.EncodeAddress() { t.Errorf("Next addresses for each wallet do not match eachother.") return } } // Test that ExtendActiveAddresses for the watching wallet match // manually requested addresses of the original wallet. newAddrs := make([]btcutil.Address, 0, keypoolSize) for i := 0; i < keypoolSize; i++ { addr, err := w.NextChainedAddress(createdAt, keypoolSize) if err != nil { t.Errorf("Cannot get next chained address for original wallet: %v", err) return } newAddrs = append(newAddrs, addr) } newWWAddrs, err := ww.ExtendActiveAddresses(keypoolSize, keypoolSize) if err != nil { t.Errorf("Cannot extend active addresses for watching wallet: %v", err) return } for i := range newAddrs { if newAddrs[i].EncodeAddress() != newWWAddrs[i].EncodeAddress() { t.Errorf("Extended active addresses do not match manually requested addresses.") return } } // Test ExtendActiveAddresses for the original wallet after manually // requesting addresses for the watching wallet. newWWAddrs = make([]btcutil.Address, 0, keypoolSize) for i := 0; i < keypoolSize; i++ { addr, err := ww.NextChainedAddress(createdAt, keypoolSize) if err != nil { t.Errorf("Cannot get next chained address for watching wallet: %v", err) return } newWWAddrs = append(newWWAddrs, addr) } newAddrs, err = w.ExtendActiveAddresses(keypoolSize, keypoolSize) if err != nil { t.Errorf("Cannot extend active addresses for original wallet: %v", err) return } for i := range newAddrs { if newAddrs[i].EncodeAddress() != newWWAddrs[i].EncodeAddress() { t.Errorf("Extended active addresses do not match manually requested addresses.") return } } // Test (de)serialization of watching wallet. buf := new(bytes.Buffer) _, err = ww.WriteTo(buf) if err != nil { t.Errorf("Cannot write watching wallet: %v", err) return } ww2 := new(Wallet) _, err = ww2.ReadFrom(buf) if err != nil { t.Errorf("Cannot read watching wallet: %v", err) return } // Check that (de)serialized watching wallet matches the exported wallet. if !reflect.DeepEqual(ww, ww2) { t.Error("Exported and read-in watching wallets do not match.") return } // Verify that nonsensical functions fail with correct error. if err := ww.Lock(); err != ErrWalletIsWatchingOnly { t.Errorf("Nonsensical func Lock returned no or incorrect error: %v", err) return } if err := ww.Unlock([]byte("banana")); err != ErrWalletIsWatchingOnly { t.Errorf("Nonsensical func Unlock returned no or incorrect error: %v", err) return } generator, err := ww.Address(w.keyGenerator.Address()) if err != nil { t.Errorf("generator isnt' present in wallet") } gpk := generator.(PubKeyAddress) if _, err := gpk.PrivKey(); err != ErrWalletIsWatchingOnly { t.Errorf("Nonsensical func AddressKey returned no or incorrect error: %v", err) return } if _, err := ww.ExportWatchingWallet(); err != ErrWalletIsWatchingOnly { t.Errorf("Nonsensical func ExportWatchingWallet returned no or incorrect error: %v", err) return } pk, _ := btcec.PrivKeyFromBytes(btcec.S256(), make([]byte, 32)) wif, err := btcutil.NewWIF(pk, tstNetParams, true) if err != nil { t.Fatal(err) } if _, err := ww.ImportPrivateKey(wif, createdAt); err != ErrWalletIsWatchingOnly { t.Errorf("Nonsensical func ImportPrivateKey returned no or incorrect error: %v", err) return } }