0

I'm trying to convert a compressed WIF generated by bitcoinaddress python Library but I couldn't find a function to do the task so I collected one. I would like someone to review my code and maybe remove unnecessary steps and enhance it.

# Script to convert compressed WIF to private key then to uncompressed WIF.

import hashlib import base58 import binascii from binascii import hexlify, unhexlify

def doubleSha256(hex): """Double sha256 function""" bin = binascii.unhexlify(hex) # perform SHA-256 hash on the private_key hash_1st = hashlib.sha256(bin).digest() # perform SHA-256 on the previous SHA-256 hash hash_2nd = hashlib.sha256(hash_1st).digest() return binascii.hexlify(hash_2nd)

Testnet WIF

private_key_WIF = "cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm" # compressed

~ private_key_WIF_uncompressed = "93QEdCzUrzMRsnbx2YuF6MsNjxQA6iWSrv9e2wX4NM4UmYzUsLn"

first_decode = base58.b58decode(private_key_WIF) private_key_full = binascii.hexlify(first_decode)

Check if the key is mainnet or testnet

if private_key_full.startswith(b"80"): testnet = False elif private_key_full.startswith(b"ef"): testnet = True

private_key_full = private_key_full[2:-8]

if private_key_full.endswith(b"01"): private_key_full = private_key_full[:-2]

if not testnet: # prepended mainnet version byte to private key text = b"80" + private_key_full elif testnet: # prepended testnet version byte to private key text = b"ef" + private_key_full

Perfrom double sha256 on string

double_sha256 = doubleSha256(text)

create a checksum using the first 4 bytes of the previous SHA-256 hash

checksum = double_sha256[0:8]

append the 4 checksum bytes to the private_key

private_key_with_checksum = text+checksum

convert mainnet_private_key + checksum into base58 encoded string

uncompressed_wif = base58.b58encode(binascii.unhexlify(private_key_with_checksum)) print(f"{uncompressed_wif=}")

Resources:

Murch
  • 75,206
  • 34
  • 186
  • 622
uak
  • 1
  • 1

1 Answers1

0

if you want to convert a compressed WIF to an uncompressed WIF, you would need to:

  1. decode the compressed WIF
  2. extract the private key
  3. remove the suffix
  4. recompute the checksum
  5. encode it back in base58

Here's one way you can implement it:

def decompress_WIF(compressed_wif):
    hex_data = binascii.b2a_hex(base58.b58decode(compressed_wif)).decode()
    if len(hex_data) != 76:
        raise ValueError("Invalid length for a compressed WIF")
    prefix = hex_data[:2]
    suffix = hex_data[-10:-8]
    original_checksum = hex_data[-8:]
    xpriv = hex_data[2:-10]
    if suffix != "01":
        raise ValueError("The provided WIF is not a compressed key")
    if checksum(prefix + xpriv + suffix) != original_checksum:
        raise ValueError("Invalid checksum in the provided WIF")
    new_checksum = checksum(prefix + xpriv)
    uncompressed_wif = base58.b58encode(binascii.a2b_hex(prefix + xpriv + new_checksum)).decode()
    return uncompressed_wif

Note that this code does not check the version byte at all

leslie
  • 52
  • 6
  • It complains about NameError: name 'checksum' is not defined – uak Sep 17 '23 at 16:18
  • @uak Of course, you need to define it! You can recode the checksum function, here's one example: def checksum(data): return sha256(sha256(binascii.a2b_hex(data)).digest()).hexdigest()[:8] – leslie Sep 17 '23 at 16:56