# From Private Key to Bitcoin Address **Published by:** [kootsZhin](https://paragraph.com/@kootszhin/) **Published on:** 2021-11-11 **URL:** https://paragraph.com/@kootszhin/from-private-key-to-bitcoin-address ## Content Okay, so you have heard of the fact that Bitcoin is using a signature algorithm which contains a pair of public key and private key in verifying the identity of the owners. Simply speaking, the public key is just the account name of your wallet and private key the password. At first glance, you may think that the public key is referring to your Bitcoin address, but in fact that is not the case. This article is a step-by-step guide to getting the exact Bitcoin address by looking at its private key. Importing Dependencies In this study, we will need to make use of the below Python libraries. import hashlib import base58 import codecs import ecdsa Converting Private Key to Address Step 0 First of all, we will have to start with a private ECDSA key (basically any series of 32 bytes) and this will be our private key. In this example, we will use the same key from the Bitcoin Wiki. Input private_key = "18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725"private_key Output '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725' Step 1 Next we will have to generate an uncompressed public key from the private key that we have Input # Hex decoding the private key to bytes using codecs library private_key_bytes = codecs.decode(private_key, 'hex')# Generating a public key in bytes using SECP256k1 & ecdsa library public_key_raw = ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1).verifying_key public_key_bytes = public_key_raw.to_string()# Hex encoding the public key from bytes public_key_hex = codecs.encode(public_key_bytes, 'hex')# Bitcoin public key begins with bytes 0x04 so we have to add the bytes at the start public_key = (b'04' + public_key_hex).decode("utf-8")public_key Output '0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6' Step 2 Next we have to compressed our uncompressed public key Input # Checking if the last byte is odd or even if (ord(bytearray.fromhex(public_key[-2:])) % 2 == 0): public_key_compressed = '02' else: public_key_compressed = '03' # Add bytes 0x02 to the X of the key if even or 0x03 if odd public_key_compressed += public_key[2:66] public_key_compressed Output '0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352' Step 3 Perform SHA-256 hashing on the compressed public key Input # Converting to bytearray for SHA-256 hashing hex_str = bytearray.fromhex(public_key_compressed) sha = hashlib.sha256() sha.update(hex_str)sha.hexdigest() # .hexdigest() is hex ASCII Output '0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98' Step 4 Perform RIPMED-160 hashing on the result of SHA-256 Input rip = hashlib.new('ripemd160') rip.update(sha.digest()) key_hash = rip.hexdigest()key_hash # Hash160 Output 'f54a5851e9372b87810a8e60cdd2e7cfd80b6e31' Step 5 Add version byte in front of RIPEMD-160 hash (0x00 for Main Network) Input modified_key_hash = "00" + key_hashmodified_key_hash Output '00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31' Step 6 Perform SHA-256 hash on the extended RIPEMD-160 result (Below steps are called Base58Check encoding) Input sha = hashlib.sha256() hex_str = bytearray.fromhex(modified_key_hash) sha.update(hex_str)sha.hexdigest() Output 'ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c' Step 7 Perform SHA-256 hash on the result of the previous SHA-256 hash Input sha_2 = hashlib.sha256() sha_2.update(sha.digest())sha_2.hexdigest() Output 'c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd' Step 8 Take the first 4 bytes of the second SHA-256 hash, this is the address checksum Input checksum = sha_2.hexdigest()[:8]checksum Output 'c7f18fe8' Step 9 Add the 4 checksum bytes from stage 8 at the end of extended RIPEMD-160 hash from stage 5, this is the 25-byte binary Bitcoin Address Input byte_25_address = modified_key_hash + checksumbyte_25_address Output '00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8' Step 10 (Final Result) Convert the result from a byte string into a base58 string using Base58Check encoding, this is the most commonly used Bitcoin Address format Input address = base58.b58encode(bytes(bytearray.fromhex(byte_25_address))).decode('utf-8')address Output '1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs' Alternative Ways in Converting Hash160 (key hash) into base58 Making use of b58.encode_check from base58 library directly at Step 6 Input key_bytes = codecs.decode(modified_key_hash, 'hex') address = base58.b58encode_check(key_bytes).decode('utf-8')address Output '1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs' ## Publication Information - [kootsZhin](https://paragraph.com/@kootszhin/): Publication homepage - [All Posts](https://paragraph.com/@kootszhin/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@kootszhin): Subscribe to updates - [Twitter](https://twitter.com/kootsZhin): Follow on Twitter