Este blog é um complemento do nosso canal no YouTube. Clique em @CanalQb para seguir e acompanhar nossos vídeos!

Sugestões de pesquisas

Scanner de Endereços Bitcoin a partir de Faixas de Chaves Privadas

#bitcoin; #enderecosbitcoin; #criptografia

@CanalQb no YouTube


@CanalQb

Scanner de Endereços Bitcoin a partir de Faixas de Chaves Privadas


Sempre crie uma frase de segurança única para jogos, testnets ou airdrops e evite usar sua carteira principal.



Scanner de Endereços Bitcoin a partir de Chaves Privadas

Este artigo apresenta um script em Python avançado capaz de escanear endereços Bitcoin derivados de uma faixa específica de chaves privadas. A ferramenta implementa formatos modernos como Bech32 (BIP173), P2SH-P2WPKH e P2PKH tanto comprimido quanto não comprimido. Também conecta-se a um banco de dados SQLite para verificar se os endereços gerados já foram utilizados.

Funcionamento da Ferramenta

O script inicia com a definição de uma chave privada em hexadecimal e calcula um intervalo de valores a partir dela. Em seguida, cada chave no intervalo é convertida em endereços Bitcoin nos principais formatos. Esses endereços são comparados com um banco de dados local para identificar coincidências conhecidas.

Dependências Utilizadas

  • sqlite3 - Interface para banco de dados SQLite.
  • math e decimal - Utilizadas para cálculos de entropia.
  • hashlib e base58 - Para funções criptográficas.
  • bit - Biblioteca Bitcoin para Python (documentação oficial).

Codificação Bech32 (BIP173)

A codificação Bech32 permite criar endereços do tipo Segwit com maior tolerância a erros e menor risco de colisões. O script implementa funções conforme o padrão BIP173 para gerar endereços a partir da chave pública.

Funções para Bech32

  • bech32_polymod: cálculo do checksum.
  • bech32_hrp_expand: expansão do prefixo HRP ("bc").
  • bech32_create_checksum: geração do checksum.
  • convertbits: conversão de bits para formato base 5.
  • bech32_encode: construção final do endereço.

Intervalo de Chaves Privadas

Uma chave privada hexadecimal é transformada em inteiro decimal e usada para definir um intervalo com define_interval. Esse intervalo é explorado para gerar múltiplas chaves e endereços:

privkey_hex = "00000000000000000000000000000000000000000000000000000000000000e0"
low, high, pk_int = define_interval(privkey_hex)

Exemplo de saída:

  • Chave privada (hex): 000000...e0
  • Intervalo: 224 - 287 (decimal)
  • Entropia (log2): log2(224) a log2(287)

Verificação em Banco de Dados

Após a geração dos endereços, o script conecta-se ao banco SQLite configurado com a tabela enderecos. Cada endereço gerado é verificado se existe no banco, o que pode ser útil para estudos sobre endereços conhecidos ou reutilizados.

Formatos de Endereços Gerados

Para cada chave privada no intervalo, são gerados os seguintes formatos de endereço:

  • P2PKH (não comprimido): padrão antigo usado amplamente até hoje.
  • P2PKH (comprimido): versão mais compacta da chave pública.
  • P2SH-P2WPKH: compatível com carteiras antigas mas com suporte parcial a Segwit.
  • Bech32 (P2WPKH): formato nativo Segwit mais moderno.

Exemplo de resultado

P2PKH (não comprimido)    1ExampleUncompressedAddress...
P2PKH (comprimido)        1ExampleCompressedAddress...
P2SH-P2WPKH               3ExampleP2SHAddress...
Bech32 (P2WPKH)           bc1examplebech32address...
WIF não comprimido:       5KExampleUncompressedWIF...
WIF comprimido:           LExampleCompressedWIF...

Exportação de Resultados

Os resultados encontrados são salvos no arquivo enderecos_encontrados.txt para futura análise, com separação entre cada grupo de dados.

Considerações de Segurança

Este script é destinado a fins educacionais e de auditoria. Não é recomendado utilizá-lo para gerar carteiras reais. Nunca reutilize ou compartilhe suas chaves privadas.

Aviso: O uso de ferramentas de análise de chaves privadas deve ser feito com responsabilidade. Não invista ou mova fundos em criptomoedas sem compreensão total dos riscos. Faça sua própria análise antes de qualquer decisão.

Para mais informações sobre padrões e endereços Bitcoin, consulte a documentação oficial da Bitcoin.org.



# Bitcoin Address Scanner from Private Key Range
import sqlite3
import math
import hashlib
import base58
from bit import Key
from bit.format import bytes_to_wif
from decimal import Decimal, getcontext

# ========== Bech32 Utils (BIP173) ==========
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7"

def bech32_polymod(values):
    GEN = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
    chk = 1
    for v in values:
        b = chk >> 25
        chk = ((chk & 0x1ffffff) << 5) ^ v
        for i in range(5):
            if (b >> i) & 1:
                chk ^= GEN[i]
    return chk

def bech32_hrp_expand(hrp):
    return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]

def bech32_create_checksum(hrp, data):
    values = bech32_hrp_expand(hrp) + data
    polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
    return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]

def bech32_encode(hrp, data):
    return hrp + '1' + ''.join([CHARSET[d] for d in data + bech32_create_checksum(hrp, data)])

def convertbits(data, frombits, tobits, pad=True):
    acc = 0
    bits = 0
    ret = []
    maxv = (1 << tobits) - 1
    for b in data:
        acc = (acc << frombits) | b
        bits += frombits
        while bits >= tobits:
            bits -= tobits
            ret.append((acc >> bits) & maxv)
    if pad and bits:
        ret.append((acc << (tobits - bits)) & maxv)
    elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
        return None
    return ret

def hash160(data: bytes) -> bytes:
    return hashlib.new('ripemd160', hashlib.sha256(data).digest()).digest()

def pubkey_to_bech32(pubkey_bytes):
    h160 = hash160(pubkey_bytes)
    return bech32_encode('bc', [0] + convertbits(h160, 8, 5))

def p2sh_p2wpkh_address(pubkey):
    redeem_script = b'\x00\x14' + hash160(pubkey)
    script_hash = hash160(redeem_script)
    addr_bytes = b'\x05' + script_hash
    checksum = hashlib.sha256(hashlib.sha256(addr_bytes).digest()).digest()[:4]
    return base58.b58encode(addr_bytes + checksum).decode()

def define_interval(privkey_hex, size=64):
    pk_int = int(privkey_hex, 16)
    base = (pk_int // size) * size
    return base, base + size - 1, pk_int

def main():
    getcontext().prec = 100
    privkey_hex = "00000000000000000000000000000000000000000000000000000000000000e0"
    low, high, pk_int = define_interval(privkey_hex)

    print("\n=== INTERVALO DE CHAVES PRIVADAS ===")
    print(f"Hex: {privkey_hex}")
    print(f"Decimal: {pk_int}")
    print(f"Intervalo: {low} - {high} ({hex(low)} - {hex(high)})")

    # Entropia
    ln2 = Decimal(math.log(2))
    log_low = Decimal(low).ln() / ln2
    log_high = Decimal(high).ln() / ln2
    print("\n=== ENTROPIA ===")
    print(f"log2(início): {log_low}")
    print(f"log2(fim):    {log_high}")
    print(f"Δ log2:       {log_high - log_low}")

    # Banco de dados
    conn = sqlite3.connect(r"D:\20052025\blockchair\banco.db")
    cursor = conn.cursor()
    cursor.execute("SELECT address FROM enderecos")
    addr_set = set(row[0] for row in cursor.fetchall())

    print("\n=== ENDEREÇOS GERADOS ===")
    for i in range(low, high + 1):
        priv_bytes = i.to_bytes(32, 'big')
        wif_uncompressed = bytes_to_wif(priv_bytes, compressed=False)
        wif_compressed = bytes_to_wif(priv_bytes, compressed=True)

        key_un = Key(wif_uncompressed)
        key_c = Key(wif_compressed)

        addresses = [
            ("P2PKH (não comprimido)", key_un.address),
            ("P2PKH (comprimido)", key_c.address),
            ("P2SH-P2WPKH", p2sh_p2wpkh_address(key_c.public_key)),
            ("Bech32 (P2WPKH)", pubkey_to_bech32(key_c.public_key)),
        ]

        found = False
        for label, addr in addresses:
            if addr in addr_set:
                print(f"{label.ljust(25)} {addr}")
                found = True

        if found:
            print(f"{'WIF não comprimido:'.ljust(25)} {wif_uncompressed}")
            print(f"{'WIF comprimido:'.ljust(25)} {wif_compressed}")
            with open("enderecos_encontrados.txt", "a") as f:
                f.write(f"WIF não comprimido: {wif_uncompressed}\n")
                f.write(f"WIF comprimido: {wif_compressed}\n")
                for label, addr in addresses:
                    if addr in addr_set:
                        f.write(f"{label}: {addr}\n")
                f.write("-" * 50 + "\n")
    conn.close()

if __name__ == "__main__":
    main()

Postar um comentário

Comente só assim vamos crescer juntos!
CanalQb mais próximo Quer falar com o CanalQb?
Em que posso te ajudar?
Fale comigo