Gerenciamento e Conversão de Chaves Privadas com Python e PostgreSQL
Sempre crie uma frase de segurança única para jogos, testnets ou airdrops e evite usar sua carteira principal.
Como Gerar e Converter Chaves Privadas para WIF com Python e PostgreSQL
Este artigo apresenta um código completo em Python para conectar a um banco de dados PostgreSQL, selecionar dados, e realizar a conversão de chaves privadas para o formato WIF (Wallet Import Format), amplamente utilizado em criptomoedas como o Bitcoin. Além disso, o script exemplifica técnicas de paralelização para otimizar o processamento e oferece funções para cálculo de tempo estimado para conversões em massa.
Conexão com o Banco de Dados PostgreSQL
Para acessar os dados, o script utiliza a biblioteca pg8000, que implementa um driver PostgreSQL puro em Python. A URL de conexão contém as credenciais e parâmetros necessários para a autenticação segura, incluindo o modo SSL:
DATABASE_URL = "postgres://neondb_owner:aaaa.us-east-1.aws.neon.tech/neondb?sslmode=require"
A função conectar_ao_banco() gerencia uma conexão global para reutilização, evitando a abertura excessiva de conexões.
Seleção Randomizada e Controle de Dados
O método selecionar_linha_randomizada() realiza uma consulta que busca linhas cuja coluna datahora esteja nula ou com mais de 3 horas, garantindo a atualização periódica dos dados processados. A função retorna os intervalos de chaves privados para processamento.
Conversão de Chaves Privadas Hexadecimais para WIF
A função private_key_to_wif(private_key_hex, compression='01') converte uma chave privada hexadecimal para o formato WIF, aplicando os seguintes passos:
- Remove o prefixo
0xse presente. - Concatena o prefixo
0x80(indica chave privada Bitcoin) e o byte de compressão. - Aplica dupla hash SHA-256 para gerar o checksum.
- Codifica o resultado em Base58, utilizando o alfabeto próprio para endereços Bitcoin.
Paralelização para Geração de WIFs
Para acelerar o processo, o código usa ThreadPoolExecutor para gerar múltiplos WIFs em paralelo. Isso permite a divisão do intervalo de chaves em blocos menores e o processamento simultâneo em diferentes threads.
Cálculo de Tempo Restante
Uma função útil calcula o tempo estimado para completar a conversão das chaves restantes com base no tempo médio por conversão. Ela retorna a estimativa em dias, horas, minutos e segundos, auxiliando no monitoramento do progresso.
Execução Principal
A função main() orquestra o fluxo de execução:
- Limpa a tela para melhor visualização.
- Exibe o total de ranges criados e processados.
- Seleciona um intervalo de chave a ser processado.
- Calcula e exibe métricas de desempenho, como tempo médio por conversão e WIFs por segundo.
- Realiza uma contagem regressiva antes de iniciar a geração paralela de WIFs.
- Ao final, exibe o endereço Bitcoin correspondente à chave gerada.
Considerações Importantes
Este código é um exemplo técnico para manipulação e geração de chaves privadas em ambiente Python com banco PostgreSQL. É fundamental compreender os riscos de segurança envolvidos no manuseio de chaves privadas, nunca compartilhando-as em ambientes inseguros e utilizando sempre boas práticas de segurança.
Para uso em produção, recomenda-se validar e adaptar o código conforme a infraestrutura e as necessidades específicas, garantindo também a conformidade com políticas de segurança e privacidade.
Este conteúdo é educativo e não deve ser utilizado para investimento ou manejo financeiro sem a devida compreensão dos riscos envolvidos.
Referências e Links Oficiais
- Documentação Python - concurrent.futures
- pg8000 - Driver PostgreSQL para Python
- Bitcoin Wiki - Wallet Import Format (WIF)
- hashlib - Funções de hash em Python
Trecho do Código Corrigido e Otimizado para Blogspot
import time
import gc
import hashlib
import os
import pg8000
import urllib.parse
from bit import Key
from concurrent.futures import ThreadPoolExecutor
DATABASE_URL = "postgres://neondb_owner:aaaa.us-east-1.aws.neon.tech/neondb?sslmode=require"
connection = None
def conectar_ao_banco():
global connection
if connection is None:
try:
url = urllib.parse.urlparse(DATABASE_URL)
connection = pg8000.connect(
user=url.username, password=url.password,
host=url.hostname, database=url.path[1:],
port=5432, ssl_context=True
)
except Exception as e:
print(f"Erro ao conectar ao banco de dados: {e}")
raise
return connection
def selecionar_linha_randomizada():
connection = conectar_ao_banco()
cursor = connection.cursor()
try:
query = """SELECT * FROM puzzle67 WHERE datahora IS NULL OR (CURRENT_TIMESTAMP - datahora) > INTERVAL '3 HOURS' ORDER BY RANDOM() LIMIT 1;"""
cursor.execute(query)
linha = cursor.fetchone()
if linha:
return linha[0], linha[2], linha[1], linha[4]
else:
print("Nenhuma linha encontrada.")
return None, None, None, None
except Exception as e:
print(f"Erro ao consultar o banco de dados: {e}")
return None, None, None, None
finally:
cursor.close()
gc.collect()
def total_de_linhas():
connection = conectar_ao_banco()
cursor = connection.cursor()
try:
cursor.execute("SELECT COUNT(*) FROM puzzle67;")
return cursor.fetchone()[0]
except Exception as e:
print(f"Erro ao consultar o banco de dados: {e}")
return None
finally:
cursor.close()
gc.collect()
def private_key_to_wif(private_key_hex, compression='01'):
if private_key_hex.startswith('0x'):
private_key_hex = private_key_hex[2:]
private_key = bytes.fromhex(private_key_hex.zfill(64))
data = b'\x80' + private_key + bytes([int(compression, 16)])
hash1 = hashlib.sha256(data).digest()
hash2 = hashlib.sha256(hash1).digest()
checksum = hash2[:4]
data += checksum
chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
i = int.from_bytes(data, 'big')
base58 = ''
while i > 0:
i, r = divmod(i, 58)
base58 = chars[r] + base58
return base58
def gerar_wif_paralelo(start_end):
start, end = start_end
return [private_key_to_wif(hex(x)) for x in range(start, end)]
def calcular_tempo_restante(total_falta, tempo_gasto):
vezes_por_segundo = (1 / tempo_gasto) * 100
tempo_restante_segundos = total_falta / vezes_por_segundo
dias = tempo_restante_segundos // (24 * 3600)
tempo_restante_segundos %= (24 * 3600)
horas = tempo_restante_segundos // 3600
tempo_restante_segundos %= 3600
minutos = tempo_restante_segundos // 60
segundos = tempo_restante_segundos % 60
return dias, horas, minutos, segundos, vezes_por_segundo
def main():
total_linhas = total_de_linhas()
os.system('cls' if os.name == 'nt' else 'clear')
if total_linhas is not None:
print(f"\tTotal de ranges criadas: {total_linhas} de 1.000.000.000")
inicio_range_db, meio_range_db, fim_range_db, _ = selecionar_linha_randomizada()
fim_range = fim_range_db
range_inicial = meio_range_db if meio_range_db else inicio_range_db
range_inicial = int(range_inicial, 16)
fim_range = int(fim_range, 16)
tamanho_parte = (fim_range - range_inicial) // 10
parte_1 = None
for i in range(10):
inicio_parte = range_inicial + i * tamanho_parte
fim_parte = fim_range if i == 9 else range_inicial + (i + 1) * tamanho_parte
if i == 0:
parte_1 = (hex(inicio_parte), hex(fim_parte))
private_key_hex = f'{range_inicial:064x}'
inicio = time.perf_counter()
wif = private_key_to_wif(private_key_hex)
fim = time.perf_counter()
tempo_gasto = fim - inicio
total_falta = int(parte_1[1], 16) - int(parte_1[0], 16)
dias, horas, minutos, segundos, vezes_por_segundo = calcular_tempo_restante(total_falta, tempo_gasto)
print(f"\tMédia de tempo por conversão: {tempo_gasto:.9f} segundos")
print(f"\tVerificando por segundo: {int(vezes_por_segundo)} WIF's")
print(f"\tTempo restante para ler todos os {total_falta} WIF's: {int(dias)} dias, {int(horas)} horas, {int(minutos)} minutos, {int(segundos)} segundos")
for i in range(3, 0, -1):
print(f"{i:02}", end="\r", flush=True)
time.sleep(1)
total_iteracoes = int(total_falta * 0.10)
intervalo_progressao = total_iteracoes // 10
intervals = [(start, start + intervalo_progressao) for start in range(int(parte_1[0], 16), int(parte_1[0], 16) + total_iteracoes, intervalo_progressao)]
with ThreadPoolExecutor(max_workers=4) as executor:
resultados = list(executor.map(gerar_wif_paralelo, intervals))
print(f"\tWIF: {Key(wif).address}")
gc.collect()
if __name__ == "__main__":
main()

Comentários
Comente só assim vamos crescer juntos!