mirror of
https://github.com/bitcoinbook/bitcoinbook
synced 2025-02-16 17:42:06 +00:00
CH04::legacy addresses: remove code examples
We instead provide an example for bech32 addresses, which are now the preferred format.
This commit is contained in:
parent
74c144bbf4
commit
132094b670
143
ch04.asciidoc
143
ch04.asciidoc
@ -1579,149 +1579,6 @@ because it has the added +01+ suffix to distinguish it from an
|
|||||||
"uncompressed" one.((("", startref="KAaddress04")))
|
"uncompressed" one.((("", startref="KAaddress04")))
|
||||||
====
|
====
|
||||||
|
|
||||||
=== Implementing Keys and Addresses in Cpass:[++]
|
|
||||||
|
|
||||||
Let's look at the complete process of creating a Bitcoin address, from a
|
|
||||||
private key, to a public key (a point on the elliptic curve), to a
|
|
||||||
double-hashed address, and finally, the Base58Check encoding. The C++
|
|
||||||
code in <<addr_example>> shows the complete step-by-step process, from
|
|
||||||
private key to Base58Check-encoded Bitcoin address. The code example
|
|
||||||
uses the libbitcoin library introduced in <<alt_libraries>> for some
|
|
||||||
helper functions.
|
|
||||||
|
|
||||||
[[addr_example]]
|
|
||||||
.Creating a Base58Check-encoded Bitcoin address from a private key
|
|
||||||
====
|
|
||||||
[role="c_less_space"]
|
|
||||||
[source, cpp]
|
|
||||||
----
|
|
||||||
include::code/addr.cpp[]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
The code uses a predefined private key to produce the same Bitcoin
|
|
||||||
address every time it is run, as shown in <<addr_example_run>>.((("",
|
|
||||||
startref="base5804")))((("", startref="Abase5804")))
|
|
||||||
|
|
||||||
[[addr_example_run]]
|
|
||||||
.Compiling and running the addr code
|
|
||||||
====
|
|
||||||
[source,bash]
|
|
||||||
----
|
|
||||||
# Compile the addr.cpp code
|
|
||||||
$ g++ -o addr addr.cpp -std=c++11 $(pkg-config --cflags --libs libbitcoin)
|
|
||||||
# Run the addr executable
|
|
||||||
$ ./addr
|
|
||||||
Public key: 0202a406624211f2abbdc68da3df929f938c3399dd79fac1b51b0e4ad1d26a47aa
|
|
||||||
Address: 1PRTTaJesdNovgne6Ehcdu1fpEdX7913CK
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
[TIP]
|
|
||||||
====
|
|
||||||
The code in <<addr_example_run>> produces a Bitcoin address (+1PRTT...+)
|
|
||||||
from a _compressed_ public key (see <<comp_pub>>). If you used the
|
|
||||||
uncompressed public key instead, it would produce a different Bitcoin
|
|
||||||
address (+14K1y...+).
|
|
||||||
====
|
|
||||||
|
|
||||||
=== Implementing Keys and Addresses in Python
|
|
||||||
|
|
||||||
((("keys and addresses", "implementing in Python",
|
|
||||||
id="KApython04")))((("pybitcointools")))The most comprehensive bitcoin
|
|
||||||
library in Python is
|
|
||||||
https://github.com/vbuterin/pybitcointools[pybitcointools] by Vitalik
|
|
||||||
Buterin. In <<key-to-address_script>>, we use the pybitcointools library
|
|
||||||
(imported as "bitcoin") to generate and display keys and addresses in
|
|
||||||
various formats.
|
|
||||||
|
|
||||||
[[key-to-address_script]]
|
|
||||||
.Key and address generation and formatting with the pybitcointools library
|
|
||||||
====
|
|
||||||
[source,python]
|
|
||||||
----
|
|
||||||
include::code/key-to-address-ecc-example.py[]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
<<key-to-address_script_run>> shows the output from running this code.
|
|
||||||
|
|
||||||
[[key-to-address_script_run]]
|
|
||||||
.Running key-to-address-ecc-example.py
|
|
||||||
====
|
|
||||||
++++
|
|
||||||
<pre data-type="programlisting">
|
|
||||||
$ python key-to-address-ecc-example.py
|
|
||||||
Private Key (hex) is:
|
|
||||||
3aba4162c7251c891207b747840551a71939b0de081f85c4e44cf7c13e41daa6
|
|
||||||
Private Key (decimal) is:
|
|
||||||
26563230048437957592232553826663696440606756685920117476832299673293013768870
|
|
||||||
Private Key (WIF) is:
|
|
||||||
5JG9hT3beGTJuUAmCQEmNaxAuMacCTfXuw1R3FCXig23RQHMr4K
|
|
||||||
Private Key Compressed (hex) is:
|
|
||||||
3aba4162c7251c891207b747840551a71939b0de081f85c4e44cf7c13e41daa601
|
|
||||||
Private Key (WIF-Compressed) is:
|
|
||||||
KyBsPXxTuVD82av65KZkrGrWi5qLMah5SdNq6uftawDbgKa2wv6S
|
|
||||||
Public Key (x,y) coordinates is:
|
|
||||||
(41637322786646325214887832269588396900663353932545912953362782457239403430124L,
|
|
||||||
16388935128781238405526710466724741593761085120864331449066658622400339362166L)
|
|
||||||
Public Key (hex) is:
|
|
||||||
045c0de3b9c8ab18dd04e3511243ec2952002dbfadc864b9628910169d9b9b00ec↵
|
|
||||||
243bcefdd4347074d44bd7356d6a53c495737dd96295e2a9374bf5f02ebfc176
|
|
||||||
Compressed Public Key (hex) is:
|
|
||||||
025c0de3b9c8ab18dd04e3511243ec2952002dbfadc864b9628910169d9b9b00ec
|
|
||||||
Bitcoin Address (b58check) is:
|
|
||||||
1thMirt546nngXqyPEz532S8fLwbozud8
|
|
||||||
Compressed Bitcoin Address (b58check) is:
|
|
||||||
14cxpo3MBCYYWCgF74SWTdcmxipnGUsPw3
|
|
||||||
</pre>
|
|
||||||
++++
|
|
||||||
====
|
|
||||||
|
|
||||||
<<ec_math>> is another example, using the Python ECDSA library for the
|
|
||||||
elliptic curve math and without using any specialized bitcoin libraries.
|
|
||||||
|
|
||||||
[[ec_math]]
|
|
||||||
.A script demonstrating elliptic curve math used for bitcoin keys
|
|
||||||
====
|
|
||||||
[source, python]
|
|
||||||
----
|
|
||||||
include::code/ec-math.py[]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
<<ec_math_run>> shows the output produced by running this script.
|
|
||||||
|
|
||||||
[NOTE]
|
|
||||||
====
|
|
||||||
<<ec_math>> ((("random numbers", "os.urandom",
|
|
||||||
see="entropy")))((("entropy", "os.urandom", see="random
|
|
||||||
numbers")))((("random numbers", "random number
|
|
||||||
generation")))((("entropy", "random number generation")))uses
|
|
||||||
+os.urandom+, which reflects a cryptographically secure random number
|
|
||||||
generator (CSRNG) provided by the underlying operating system. Caution:
|
|
||||||
Depending on the OS, +os.urandom+ may _not_ be implemented with
|
|
||||||
sufficient security or seeded properly and may _not_ be appropriate for
|
|
||||||
generating production-quality bitcoin keys.((("",
|
|
||||||
startref="KApython04")))
|
|
||||||
====
|
|
||||||
|
|
||||||
[[ec_math_run]]
|
|
||||||
.Installing the Python ECDSA library and running the ec_math.py script
|
|
||||||
====
|
|
||||||
----
|
|
||||||
$ # Install Python PIP package manager
|
|
||||||
$ sudo apt-get install python-pip
|
|
||||||
$ # Install the Python ECDSA library
|
|
||||||
$ sudo pip install ecdsa
|
|
||||||
$ # Run the script
|
|
||||||
$ python ec-math.py
|
|
||||||
Secret: 38090835015954358862481132628887443905906204995912378278060168703580660294000
|
|
||||||
EC point: (70048853531867179489857750497606966272382583471322935454624595540007269312627, 105262206478686743191060800263479589329920209527285803935736021686045542353380)
|
|
||||||
BTC public key: 029ade3effb0a67d5c8609850d797366af428f4a0d5194cb221d807770a1522873
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
=== Advanced Keys and Addresses
|
=== Advanced Keys and Addresses
|
||||||
|
|
||||||
((("keys and addresses", "advanced forms", id="KAadvanced04")))In the
|
((("keys and addresses", "advanced forms", id="KAadvanced04")))In the
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
#include <bitcoin/bitcoin.hpp>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
// Private secret key string as base16
|
|
||||||
bc::ec_secret decoded;
|
|
||||||
bc::decode_base16(decoded,
|
|
||||||
"038109007313a5807b2eccc082c8c3fbb988a973cacf1a7df9ce725c31b14776");
|
|
||||||
|
|
||||||
bc::wallet::ec_private secret(
|
|
||||||
decoded, bc::wallet::ec_private::mainnet_p2kh);
|
|
||||||
|
|
||||||
// Get public key.
|
|
||||||
bc::wallet::ec_public public_key(secret);
|
|
||||||
std::cout << "Public key: " << public_key.encoded() << std::endl;
|
|
||||||
|
|
||||||
// Create Bitcoin address.
|
|
||||||
// Normally you can use:
|
|
||||||
// bc::wallet::payment_address payaddr =
|
|
||||||
// public_key.to_payment_address(
|
|
||||||
// bc::wallet::ec_public::mainnet_p2kh);
|
|
||||||
// const std::string address = payaddr.encoded();
|
|
||||||
|
|
||||||
// Compute hash of public key for P2PKH address.
|
|
||||||
bc::data_chunk public_key_data;
|
|
||||||
public_key.to_data(public_key_data);
|
|
||||||
const auto hash = bc::bitcoin_short_hash(public_key_data);
|
|
||||||
|
|
||||||
bc::data_chunk unencoded_address;
|
|
||||||
// Reserve 25 bytes
|
|
||||||
// [ version:1 ]
|
|
||||||
// [ hash:20 ]
|
|
||||||
// [ checksum:4 ]
|
|
||||||
unencoded_address.reserve(25);
|
|
||||||
// Version byte, 0 is normal BTC address (P2PKH).
|
|
||||||
unencoded_address.push_back(0);
|
|
||||||
// Hash data
|
|
||||||
bc::extend_data(unencoded_address, hash);
|
|
||||||
// Checksum is computed by hashing data, and adding 4 bytes from hash.
|
|
||||||
bc::append_checksum(unencoded_address);
|
|
||||||
// Finally we must encode the result in Bitcoin's base58 encoding.
|
|
||||||
assert(unencoded_address.size() == 25);
|
|
||||||
const std::string address = bc::encode_base58(unencoded_address);
|
|
||||||
|
|
||||||
std::cout << "Address: " << address << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
|||||||
import ecdsa
|
|
||||||
import os
|
|
||||||
|
|
||||||
# secp256k1, http://www.oid-info.com/get/1.3.132.0.10
|
|
||||||
_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
|
||||||
_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
|
||||||
_b = 0x0000000000000000000000000000000000000000000000000000000000000007
|
|
||||||
_a = 0x0000000000000000000000000000000000000000000000000000000000000000
|
|
||||||
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
|
|
||||||
_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
|
|
||||||
curve_secp256k1 = ecdsa.ellipticcurve.CurveFp(_p, _a, _b)
|
|
||||||
generator_secp256k1 = ecdsa.ellipticcurve.Point(curve_secp256k1, _Gx, _Gy, _r)
|
|
||||||
oid_secp256k1 = (1, 3, 132, 0, 10)
|
|
||||||
SECP256k1 = ecdsa.curves.Curve("SECP256k1", curve_secp256k1,
|
|
||||||
generator_secp256k1, oid_secp256k1)
|
|
||||||
ec_order = _r
|
|
||||||
|
|
||||||
curve = curve_secp256k1
|
|
||||||
generator = generator_secp256k1
|
|
||||||
|
|
||||||
|
|
||||||
def random_secret():
|
|
||||||
convert_to_int = lambda array: int("".join(array).encode("hex"), 16)
|
|
||||||
|
|
||||||
# Collect 256 bits of random data from the OS's cryptographically secure
|
|
||||||
# random number generator
|
|
||||||
byte_array = os.urandom(32)
|
|
||||||
|
|
||||||
return convert_to_int(byte_array)
|
|
||||||
|
|
||||||
|
|
||||||
def get_point_pubkey(point):
|
|
||||||
if (point.y() % 2) == 1:
|
|
||||||
key = '03' + '%064x' % point.x()
|
|
||||||
else:
|
|
||||||
key = '02' + '%064x' % point.x()
|
|
||||||
return key.decode('hex')
|
|
||||||
|
|
||||||
|
|
||||||
def get_point_pubkey_uncompressed(point):
|
|
||||||
key = ('04' +
|
|
||||||
'%064x' % point.x() +
|
|
||||||
'%064x' % point.y())
|
|
||||||
return key.decode('hex')
|
|
||||||
|
|
||||||
|
|
||||||
# Generate a new private key.
|
|
||||||
secret = random_secret()
|
|
||||||
print("Secret: ", secret)
|
|
||||||
|
|
||||||
# Get the public key point.
|
|
||||||
point = secret * generator
|
|
||||||
print("EC point:", point)
|
|
||||||
|
|
||||||
print("BTC public key:", get_point_pubkey(point).encode("hex"))
|
|
||||||
|
|
||||||
# Given the point (x, y) we can create the object using:
|
|
||||||
point1 = ecdsa.ellipticcurve.Point(curve, point.x(), point.y(), ec_order)
|
|
||||||
assert(point1 == point)
|
|
@ -1,46 +0,0 @@
|
|||||||
from __future__ import print_function
|
|
||||||
import bitcoin
|
|
||||||
|
|
||||||
# Generate a random private key
|
|
||||||
valid_private_key = False
|
|
||||||
while not valid_private_key:
|
|
||||||
private_key = bitcoin.random_key()
|
|
||||||
decoded_private_key = bitcoin.decode_privkey(private_key, 'hex')
|
|
||||||
valid_private_key = 0 < decoded_private_key < bitcoin.N
|
|
||||||
|
|
||||||
print("Private Key (hex) is: ", private_key)
|
|
||||||
print("Private Key (decimal) is: ", decoded_private_key)
|
|
||||||
|
|
||||||
# Convert private key to WIF format
|
|
||||||
wif_encoded_private_key = bitcoin.encode_privkey(decoded_private_key, 'wif')
|
|
||||||
print("Private Key (WIF) is: ", wif_encoded_private_key)
|
|
||||||
|
|
||||||
# Add suffix "01" to indicate a compressed private key
|
|
||||||
compressed_private_key = private_key + '01'
|
|
||||||
print("Private Key Compressed (hex) is: ", compressed_private_key)
|
|
||||||
|
|
||||||
# Generate a WIF format from the compressed private key (WIF-compressed)
|
|
||||||
wif_compressed_private_key = bitcoin.encode_privkey(
|
|
||||||
bitcoin.decode_privkey(compressed_private_key, 'hex'), 'wif_compressed')
|
|
||||||
print("Private Key (WIF-Compressed) is: ", wif_compressed_private_key)
|
|
||||||
|
|
||||||
# Multiply the EC generator point G with the private key to get a public key point
|
|
||||||
public_key = bitcoin.fast_multiply(bitcoin.G, decoded_private_key)
|
|
||||||
print("Public Key (x,y) coordinates is:", public_key)
|
|
||||||
|
|
||||||
# Encode as hex, prefix 04
|
|
||||||
hex_encoded_public_key = bitcoin.encode_pubkey(public_key, 'hex')
|
|
||||||
print("Public Key (hex) is:", hex_encoded_public_key)
|
|
||||||
|
|
||||||
# Compress public key, adjust prefix depending on whether y is even or odd
|
|
||||||
(public_key_x, public_key_y) = public_key
|
|
||||||
compressed_prefix = '02' if (public_key_y % 2) == 0 else '03'
|
|
||||||
hex_compressed_public_key = compressed_prefix + (bitcoin.encode(public_key_x, 16).zfill(64))
|
|
||||||
print("Compressed Public Key (hex) is:", hex_compressed_public_key)
|
|
||||||
|
|
||||||
# Generate Bitcoin address from public key
|
|
||||||
print("Bitcoin Address (b58check) is:", bitcoin.pubkey_to_address(public_key))
|
|
||||||
|
|
||||||
# Generate compressed Bitcoin address from compressed public key
|
|
||||||
print("Compressed Bitcoin Address (b58check) is:",
|
|
||||||
bitcoin.pubkey_to_address(hex_compressed_public_key))
|
|
Loading…
Reference in New Issue
Block a user