- Saved searches
- Use saved searches to filter your results more quickly
- License
- fortesp/bitcoinaddress
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- Nikolaj-K / bitcoin_priv_key_address_wif.py
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
Bitcoin Wallet Address Generator
License
fortesp/bitcoinaddress
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
Bitcoin Wallet Address Generator
This is a simple Bitcoin non-deterministic wallet address generator coded in Python 3. It generates a Private Key in different formats (hex, wif and compressed wif) and corresponding Public Addresses, raw, P2WPKH addresses starting with prefix 1, P2SH addresses starting with prefix 3 as part of Segwit soft fork and Bech32 addresses with prefix bc1 P2WPKH and P2WSH.
pip install bitcoinaddress
from bitcoinaddress import Wallet wallet = Wallet() print(wallet)
Private Key HEX: 03902e4f09664bc177fe4e090dcd9906b432b50f15fb6151984475c1c75c35b6 Private Key WIF: 5HqrbgkWPqBy6dvCE7FoUiMuiCfFPRdtRsyi6NuCM2np8qBZxq5 Private Key WIF compressed: KwLdv6T2jmhQbswnYrcL9KZHerTpVyjozp1JNjfP5QuD3GchCwCc Public Key: 04c5389a31ce6149c28ba20d14db8540b2319e5a65000a2919fbf7a6296e7840b53f883a9483fb7f2b43f3eacd857c904d1b70ecc168571b64d8f1ab82b57eea88 Public Key compressed: 02c5389a31ce6149c28ba20d14db8540b2319e5a65000a2919fbf7a6296e7840b5 Public Address 1: 1Bu6YxH64nfvhdDsYNEP8PftoBMqgusdPS Public Address 1 compressed: 18i5PtPisxbGiGGEviW7HPcnfNPmcsscwH Public Address 3: 38dRrGx5YbrnRWuWcJv5i2XHjYUnHE2wvv Public Address bc1 P2WPKH: bc1q2jxe5azr6zmhk3258av7ul6cqtu4eu4mps8f4p Public Address bc1 P2WSH: bc1qdveuf0egtfdnd2fnsp0lzfukn2e58czf8323ky6xt8ydew4ecfcqv3ettx
from bitcoinaddress import Wallet wallet = Wallet(testnet=True) print(wallet)
Private Key HEX: 064f8f0bebfa2f65db003b56bc911535614f2764799bc89091398c1aed82e884 Private Key WIF: 91dhN38UTmqGtd3zG1GnDdnyivAP5LnWJQyyj7V7pqthirHAj4X Private Key WIF compressed: cMny9rPzDAt58r8BjECeamPwN1eQSAKrKrrVNsd78AoCjcWxuVym Public Key: 04f7a01e30388dea9673db8cdb48b985441db785382efbcecc05abac079a6304818a907f886b0d0518e345a0288a6f1e09072f2b11d4ccb75bc67ec6c71dfef800 Public Key compressed: 02f7a01e30388dea9673db8cdb48b985441db785382efbcecc05abac079a630481 Public Address 1: mwdHSyBBHMbcy8rogvzssvDrGyffRo3amQ Public Address 1 compressed: n4VzeGfAyZGR7xCXiKmABvnKXojTFJrmKH Public Address 3: 2MtJ3jPSD2AYgbF25fq9cm1aUCPhSmWUMcJ Public Address bc1 P2WPKH: tb1qlsw8qqe2aa2avzn9t9nsfjy8kwwgarwcfvfqlh Public Address bc1 P2WSH: tb1qp53qkcsth8ffuvr00cnlg5hde03aszzeq7y0layklhd4nwkxzejs99tlh3
Example 3 — Import Private Key
from bitcoinaddress import Wallet wallet = Wallet('5HqrbgkWPqBy6dvCE7FoUiMuiCfFPRdtRsyi6NuCM2np8qBZxq5') print(wallet)
Private Key HEX: 03902e4f09664bc177fe4e090dcd9906b432b50f15fb6151984475c1c75c35b6 Private Key WIF: 5HqrbgkWPqBy6dvCE7FoUiMuiCfFPRdtRsyi6NuCM2np8qBZxq5 Private Key WIF compressed: KwLdv6T2jmhQbswnYrcL9KZHerTpVyjozp1JNjfP5QuD3GchCwCc Public Key: 04c5389a31ce6149c28ba20d14db8540b2319e5a65000a2919fbf7a6296e7840b53f883a9483fb7f2b43f3eacd857c904d1b70ecc168571b64d8f1ab82b57eea88 Public Key compressed: 02c5389a31ce6149c28ba20d14db8540b2319e5a65000a2919fbf7a6296e7840b5 Public Address 1: 1Bu6YxH64nfvhdDsYNEP8PftoBMqgusdPS Public Address 1 compressed: 18i5PtPisxbGiGGEviW7HPcnfNPmcsscwH Public Address 3: 38dRrGx5YbrnRWuWcJv5i2XHjYUnHE2wvv Public Address bc1 P2WPKH: bc1q2jxe5azr6zmhk3258av7ul6cqtu4eu4mps8f4p Public Address bc1 P2WSH: bc1qdveuf0egtfdnd2fnsp0lzfukn2e58czf8323ky6xt8ydew4ecfcqv3ettx
Example 4 — Check attributes
from bitcoinaddress import Wallet wallet = Wallet() print(wallet.key.__dict__) print(wallet.key.__dict__['mainnet'].__dict__) print(wallet.key.__dict__['testnet'].__dict__) print(wallet.address.__dict__) print(wallet.address.__dict__['mainnet'].__dict__) print(wallet.address.__dict__['testnet'].__dict__)
Nikolaj-K / bitcoin_priv_key_address_wif.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
«»» |
Discussed in the video |
https://youtu.be/LYN3h5DjeXw |
See e.g. |
https://allbitcoinprivatekeys.com/1 |
* For the following we use Bitcoin specification conventions. |
* Essentially all those notions were around before and later blockchain |
projects are all variations of Bitcoins conventions. |
Relevant for this video: |
* (1) Unformated Private key |
— a.k.a. secret number |
— a.k.a. exponent |
* (2) Public key |
— a.k.a. points |
* (3) Multiplication of points on an eliptic curve |
— Note: Exponentiation is just repeated multiplication, thus (1) |
* (4) Base encodings |
* (6) Hash functions |
* (5) Checksums |
* (6) Blockchain addresses |
* (7) Wallet input format private key (WIF) |
Topic of this video: |
How to get (6) and (7) from (1), i.e. explicitly computing two functions. |
Here (3), (4) and (5) are largely taken as blackbox here. But see videos on my channel. |
Previous related videos: |
Hash functions: |
* VIDEO: What’s a hash and what’s the point? |
https://youtu.be/wZiZjXOpaEs |
* VIDEO: Hash function by analogy? |
https://youtu.be/L-4T-pIJuQw |
* VIDEO: SHA256 live coding on bit-level with Python |
https://youtu.be/UziK-Hqzwi4 |
* VIDEO: Blockchain explained by analogy (focused on the chain of blocks itself) |
https://youtu.be/w3sI8WVX-cc |
Digital signatures: |
* VIDEO: The Elliptic Curve Digital Signature Algorithm and raw transactions on Bitcoin |
https://youtu.be/YZafZ3Rvd8I |
See link therein as well as: |
For use of some of this in a Bitcoin protocol transaction (tx), see |
https://klmoney.wordpress.com/bitcoin-dissecting-transactions-part-1/ |
https://klmoney.wordpress.com/bitcoin-dissecting-transactions-part-2-building-a-transaction-by-hand/ |
* VIDEO: The private key: How to digitally sign a message? |
https://youtu.be/FVc-UOHcajc |
Relevant external Bitcoin wiki links: |
* https://en.bitcoin.it/wiki/Secp256k1 |
* https://en.bitcoin.it/wiki/Base58Check_encoding |
* https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses |
* https://en.bitcoin.it/wiki/Wallet_import_format |
See also the Bitcoin Stackexchange. |
In fact, other projects wiki’s and StackExchanges will help too. |
Needs you to install all the libaries I import from right below and is only guaraneed to run on pyhton 3.7+ |
Don’t write me emails asking how to install python or something of the sort. |
If you ask me something, use an adult sentence structure and attire. |
Disclaimer: Due to potential bugs, don’t use functions from this script for anything of value! |
I have refactored the encodings and played with this script |
a thousand times, so don’t use its routines for anything of value! |
You will anyway find many implementations of those things |
online, especially in Cpp, Java, Rust, Javascript, Python. |
«»» |
import binascii |
import ecdsa |
import hashlib |
from base58 import b58encode # https://github.com/serengil/crypto/blob/master/python/base58.py |
# See also https://en.bitcoin.it/wiki/Base58Check_encoding |
def secret_to_address ( secret , legacy = False ): |
«»» |
1. Exponent (secret private key) to point on curve |
2. Point to x-cooridnate |
3. Coordinate to checksummed obscrurification (address) |
See also |
https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses |
etc. |
«»» |
pubk_pair = from_secret_pubk_point ( secret ) |
compressed_pubk , pubk = _pubk_to_compressed_pubk ( * pubk_pair ) |
address = _pubk_to_address ( pubk ) if legacy else _pubk_to_address ( compressed_pubk ) |
return address |
def from_secret_pubk_point ( secret ): |
«»» |
See also https://en.bitcoin.it/wiki/Secp256k1 |
1. Compute point from secret number (a.k.a (unformated) private key, a.k.a. exponent) |
2. Format pubk_vk |
3. Project out coordinates |
«»» |
CURVE = ecdsa . SECP256k1 |
sk = ecdsa . SigningKey . from_secret_exponent ( secret , curve = CURVE ) |
pubk_vk = sk . verifying_key # the point |
# Note: Rougly g^(secret + x) = g^secret * g^x, where g is a point that comes with the curve spec. |
# Note: 0 < secret < _r (see SECP256k1 for max secret) |
pubk = binascii . b2a_hex ( pubk_vk . to_string ()). decode ( ‘ascii’ ) |
pubk_x = pubk [: 64 ] |
pubk_y = pubk [ 64 :] |
#print(f»pubk:\t\npubk_x:\t\npubk_y:\t\n») |
return pubk_x , pubk_y |
def _pubk_to_compressed_pubk ( pubk_x , pubk_y ): |
«»» |
Prefix pubk_x with info about pubk_y. |
Note: |
print(f’Uncompressed pubk: 04 ‘) |
«»» |
EVEN_PREFIX = ’02’ |
UNEVEN_PREFIX = ’03’ |
LEGACY_PREFIX = ’04’ |
# Prepend parity information |
y_parity = ord ( bytearray . fromhex ( pubk_y [ — 2 :])) % 2 |
prefix = EVEN_PREFIX if y_parity == 0 else UNEVEN_PREFIX |
compressed_pubk = prefix + pubk_x |
#print(f»y_parity:\t\t, compressed_pubk: «) |
pubk = LEGACY_PREFIX + pubk_x + pubk_y |
return compressed_pubk , pubk |
def _pubk_to_address ( pubk ): |
«»» |
Hash and checksum the pubk. |
Note: No discussion of Pay-to-ScriptHash addresses («3..») here but only Pay-to-PubKeyHash («1..») |
Newer SegWit addresses («bc..») are a deviation in some details. |
«»» |
pubk_array = bytearray . fromhex ( pubk ) |
# Compute key_hash |
sha = hashlib . sha256 () # See Nikolaj-K videos |
sha . update ( pubk_array ) |
rip = hashlib . new ( ‘ripemd160’ ) |
rip . update ( sha . digest ()) |
PREFIX = ’00’ |
key_hash = PREFIX + rip . hexdigest () # .hexdigest() is hex ASCII |
#print(f»key_hash:\t\t») |
# Compute checksum to append to key_hash |
sha = hashlib . sha256 () |
sha . update ( bytearray . fromhex ( key_hash )) |
checksum = sha . digest () |
sha = hashlib . sha256 () |
sha . update ( checksum ) |
checksum = sha . hexdigest ()[ 0 : 8 ] |
# Append checksum |
address_hex = key_hash + checksum |
# expected encoding |
bs = bytes ( bytearray . fromhex ( address_hex )) |
address = b58encode ( bs ). decode ( ‘utf-8’ ) |
return address |
def secret_to_wif ( secret ): |
«»» |
See also |
https://en.bitcoin.it/wiki/Wallet_import_format |
etc. |
«»» |
# Cast / Format |
PREFIX = «80» |
hex_string = hex ( secret )[ 2 :]. zfill ( 64 ) # remove 0x and fill with zeros |
pre_hash = PREFIX + hex_string |
# Compute checksum via hashing |
hash_1 = hashlib . sha256 ( binascii . unhexlify ( pre_hash )). hexdigest () |
hash_2 = hashlib . sha256 ( binascii . unhexlify ( hash_1 )). hexdigest () |
checksum = hash_2 [: 8 ] |
# Append checksum |
pre_hash_checksum = pre_hash + checksum |
# Cast / Format |
from_hex_string = int ( pre_hash_checksum , 16 ) |
def _get ( idx ): |
ALPHABET = ‘123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz’ |
m = 58 ** idx |
idx = from_hex_string // m % 58 |
return ALPHABET [ idx ] |
IDXS = range ( 100 ) # sufficiently long |
wif_str = «» . join ( map ( _get , IDXS )) |
# Reverse |
rev_wif_str = wif_str [:: — 1 ]. lstrip ( ‘1’ ) |
return rev_wif_str |
if __name__ == «__main__» : |
EXAMPLE_PRIVATE_KEYS = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 17 , 18 , 19 , 7000000003 , 9001000007000000003 , 666 ] |
for secret in EXAMPLE_PRIVATE_KEYS : |
# Compute wallet-input-format of private key |
wif = secret_to_wif ( secret ) |
# Compute adresses |
address_legacy = secret_to_address ( secret , True ) |
address = secret_to_address ( secret ) |
print ( |
f»priv key (secret): \t < secret >\n « |
f»priv key (secret wif): \t < wif >\n « |
f»legacy address: \t \t < address_legacy >\n « |
f»address: \t \t < address >\n » + 80 * «-« |
) |