Como criar um endereço de carteira Bitcoin a partir de uma chave privada

No artigo anterior, vimos diferentes métodos para gerar uma chave privada. Qualquer que seja o método escolhido, você acabará com 32 bytes de dados. Aqui está o que encontramos no final desse artigo:

60cf347dbc59d31c1358c8e5cf5e45b822ab85b79cb32a9f3d98184779a9efc2

Usaremos essa chave privada ao longo do artigo para derivar uma chave pública e o endereço da carteira Bitcoin.

O que queremos fazer é aplicar uma série de conversões à chave privada para obter uma chave pública e, em seguida, um endereço de carteira. A maioria dessas conversões são chamadas de funções hash. Essas funções hash são conversões unilaterais que não podem ser revertidas. Não iremos para a mecânica das funções em si – existem muitos artigos excelentes que cobrem isso. Em vez disso, veremos como o uso dessas funções na ordem correta pode levar você ao endereço da carteira Bitcoin que você pode usar.

Criptografia de curva elíptica

A primeira coisa que precisamos fazer é aplicar o ECDSA ou Algoritmo de Assinatura Digital da Curva Elíptica à nossa chave privada. Uma curva elíptica é uma curva definida pela equação y² = x³ + ax + b com um a e b escolhidos. Existe toda uma família de curvas que são amplamente conhecidas e utilizadas. Bitcoin usa a curva secp256k1 . Se você quiser saber mais sobre criptografia de curva elíptica, vou encaminhá-lo para este artigo.

Aplicando o ECDSA à chave privada, obtemos um número inteiro de 64 bytes. Consiste em dois inteiros de 32 bytes que representam o X e o Y do ponto na curva elíptica, concatenados.

Para o nosso exemplo, obtivemos: 1e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7b73ff919898c836396a6b0c96812c3213b99372050853bd16787 Em Python, seria assim:

Observação: como você pode ver no código, antes de usar um método do módulo ecdsa , decodifiquei a chave privada usando codecs . Isso é mais relevante para o Python e menos para o algoritmo em si, mas explicarei o que estamos fazendo aqui para remover possíveis confusões.

Em Python, existem pelo menos duas classes que podem manter as chaves privadas e públicas: “str” e “bytes”. O primeiro é uma string e o segundo é uma matriz de bytes. Os métodos criptográficos em Python funcionam com uma classe “bytes”, pegando-a como entrada e retornando-a como resultado.

Agora, há um pequeno problema: uma string, digamos, 4f3c não é igual à matriz de bytes 4f3c , é igual à matriz de bytes com dois elementos, O & lt; . E é isso que o método codecs.decode faz: ele converte uma string em uma matriz de bytes. Isso será o mesmo para todas as manipulações criptográficas que faremos neste artigo.

Chave pública

Assim que terminarmos com o ECDSA, tudo o que precisamos fazer é adicionar os bytes 0x04 no início de nossa chave pública. O resultado é uma chave pública completa Bitcoin, que é igual a: 041e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7b73ff919898c836396a6b0c96812c3213bead814487207

Chave pública compactada

Mas podemos fazer melhor. Como você deve se lembrar, a chave pública é algum ponto (X, Y) na curva. Conhecemos a curva e, para cada X, existem apenas dois Ys que definem o ponto que está nessa curva. Então, por que manter Y? Em vez disso, vamos manter X e o sinal de Y. Mais tarde, podemos derivar Y disso, se necessário.

As especificações são as seguintes: pegamos X da chave pública ECDSA. Agora, adicionamos 0x02 se o último byte de Y for par, e o byte 0x03 se o último byte for ímpar.

No nosso caso, o último byte é estranho, então adicionamos 0x03 para obter a chave pública compactada: 031e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7 . Esta chave contém as mesmas informações, mas é quase duas vezes mais curta que a chave descompactada. Legal!

Anteriormente, o software de carteira usava versões longas e completas de chaves públicas, mas agora a maioria mudou para chaves compactadas.

Criptografando a chave pública

De agora em diante, precisamos fazer um endereço de carteira. Seja qual for o método de obtenção da chave pública que você escolher, ele seguirá o mesmo procedimento. Obviamente, os endereços serão diferentes. Neste artigo, iremos com a versão compactada.

O que precisamos fazer aqui é aplicar SHA-256 à chave pública e, em seguida, aplicar RIPEMD-160 ao resultado. A ordem é importante.

SHA-256 e RIPEMD-160 são duas funções hash e, novamente, não entraremos em detalhes sobre como funcionam. O que importa é que agora temos um inteiro de 160 bits, que será usado para modificações posteriores. Vamos chamar isso de chave pública criptografada. Para nosso exemplo, a chave pública criptografada é 453233600a96384bb8d73d400984117ac84d7e8b .

Veja como criptografamos a chave pública em Python:

Adicionando o byte de rede

O Bitcoin possui duas redes, principal e teste. A rede principal é a rede que todas as pessoas usam para transferir as moedas. A rede de teste foi criada - você adivinhou - para testar novos recursos e software.

Queremos gerar um endereço para usá-lo na rede principal, então precisamos adicionar 0x00 bytes à chave pública criptografada. O resultado é 00453233600a96384bb8d73d400984117ac84d7e8b . Para o testnet, isso seria 0x6f bytes.

Soma de verificação

Agora precisamos calcular a soma de verificação de nossa chave mainnet. A ideia da soma de verificação é garantir que os dados (em nosso caso, a chave) não foram corrompidos durante a transmissão. O software da carteira deve examinar a soma de verificação e marcar o endereço como inválido se a soma de verificação for incompatível.

Para calcular a soma de verificação da chave, precisamos aplicar SHA-256 duas vezes e, a seguir, obter os primeiros 4 bytes do resultado. Para nosso exemplo, o SHA-256 duplo é 512f43c48517a75e58a7ec4c554ecd1a8f9603c891b46325006abf39c5c6b995 e, portanto, a soma de verificação é 512f43c4 (observe que 4 bytes são 8 dígitos hexadecimais).

O código para calcular uma soma de verificação de endereço é o seguinte:

Obtendo o endereço

Finalmente, para fazer um endereço, apenas concatenamos a chave mainnet e a soma de verificação. Isso o torna 00453233600a96384bb8d73d400984117ac84d7e8b512f43c4 para nosso exemplo.

É isso! Esse é o endereço da carteira da chave privada no início do artigo.

Mas você pode notar que algo está errado. Você provavelmente já viu um punhado de endereços de Bitcoin e eles não se parecem com isso. Bem, a razão é que eles são codificados com Base58. É um pouco estranho.

Este é o algoritmo para converter um endereço hexadecimal para o endereço Base58:

O que obtemos é 17JsmEygbbEUEpvt4PFtYaTeSqfb9ki1F1 , um endereço de carteira Bitcoin compactado.

Conclusão

O processo de geração da chave da carteira pode ser dividido em quatro etapas:

Dependendo da forma da chave pública (completa ou compactada), obtemos endereços diferentes, mas ambos são perfeitamente válidos.

Este é o algoritmo completo para a chave pública descompactada:

Se você quiser brincar com o código, eu o publiquei no repositório Github.

Estou fazendo um curso sobre criptomoedas aqui no Medium. A primeira parte é uma descrição detalhada do blockchain.

Eu também posto pensamentos aleatórios sobre criptografia no Twitter, então você pode querer dar uma olhada.