• Nenhum resultado encontrado

Carteiras Determinísticas Hierárquicas (BIP0032/BIP0044)

No documento Dominando Bitcoin (páginas 97-106)

As carteiras determinísticas foram desenvolvidas para facilitar a derivação de várias chaves a partir de uma única "semente". A forma mais avançada de carteiras determinísticas é a carteira determinística

hierárquica ou carteira HD, que é definida pelo padrão BIP0032. As carteiras HD contêm chaves

derivadas em uma estrutura de árvore, de tal forma que uma chave pai pode derivar uma sequência de chaves filhas, cada uma das quais pode derivar uma sequência de chaves netas, e assim por diante, a uma profundidade infinita. Essa estrutura em árvore é ilustrada em Carteira hierárquica determinística (HD) tipo-2: uma árvore de chaves geradas a partir de uma única semente.

Figure 9. Carteira hierárquica determinística (HD) tipo-2: uma árvore de chaves geradas a partir de uma única semente

TIP Se você estiver implementando uma carteira bitcoin, ela deve ser desenvolvida como umacarteira HD seguindo os padrões BIP0032 e BIP0044.

Carteiras HD fornecem duas grandes vantagens em comparação com chaves randômicas (não determinísticas). Primeiro, a estrutura em árvore pode ser usada para expressar significado organizacional adicional, por exemplo quando um ramo específico de subchaves é usado para pagamentos recebidos e outro ramo é usado para receber troco de pagamentos realizados. Ramos ou chaves também podem ser usados num cenário corporativo, alocando ramos diferentes a departamentos, subsidiárias, funções específicas, ou centros de custo.

A segunda vantagem de carteiras HD é que os usuários podem criar uma sequência de chaves públicas sem precisar ter acesso às chaves privadas correspondentes. Isso permite que carteiras HD sejam utilizadas num servidor inseguro, ou numa aplicação de somente recebimento, emitindo uma chave pública diferente para cada transação. As chaves públicas não precisam ser previamente carregadas ou derivadas de antemão, assim o servidor não detém as chaves privadas que possam gastar os fundos.

Criação de carteira HD a partir de semente

Carteiras HD são criadas a partir de uma única semente raiz, que é um número randômico de 128, 256, ou de 512 bits. Tudo mais na carteira HD é derivado deterministicamente a partir da sua semente raiz, o que torna possível recriar a carteira HD completa a partir daquela semente em qualquer carteira HD compatível. Isso faz com que seja fácil realizar backup, restaurar, exportar e importar carteiras HD contendo milhares ou até mesmo milhões de chaves, simplesmente transferindo apenas a semente raiz. A semente raiz é mais frequentemente representada por uma sequência mnemônica de palavras, tal como descrito na seção anterior Códigos Mnemônicos de Palavras, para tornar mais fácil para as pessoas transcrever e armazenar.

O processo de criar as chaves e códigos de encadeamento mestre para uma carteira HD é demonstrado em Criando chaves mestres e código de cadeia a partir da semente raiz.

A semente raiz é usada como input no algoritmo HMAC-SHA512 e o hash resultante é usado para criar uma chave privada mestre (m) e um código de corrente mestre. A chave privada mestre (m) então gera a chave pública mestre correspondente (M), usando o processo normal de multiplicação da curva elíptica m * G que nós vimos anteriormente nesse capítulo. O código de corrente é usado para criar entropia na função que cria as chaves filhas a partir das chaves pais, como nós iremos ver na próxima seção.

Derivação da chave privada filha

As carteiras hierárquicas determinísticas usam uma função de derivação de chave filha ("child key derivation", CKD) para derivar chaves filhas a partir das chaves pais.

As funções de derivação de chave filha são baseadas em uma função de hash de sentido único, que combina:

• Uma chave privada pai ou uma chave pública (chava não-comprimida ECDSA) • Uma semente chamada de código de corrente (256 bits)

• Um número índice (32 bits)

O código da corrente é usado para introduzir dados aparentemente aleatórios ao processo, fazendo com que o índice não seja suficiente para derivar outras chaves filhas. Logo, o fato de se ter uma chave filha não torna alguém capaz de descobrir suas chaves irmãs, a menos que a pessoa tenha também o código da corrente. A semente do código da corrente inicial (no nível da raiz da árvore) é feito a partir de dados aleatórios, enquando os códigos de corrente subsequentes são derivadas de cada código de corrente pai.

Esses três ítens são combinados e são usados para fazer um hash, gerando as chaves filhas.

A chave pública pai, o código de corrente e o número índice são combinados e sofrem hash com o algoritmo HMAC-SHA512 para produzir um hash de 512-bit. O hash resultante é dividido em duas metades. A metade da direita de 256 bits do output do hash se torna o código de corrente da filha. A metade da esquerda de 256 bits do hash e o número índice são adicionados à chave privada pai para produzir a chave privada filha. Em [CKDpriv], nós vimos isso ilustrado com o índice definido em 0 para produzir a 0º (primeiro no índice) filha do pai.

1. Estendendo uma chave privada pai para criar uma chave privada filha image::images/msbt_0411.png["ChildPrivateDerivation"]

Mudar o índice nos permite estender a chave pai e criar a outra chave filha na sequência. Por exemplo, Filha 0, Filha 1, Filha 2, etc. Cada chave pai pode ter 2 bilhões de chaves filha.

Repetindo o processo em um nível abaixo da árvore, cada filha pode virar um pai e criar suas próprias filhas, em um número infinito de gerações.

Usando as chaves filhas derivadas

As chaves privadas filhas são indistinguíveis das chaves não-determinísticas (aleatórias). Como a função de derivação é uma função de via única, a chave filha não pode ser usada para se encontrar a chave pai. A chave filha também não pode ser usada para se encontrar nenhuma chave irmã. Se você tem a chave filha n, você não é capaz de descobrir suas irmãs, como a filha n–1 ou a filha n+1, assim como nenhuma outra filha que faça parte da sequência. Somente a chave pai e o código de cadeia podem derivar todas as filhas. Sem o código de corrente da filha, a chave filha também não pode ser usada para derivar nenhuma chave neta. Você precisa ter tanto a chave privada filha quando o código de corrente da filha para poder iniciar um novo ramo e derivar as chaves netas.

Então para que serve uma chave filha privada isolada? Ela pode ser usada para fazer uma chave pública e um endereço bitcoin. Ou seja, ela pode ser usada para assinar transações que gastem qualquer valor que aquele endereço tenha recebido.

TIP

Uma chave privada filha, a chave pública e o endereço bitcoin correspondentes são todos indistinguíveis de chaves e endereços criados aleatoriamente. Ninguém sabe que elas fazem parte de uma sequência, exceto a função de carteira HD que as criou. Uma vez criadas, elas operam exatamente como chaves "normais".

Chaves estendidas

Como nós vimos anteriormente, a função de derivação de chave pode ser usada para criar chaves filhas em qualquer nível da árvore, baseando-se em três entradas (inputs): uma chave, um código de corrente e o índice da filha desejada. Os dois ingredientes essenciais são a chave a o código de cadeia, que combinados são chamados de chave estendida. O termo "chave estendida" também poderia ser considerado como uma "chave estendível", pois esse tipo de chave pode ser usado para derivar chaves filhas.

As chaves estendidas são armazenadas e representadas basicamente como uma concatenação da chave de 256-bit e do código de corrente de 256-bit em uma sequência de 512-bit. Existem dois tipos de chaves estendidas. A chave priva estendida é a combinação de uma chave privada e do código de cadeia, e pode ser usada para derivar as chaves privadas filhas (e, a partir delas, as chaves públicas filhas). Uma chave pública estendida é uma chave pública e um código de corrente, que pode ser usada para criar as chaves públicas filhas, como descrito em Gerando uma Chave Pública.

Imagina uma chave estendida como a raiz de um ramo na estrutura de árvore da carteira HD. Tendo a raiz do ramo, você pode derivar o resto do ramo. A chave privada estendida pode criar um ramo completo, enquanto a chave pública estendida só é capaz de criar um ramo de chaves públicas.

TIP

Uma chave estendida consiste de uma chave privada ou chave pública e um código de corrente. Uma chave estendida pode criar chaves filhas, gerando a sua própria remificação na estrutura em árvore. Compartilhar uma chave estendida dá acesso a toda a ramificação.

diferentes carteiras compatíveis com o BIP-0032. A codificação Base58Check para as chaves estendidas usa um número de versão especial que resulta no prefixo "xprv" e "xpub" quando codificada em caracteres Base58, para torná-los mais facilmente reconhecíveis. Como a chave estendida é de 512 ou 513 bits, ela é muito mais longa do que qualquer um dos strings codificados em Base58Check que nós já vimos anteriormente.

Esse é um exemplo de uma chave privada estendida, codificada em Base58Check:

xprv9tyUQV64JT5qs3RSTJkXCWKMyUgoQp7F3hA1xzG6ZGu6u6Q9VMNjGr67Lctvy5P8oyaYAL9CAWrUE9i6GoNMK Uga5biW6Hx4tws2six3b9c

Essa é a chave pública estendida correspondente, também codificada em Base58Check:

xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KECeeMVKZBPLrtJunSDMst weyLXhRgPxdp14sk9tJPW9

Derivação de chaves públicas filhas

Como mencionado anteriormente, uma característica muito útil das carteiras determinísticas hierárquicas é a habilidade de derivar chaves públicas filhas a partir de chaves públicas pais, sem que seja necessário saber as chaves privadas. Isso fornece duas maneiras de derivar um chave pública filha: a partir da chave privada filha, ou diretamente a partir da chave pública pai.

Portanto, uma chave pública estendida pode ser usada para derivar todas as chaves públicas (e somente as chaves públicas) naquela ramificação da estrutura da carteira HD.

Esse atalho pode ser usado para criar implantações somente-chave-pública muito seguras, onde um servidor ou aplicação possui uma cópia da chave pública estendida e nenhuma chave privada. Esse tipo de implantação pode produzir um número infinito de chaves públicas e endereços bitcoin, mas não pode gastar nenhum dos bitcoins que forem enviados para esses endereços. Enquanto isso, em outro servidor mais seguro, a chave privada estendida pode derivar todas as cahves privadas correspondentes para assinar as transações e gastar os bitcoins.

Uma utilização comum dessa solução é a instalação de uma chave pública estendida em um servidor web que seja utilizada em um serviço de comércio eletrônico. O servidor web pode usar a função de derivação de chave pública para cirar um novo endereço bitcoin a cada transação (por exemplo, para um carrinho de compras de um consumidor). O servidor web não irá ter nenhuma chave privada que seriam vulneráveis a roubo. Sem as carteiras HD, a única maneira de se fazer isso seria gerar milhares de endereços bitcoin em um outro servidor seguro, e então enviá-los antecipadamente para o servidor de comércio eletrônico. Essa abordagem não é prática, pois requer uma manutenção constante para evitar que as chaves do servidor de comércio eletrônico sejam todas gastas e "acabem".

Outra aplicação comum dessa solução é o uso de carteiras de harware ou de armazenamento frio. Nesse cenário, a chave privada estendida pode ser armazenada em uma carteira de papel ou em um

dispositivo de hardware (como a carteira de hardware Trezor), enquanto a chave pública estendida pode ser mantida online. O usuário pode criar endereços de "recebimento" à vontade, pois as suas chaves privadas estão armazenadas de maneira segura em um ambiente offline. Para gastar os fundos, o usuário pode usar a chave privada estendida em um cliente bitcoin que assine a transação online, ou ao assinar as transações em um dispositivo de carteira de hardware (por exemplo, o Trezor).

Estendendo uma chave pública pai para criar uma chave pública filha ilustra o mecanismo para estender uma chave pública pai para derivar as chaves públicas filhas.

Figure 11. Estendendo uma chave pública pai para criar uma chave pública filha Derivação endurecida da chave filha

A habilidade de derivar um ramo de chaves públicas a partir de uma chave pública estendida é muito útil, mas isso traz um risco em potencial. Ter acesso a uma chave pública estendida não dá acesso ás chaves privadas filhas. No entanto, como a chave pública estendida contém o código de corrente, se a chave privada filha é conhecida, ou vazou de alguma maneira, ela pode ser usada com o código de corrente para derivar todas as outras chaves privadas filhas. Uma única chave privada filha vazada, junto com um código de corrente pai, é suficiente para revelar todas as chaves privadas de todas as filhas. Pior ainda, a chave privada filha junto com o código de corrente pai pode ser usado para deduzir a chave privada pai.

Para evitar esse risco, as carteiras HD usam uma função de derivação alternativa chamada derivação

endurecida ("hardened derivation"), que "desfaz" a relação entre a chave pública pai e o código de

corrente filho. A função de derivação endurecida usa a chave privada pai para derivar o código de corrente filho, ao invés da chave pública pai. Isso cria um "firewall" na sequência pai/filha, com um código de corrente que não pode ser usado para comprometer uma chave privada pai ou irmã. A função de derivação endurecida parece quase idêntica à derivação de chave privada filha normal, com a exceção de que a chave privada pai é usada como input da função de hash, ao invés da chave pública pai, como demonstrado no diagrama em Derivação endurecida de uma chave filha; omitindo a chave pública pai.

Figure 12. Derivação endurecida de uma chave filha; omitindo a chave pública pai

Quando a função de derivação privada endurecida é utilizada, a chave privada filha e o código de cadeia resultantes são completamente diferentes do que iriam resultar a partir de uma função de derivação normal. O "ramo" de chaves resultante poderia ser usada para produzir chaves públicas estendidas que não são vulneráveis, pois o código de corrente que elas contém não pode ser hackeado para revelar as chaves privadas. A derivação endurecida é portanto usada para criar uma lacuna (um "gap") na árvore acima do nível onde as chaves públicas estendidas são usadas.

Em termos simples, se você quer usar a conveniência de uma chave pública estendida para derivar ramos das chaves públicas, sem se expor ao risco de deixar o código de corrente vazar, você deveria derivá-la a partir de um pai endurecido, ao invés de um pai normal. Como uma prática recomendada, as filhas do nível-1 das chaves mestre são sempre derivadas através da derivação endurecida, para evitar o comprometimento das chaves mestre.

Números de índice para a derivações normal e endurecida

O número de índice usado na função de derivação é um número de 32-bit. Para diferenciar facilmente entre as chaves derivadas através da função de derivação normal das chaves derivadas através da derivação endurecida, esse número índice é dividido em duas faixas. Os números de índice entre 0 e 231–1 (0x0 a 0x7FFFFFFF) são usados apenas para a derivação normal. Os números de índice entre 231 e

232–1 (0x80000000 a 0xFFFFFFFF) são usados apenas para a derivação endurecida. Portanto, se o

número de índice é menor do que 231, isso significa que a filha é normal, enquanto se o número de

índice é maior ou igual a 231, a filha é endurecida.

endurecidas é exibido iniciando do zero, mas com um apóstrofo. A primeira chave filha normal é portanto exibida como um 0, enquanto a primeira chave filha endurecida (índice 0x80000000) é exibida como <markup>0'</markup>. Na sequência, a segunda chave endurecida teria o índice 0x80000001 e seria exibida como 1', e assim por diante. Quando você se deparar com um índice de carteira HD i', isso significa 2<sup>31</sup>+i.

Identificador (caminho) da chave de uma carteira HD

As chaves em uma carteira HD são identificadas a partir de uma convenção de nomenclatura de "caminho", com cada nível sendo separado por uma barra (/) (ver Exemplos de caminhos de carteira HD). As chaves privadas derivadas a partir da chave privada mestre iniciam com "m". As chaves públicas derivadas a partir da chave pública mestre iniciam com "M". Portanto, a primeira chave privada filha da chave privada mestre é m/0. A primeira chave pública filha é M/0. A segunda neta da primeira filha é m/0/1, e assim por diante.

Os "antepassados" de uma chave são lidos da direita para a esquerda, até você chegar na chave mestre a partir da qual ela foi derivada. Por exemplo, o identificador m/x/y/z descreve a chave que é a zª filha da chave m/x/y, que é a yª filha da chave m/x, que é a xª filha da chave m.

Table 6. Exemplos de caminhos de carteira HD

Caminho HD Chave descrita

m/0 A primeira (0) chave privada a partir da chave privada mestre (m)

m/0/0 A primeira chave privada neta da primeira filha (m/0)

m/0'/0 A primeira neta normal da primeira filha

endurecida (m/0')

m/1/0 A primeira chave privada neta da segunda filha (m/1)

M/23/17/0/0 A primeira chave pública tataraneta da primeira bisneta da 18ª neta da 24ª filha

Navegando as estrutura de árvore da carteira HD

A estrutura de árvore da carteira HD oferece uma flexibilidade imensa. Cada chave pai estendida pode ter 4 bilhões de filhas: 2 bilhões de filhas normais e 2 bilhões de filhas endurecidas. Cada uma dessas filhas pode ter outras 4 bilhões de filhas, e assim por diante. A árvore pode ter a profundidade que for necessária, com um número infinito de gerações. Com toda essa flexibilidade, entretanto, se torna bastante difícil navegar nessa árvore infinita. É especialmente difícil transferir carteiras HD entre implementações, porque as possibilidades de organização interna em ramos e subramos são infinitas. Duas Propostas de Melhorias para o Bitcoin (BIPs) oferecem uma solução para essa complexidade, ao criar alguns padrões propostos para a estrutura das árvores das carteiras HD. A BIP0043 propõe o uso

do índice da primeira filha endurecida como um identificador especial que representa o "propósito" da estrutura de árvore. Baseando-se na BIP0043, uma carteira HD deveria usar apenas um ramo de nível- 1 da árvore, com o número de índice identificando a estrutura e o espaço de nomes para o resto da árvore ao definir o seu propósito. Por exemplo, uma carteira HD usando apenas o ramo m/i'/ se destina a um propósito específico, e esse propósito é identificado pelo número índice "i".

Estendendo essa especificação, a BIP0044 propõe uma estrutura de múltiplas contas como número de "proposta" 44' sob a BIP0043. Todas as carteiras HD seguindo a estrutura BIP0044 são identificads pelo fato de que elas somente usaram um ramo da árvore: m/44'/.

O BIP0044 especifica a estrutura como consistindo de cinco níveis de árvore pré-definidos: m / purpose' / coin_type' / account' / change / address_index

A "proposta" ("purpose") do primeiro nível é sempre definida como 44'. O "tipo_de_moeda" ("coin_type") do segundo nível especifica o tipo de criptomoeda, permitindo a existência de carteiras HD que usem múltiplas moedas, onde cada moeda possui a sua própria subárvore sob o segundo nível. Existem três moedas definidas até hoje: a Bitcoin é m/44'/0', a Bitcoin Testnet é <markup>m/44'/1'</markup>; e a Litecoin é <markup>m/44'/2'</markup>.

O terceiro nível da árvore é a "conta" ("account"), que permite que os usuários subdividam suas carteiras em subcontas separadas lógicas, para fins de contabilidade e organização. Por exemplo, uma carteira HD pode conter duas "contas" bitcion: <markup>m/44'/0'/0'</markup> e <markup>m/44'/0'/1'</markup>. Cada conta é a raiz de sua própria subárvore.

No quarto nível, "troco" ("change"), uma carteira HD tem duas subárvores, uma para criar endereços de recebimento e outra para criar endereços de troco. Note que enquanto os níveis anteriores usavam derivação endurecida, esse nível usa derivação normal. Isso acontece para permitir que esse nível da árvore exporte chaves públicas estendidas para uso em ambientes não-seguros. Os endereços utilizáveis são derivados pela carteira HD como crianças no quarto nível, tornando o quinto nível da árvore o "índice_de_endereço" ("address_index"). Por exemplo, o terceiro endereço de recebimento para pagamentos bitcoin na conta primária seria M/44'/0'/0'/0/2. Exemplos de estrutura de carteira HD da BIP0044 demonstra mais alguns exemplos.

Table 7. Exemplos de estrutura de carteira HD da BIP0044

Caminho HD Chave descrita

No documento Dominando Bitcoin (páginas 97-106)