Bitcoin Address Generation in Pure Python - OPSXCQ Blog
Bitcoin Address Generation in Pure Python - OPSXCQ Blog
randomBytes = os.urandom(32)
Next step is to convert the key to a byte array and hash it,
first with SHA-256 then with RIPEMD-160. Then we prepend
the hashed public key with 0x00 if the target network is
the mainnet, if the address generated meant to be used in
the testnet 0x6f must be prepended.
SPEC256k1 = Point()
pk = int.from_bytes(privkey, "big")
hash160 = ripemd160(sha256((SPEC256k1 * pk).toBytes()))
address = b"\x00" + hash160
Checksum
Then the only thing left to add in the address it the
checksum, it is appended to the address and is the last 4
bytes of the double SHA-256 of the address calculated above.
Then just encode the key bytes to base58 and you have your
Bitcoin address !
Source code
This is a reference script, it depends on Python 3 to run
and is self contained, it means no external dependencies are
required to run it. One example of its output:
$ ./bitcoin-address-generator.py
Address: 18jJh1kSPJqbXtMB51SyczgcHL1drkDgxV
Privkey: 5JTEF3GHpDAin1caVqfznHU8T1jscHVVD5SMFALBTC4no2J4DqX
import os
import hashlib
def sha256(data):
digest = hashlib.new("sha256")
digest.update(data)
return digest.digest()
def ripemd160(x):
d = hashlib.new("ripemd160")
d.update(x)
return d.digest()
def b58(data):
B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
if data[0] == 0:
return "1" + b58(data[1:])
return ret
class Point:
def __init__(self,
x=0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
y=0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8,
p=2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1):
self.x = x
self.y = y
self.p = p
for i in range(256):
if other & (1 << i):
q = q + n
n = n + n
return q
if self == other:
l = pow(2 * y2 % p, p-2, p) * (3 * x2 * x2) % p
else:
l = pow(x1 - x2, p-2, p) * (y1 - y2) % p
newX = (l ** 2 - x2 - x1) % p
newY = (l * x2 - l * newX - y2) % p
def toBytes(self):
x = self.x.to_bytes(32, "big")
y = self.y.to_bytes(32, "big")
return b"\x04" + x + y
def getPublicKey(privkey):
SPEC256k1 = Point()
pk = int.from_bytes(privkey, "big")
hash160 = ripemd160(sha256((SPEC256k1 * pk).toBytes()))
address = b"\x00" + hash160
def getWif(privkey):
wif = b"\x80" + privkey
wif = b58(wif + sha256(sha256(wif))[:4])
return wif
if __name__ == "__main__":
randomBytes = os.urandom(32)
print("Address: " + getPublicKey(randomBytes))
print("Privkey: " + getWif(randomBytes))
References
Eliptic curves in cryptography
Bitcoin Address documentation