Have you consulted
https://en.bitcoin.it/wiki/Wallet_import_format page before writing your code?
For example (as pooya87 has already noted):
# Decode the WIF string to a bytes object
wif_bytes = wif.encode()
Wrong. You should be using b58decode function from base58 module or something similar to convert encoded string to bytes.
Therefore, the following two lines are also wrong because you are dealing with improperly decoded string.
And yes, when you calculate a checksum you don't disregard a first byte (you add it instead).
# The last four bytes of the WIF string represent the checksum
checksum = wif_bytes[-4:]
# The private key is the bytes preceding the checksum
private_key_bytes = wif_bytes[1:-4]
Checksum is a
double hash of a byte string, so your calculated checksum is wrong by definition:
calculated_checksum = hashlib.sha256(private_key_bytes).digest()[:4]
Lines like
will never work because you didn't specify encoding (bytes[0].hex() == '80' or b.hex() == f'{0x80:x}' if you like)
wif_bytes[0] == 0xef:
# Compressed WIF
Wrong, it is not compressed WIF, 0xef byte is for testnet keys. In order to determine whether a private key is compressed or uncompressed, you should be checking for 0x01 byte at the end of a private key. However, the more accurate way would be to check against length in bytes. Uncompressed private keys will be 1 byte shorter than compressed.
Something like the following should work:
def wif_to_int_private_key(wif: str) -> int:
import base58
from sha256 import sha256
# https://en.bitcoin.it/wiki/Wallet_import_format
wif_bytes = base58.b58decode(wif)
private_key_bytes, checksum = wif_bytes[:-4], wif_bytes[-4:]
calculated_checksum = sha256(sha256(private_key_bytes))[:4]
if calculated_checksum != checksum:
raise ValueError("Invalid WIF checksum")
private_key = int.from_bytes(private_key_bytes[1:-1]) if len(
private_key_bytes) == 34 else int.from_bytes(private_key_bytes[1:])
return private_key