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:

1 Answer 1

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

2
  • It complains about NameError: name 'checksum' is not defined
    – uak
    Sep 17, 2023 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, 2023 at 16:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.