Hash da Chave Pública

Uma chave pública encurtada

Diagrama mostrando um hash da chave pública como o HASH160 (SHA-256 + RIPEMD-160) de uma chave pública.

Um hash da chave pública é o hash de uma chave pública. Então, nenhuma surpresa por aqui.

Fazer o hash produz uma versão encurtada da chave pública, o que, no fim das contas, significa que você pode criar um endereço mais curto e mais fácil de compartilhar com outras pessoas.

Esse hash da chave pública é usado dentro dos scripts de travamento P2PKH (Pay To Public Key Hash) e P2WPKH (Pay To Witness Public Key Hash), que são os scripts de travamento mais comuns usados ao enviar bitcoins para um endereço através de uma carteira de bitcoin.

Criando

Como você cria um hash da chave pública?

Diagrama mostrando como criar um hash da chave pública passando uma chave pública pelo HASH160 (SHA-256 + RIPEMD-160).

Um hash da chave pública é o HASH160 de uma chave pública.

Ícone Ferramenta Chave Pública

Chave Pública

Calcule a chave pública a partir de uma chave privada.

0 bytes

Chave Pública

Coordenadas
0d
0d

Uma chave pública é apenas um ponto em uma curva elíptica. A chave pública final são essas coordenadas em hexadecimal.

Compressão

A curva é simétrica no eixo x, então a chave comprimida guarda só a coordenada x e se o y é par ou ímpar. A x-only é usada em saídas Taproot.

0 bytes

Nunca digite sua chave privada em um site, nem use uma chave privada gerada por um site. Sites podem facilmente salvar a chave privada e usá-la para roubar seus bitcoins.

Ícone Ferramenta HASH160

HASH160

SHA-256 + RIPEMD-160. Usado para encurtar uma chave pública ou script antes de converter em um endereço.

Uma chave pública ou script, por exemplo

0 bytes
SHA-256
RIPEMD-160

RIPEMD-160(SHA-256(dados))

0 bytes

Por exemplo, se esta é a sua chave pública:

02e3af28965693b9ce1228f9d468149b831d6a0540b25e8a9900f71372c11fb277

Este é o hash da chave pública:

1e51fcdc14be9a148bb0aaec9197eb47c83776fb

Código

# Função HASH160
def hash160(data)
  # Converte os dados para binário antes de fazer o hash
  binary = [data].pack("H*")

  # SHA-256 primeiro
  sha256 = Digest::SHA256.digest(binary)

  # RIPEMD-160 depois
  ripemd160 = Digest::RMD160.digest(sha256)

  # Converte de volta de binário para hexadecimal
  hash160 = ripemd160.unpack("H*").join

  return hash160
end

# Chave Pública
publickey = "02e3af28965693b9ce1228f9d468149b831d6a0540b25e8a9900f71372c11fb277"

# Hash da Chave Pública
puts hash160(publickey) #=> 1e51fcdc14be9a148bb0aaec9197eb47c83776fb

RIPEMD-160

O RIPEMD-160 produz um digest de 20 bytes (160 bits).

Isso é menor que a chave pública original (65 bytes não comprimida, 33 bytes comprimida).

Diagrama mostrando a diferença de tamanho entre uma chave pública não comprimida/comprimida e um hash da chave pública.

Isso significa que o endereço que acabamos criando a partir dele conterá menos caracteres do que uma chave pública completa, tornando-o mais fácil de repassar.

Ícone Ferramenta SHA-256

SHA-256

SHA-256 simples. Faz o hash dos bytes de dados usando a função de hash SHA-256.

0 bytes
SHA-256
0 bytes
Ícone Ferramenta RIPEMD-160

RIPEMD-160

RIPEMD-160. Faz o hash de bytes de dados usando a função de hash RIPEMD-160.

0 bytes
RIPEMD-160
0 bytes

Uso

Como os hashes de chave pública são usados no Bitcoin?

A principal razão para fazer o hash de uma chave pública é encurtá-la antes de convertê-la em um endereço.

Ícone Ferramenta Endereço (Base58)

Endereço (Base58)

Codifique el hash160 de una clave pública o script en una dirección heredada.

1 byte
0 bytes
0 bytes
Tipo de dirección

Codificación Base58 de los datos anteriores

0 caracteres

Então, quando alguém envia bitcoins para o nosso endereço usando uma carteira, na verdade essa pessoa está travando uma saída ao nosso hash da chave pública, em vez da nossa chave pública completa:

Diagrama mostrando uma saída sendo travada a um hash da chave pública em vez da chave pública completa.

Quando vamos gastar esses bitcoins em uma transação futura, fornecemos então a chave pública original junto com uma assinatura dentro do código de destravamento da entrada:

Diagrama mostrando a chave pública original e uma assinatura sendo fornecidas no ScriptSig da entrada para destravar a saída.

Quando um valida essa transação, ele vai:

  1. Verificar se a chave pública resulta no hash da chave pública que está dentro do cadeado.
  2. Verificar a assinatura contra a chave pública normalmente.

Então, basicamente, usar um hash da chave pública adiciona um passo extra na hora de travar e destravar bitcoins, mas o que ganhamos em troca é poder usar endereços mais curtos.

Localização

Onde você encontra hashes de chave pública?

Um hash da chave pública pode ser encontrado dentro de transações que usam os scripts de travamento P2PKH e P2WPKH.

Aqui estão alguns exemplos de hashes de chave pública dentro de transações brutas na blockchain.

P2PKH

Pay To Public Key Hash

Um hash da chave pública pode ser encontrado dentro do ScriptPubKey de um P2PKH (Pay To Public Key Hash):

Bruto

0100000002f60b5e96f09422354ab150b0e506c4bffedaf20216d30059cc5a3061b4c83dff000000004a493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01fffffffff7272ef43189f5553c2baea50f59cde99b3220fd518884d932016d055895b62d000000004a493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01ffffffff0100e40b54020000001976a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac00000000

Separado

{
  "version": "01000000",
  "inputcount": "02",
  "inputs": [
    {
      "txid": "f60b5e96f09422354ab150b0e506c4bffedaf20216d30059cc5a3061b4c83dff",
      "vout": "00000000",
      "scriptsigsize": "4a",
      "scriptsig": "493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01",
      "sequence": "ffffffff"
    },
    {
      "txid": "f7272ef43189f5553c2baea50f59cde99b3220fd518884d932016d055895b62d",
      "vout": "00000000",
      "scriptsigsize": "4a",
      "scriptsig": "493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01",
      "sequence": "ffffffff"
    }
  ],
  "outputcount": "01",
  "outputs": [
    {
      "amount": "00e40b5402000000",
      "scriptpubkeysize": "19",
      "scriptpubkey": "76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac"
    }
  ],
  "locktime": "00000000"
}

Transação: 6f7cf9580f1c2dfb3c4d5d043cdbb128c640e3f20161245aa7372e9666168516

A chave pública completa é então revelada no ScriptSig quando essa saída é usada como uma entrada em uma transação de gasto:

Bruto

01000000030dd7891efbf67da47c651531db8aab3144ed7a524e4ae1e30b773525e27ddd7b000000004948304502206f6a68710a51f77e5a1fa4d1037a23a76723724a51fd54710949e0189ee02dfa022100dad3454ade12fe84f3818e14c41ec2e02bbb154dd3136a094cdf86f67ebbe0b601ffffffff16851666962e37a75a246101f2e340c628b1db3c045d4d3cfb2d1c0f58f97c6f000000008b48304502203f004eeed0cef2715643e2f25a27a28f3c578e94c7f0f6a4df104e7d163f7f8f022100b8b248c1cfd8f77a0365107a9511d759b7544d979dd152a955c867afac0ef7860141044d05240cfbd8a2786eda9dadd520c1609b8593ff8641018d57703d02ba687cf2f187f0cee2221c3afb1b5ff7888caced2423916b61444666ca1216f26181398cffffffffffda5d38e91fd9a0d92872d51f83cb746fc7bf5d3ff13402f8d0d5ed60ddc79c0000000049483045022100b6fd43f2fa16e092678283f64d2e08fb2070b4af2b3ddfb9ca3c5e238288acaa02200c5a28e0a4fc1a540f6eeb30ccc4788050eae46964fe33ccb4500c3de1320c2501ffffffff02c0c62d00000000001976a91417194e1bd175fb5b1b2a1f9d221f6f5c29e1928388ac00c817a8040000001976a91465bda9b05f7e9a8f96a7f4ba0996a877708ef90888ac00000000

Separado

{
  "version": "01000000",
  "inputcount": "03",
  "inputs": [
    {
      "txid": "0dd7891efbf67da47c651531db8aab3144ed7a524e4ae1e30b773525e27ddd7b",
      "vout": "00000000",
      "scriptsigsize": "49",
      "scriptsig": "48304502206f6a68710a51f77e5a1fa4d1037a23a76723724a51fd54710949e0189ee02dfa022100dad3454ade12fe84f3818e14c41ec2e02bbb154dd3136a094cdf86f67ebbe0b601",
      "sequence": "ffffffff"
    },
    {
      "txid": "16851666962e37a75a246101f2e340c628b1db3c045d4d3cfb2d1c0f58f97c6f",
      "vout": "00000000",
      "scriptsigsize": "8b",
      "scriptsig": "48304502203f004eeed0cef2715643e2f25a27a28f3c578e94c7f0f6a4df104e7d163f7f8f022100b8b248c1cfd8f77a0365107a9511d759b7544d979dd152a955c867afac0ef7860141044d05240cfbd8a2786eda9dadd520c1609b8593ff8641018d57703d02ba687cf2f187f0cee2221c3afb1b5ff7888caced2423916b61444666ca1216f26181398c",
      "sequence": "ffffffff"
    },
    {
      "txid": "ffda5d38e91fd9a0d92872d51f83cb746fc7bf5d3ff13402f8d0d5ed60ddc79c",
      "vout": "00000000",
      "scriptsigsize": "49",
      "scriptsig": "483045022100b6fd43f2fa16e092678283f64d2e08fb2070b4af2b3ddfb9ca3c5e238288acaa02200c5a28e0a4fc1a540f6eeb30ccc4788050eae46964fe33ccb4500c3de1320c2501",
      "sequence": "ffffffff"
    }
  ],
  "outputcount": "02",
  "outputs": [
    {
      "amount": "c0c62d0000000000",
      "scriptpubkeysize": "19",
      "scriptpubkey": "76a91417194e1bd175fb5b1b2a1f9d221f6f5c29e1928388ac"
    },
    {
      "amount": "00c817a804000000",
      "scriptpubkeysize": "19",
      "scriptpubkey": "76a91465bda9b05f7e9a8f96a7f4ba0996a877708ef90888ac"
    }
  ],
  "locktime": "00000000"
}

Transação: 12e753ef5cc30925a6eee2c457aa7f53022443ca013ea81882a6b59b69e342a6

P2WPKH

Pay To Witness Public Key Hash

Um hash da chave pública pode ser encontrado dentro do ScriptPubKey de um P2WPKH (Pay To Witness Public Key Hash):

Bruto

020000000001016972546966be990440a0665b73d0f4c3c942592d1f64d1033717aaa3e2c2ec913300000000ffffffff024087100000000000160014841b80d2cc75f5345c482af96294d04fdd66b2b760e31600000000001600142e8734f8e263e516d47fcaa2dfe1bd01e0dc935802473044022042e5e3ed2a41214ae864634b6fde33ca2ff312f3d89d6aa3e14c026d50d8ed3202206c38dcd0432a0724490356fbf599cdae40e334c3667a9253f8f4cc57cf3c4480012103f465315805ed271eb972e43d84d2a9e19494d10151d9f6adb32b8534bfd764ab00000000

Separado

{
  "version": "02000000",
  "marker": "00",
  "flag": "01",
  "inputcount": "01",
  "inputs": [
    {
      "txid": "6972546966be990440a0665b73d0f4c3c942592d1f64d1033717aaa3e2c2ec91",
      "vout": "33000000",
      "scriptsigsize": "00",
      "scriptsig": "",
      "sequence": "ffffffff"
    }
  ],
  "outputcount": "02",
  "outputs": [
    {
      "amount": "4087100000000000",
      "scriptpubkeysize": "16",
      "scriptpubkey": "0014841b80d2cc75f5345c482af96294d04fdd66b2b7"
    },
    {
      "amount": "60e3160000000000",
      "scriptpubkeysize": "16",
      "scriptpubkey": "00142e8734f8e263e516d47fcaa2dfe1bd01e0dc9358"
    }
  ],
  "witness": [
    {
      "stackitems": "02",
      "0": {
        "size": "47",
        "item": "3044022042e5e3ed2a41214ae864634b6fde33ca2ff312f3d89d6aa3e14c026d50d8ed3202206c38dcd0432a0724490356fbf599cdae40e334c3667a9253f8f4cc57cf3c448001"
      },
      "1": {
        "size": "21",
        "item": "03f465315805ed271eb972e43d84d2a9e19494d10151d9f6adb32b8534bfd764ab"
      }
    }
  ],
  "locktime": "00000000"
}

Transação: c178d8dacdfb989f9d4fa45828ed188cd54a0414d625c3e61e75c5e3ac15a83a

Nota: esta transação também tem uma segunda saída P2WPKH contendo outro hash da chave pública, mas destaquei apenas o primeiro como exemplo.

A chave pública completa é então revelada na Testemunha quando essa saída é usada como uma entrada em uma transação de gasto:

Bruto

020000000001013aa815ace3c5751ee6c325d614044ad58c18ed2858a44f9d9f98fbcddad878c10000000000ffffffff01344d10000000000016001430cd68883f558464ec7939d9f960956422018f0702483045022100c7fb3bd38bdceb315a28a0793d85f31e4e1d9983122b4a5de741d6ddca5caf8202207b2821abd7a1a2157a9d5e69d2fdba3502b0a96be809c34981f8445555bdafdb012103f465315805ed271eb972e43d84d2a9e19494d10151d9f6adb32b8534bfd764ab00000000

Separado

{
  "version": "02000000",
  "marker": "00",
  "flag": "01",
  "inputcount": "01",
  "inputs": [
    {
      "txid": "3aa815ace3c5751ee6c325d614044ad58c18ed2858a44f9d9f98fbcddad878c1",
      "vout": "00000000",
      "scriptsigsize": "00",
      "scriptsig": "",
      "sequence": "ffffffff"
    }
  ],
  "outputcount": "01",
  "outputs": [
    {
      "amount": "344d100000000000",
      "scriptpubkeysize": "16",
      "scriptpubkey": "001430cd68883f558464ec7939d9f960956422018f07"
    }
  ],
  "witness": [
    {
      "stackitems": "02",
      "0": {
        "size": "48",
        "item": "3045022100c7fb3bd38bdceb315a28a0793d85f31e4e1d9983122b4a5de741d6ddca5caf8202207b2821abd7a1a2157a9d5e69d2fdba3502b0a96be809c34981f8445555bdafdb01"
      },
      "1": {
        "size": "21",
        "item": "03f465315805ed271eb972e43d84d2a9e19494d10151d9f6adb32b8534bfd764ab"
      }
    }
  ],
  "locktime": "00000000"
}

Transação: 1674761a2b5cb6c7ea39ef58483433e8735e732f5d5815c9ef90523a91ed34a6

História

Por que usamos hashes de chave pública, afinal?

Porque foi assim que Satoshi decidiu fazer os endereços funcionarem na primeira versão do Bitcoin.

Acredito que isso provavelmente se deveu ao fato de Satoshi não saber que era possível usar chaves públicas comprimidas (33 bytes em vez de 65 bytes), de modo que fazer o hash da chave pública era uma forma de criar um endereço bem mais curto que você pudesse compartilhar com outras pessoas.

Diagrama mostrando como Satoshi pode não ter percebido que chaves públicas comprimidas (33 bytes) não eram muito maiores que hashes de chave pública (20 bytes).

Então talvez, se Satoshi conhecesse a existência das chaves públicas comprimidas, teríamos endereços para o script de travamento P2PK, mais simples, e o P2PKH não seria necessário.

Para deixar os endereços de Bitcoin curtos, eles são um hash da chave pública, e não a própria chave pública.
Satoshi Nakamoto, bitcointalk.org
É só para obter endereços mais curtos. Chaves públicas comuns têm 65 bytes de comprimento, o que é longo demais para ser conveniente. Chaves públicas comprimidas têm 33 bytes e poderiam, em tese, ser usadas no lugar dos hashes, embora sejam um pouco mais longas que os hashes de 20 bytes. Também parece provável que Satoshi não conhecesse as chaves públicas comprimidas ou não estivesse confortável em usá-las quando projetou o Bitcoin.
theymos, bitcoin.stackexchange.com

Teoria Alternativa: Segurança Extra

Uma teoria alternativa é que fazer o hash da chave pública fornece uma camada extra de segurança.

Por exemplo, se entregamos nossa chave pública diretamente quando queremos receber bitcoins, a "única" coisa que protege você de atacantes que tentam chegar à sua chave privada é a curva elíptica.

Diagrama mostrando uma chave pública exposta como um alvo fácil, protegida apenas pela curva elíptica.

No entanto, se entregamos um hash da chave pública, os atacantes teriam que quebrar tanto a RIPEMD-160 quanto a SHA-256 — duas funções de hashbem como lidar com o problema da curva elíptica.

Diagrama mostrando as funções de hash RIPEMD-160 e SHA-256 como barreiras extras de proteção sobre a curva elíptica.

Então, basicamente, enquanto você tem bitcoins parados na blockchain, as funções de hash funcionam como obstáculos extras que os atacantes precisam transpor para tentar chegar à nossa chave privada (e roubar nossos bitcoins).

Então a curva elíptica não é proteção suficiente?

Na verdade, é uma proteção excelente.

Graças às propriedades da multiplicação de curva elíptica, é incrivelmente difícil trabalhar de trás para frente de uma chave pública para uma chave privada. Isso é conhecido como o "problema do logaritmo discreto da curva elíptica".

No entanto, se por algum milagre esse problema for resolvido, ainda há duas funções de hash diferentes para servir de reserva na proteção da nossa chave privada.

Mas você ainda não entrega a sua chave pública?

Sim. Mas, neste sistema, a sua chave pública só é entregue no último momento (quando você vai gastar seus bitcoins).

A teoria é que, se alguém quiser quebrar a sua chave privada, terá uma pequena quantidade de tempo para fazê-lo antes que a sua transação se propague pela rede e seja minerada em um bloco. Portanto, isso é mais seguro do que deixar a sua chave pública bruta exposta desde o início.

No entanto, essa teoria não é popular com todo mundo:

Acho que essa vantagem de manter a chave pública em segredo é, na melhor das hipóteses, muito marginal, e mais comumente uma ilusão. Praticamente qualquer coisa interessante além de pagamentos simples (multisig, Lightning, ...) envolve compartilhar suas chaves públicas com partes não totalmente confiáveis. A segurança do Bitcoin depende de o ECDSA ser inquebrável mesmo quando as chaves públicas são reveladas; na minha opinião, o argumento de que "as chaves públicas só ficam expostas brevemente é uma vantagem" é culto à carga (cargo cult).
Pieter Wuille, bitcoin.stackexchange.com

Resumo

Certamente seria mais fácil se não usássemos hashes de chave pública e simplesmente usássemos chaves públicas em vez disso.

Isso significaria que poderíamos usar apenas o script de travamento mais simples, o P2PK, em vez de termos que usar o passo extra envolvido no P2PKH e no P2WPKH, onde primeiro travamos uma saída a um hash da chave pública e só depois fornecemos a chave pública original.

No entanto, Satoshi pensava nos usuários ao desenvolver o bitcoin, e ele achava que encurtar a chave pública o máximo possível antes de convertê-la em um endereço seria mais amigável, e é por isso que continuamos a usar hashes de chave pública por todo o Bitcoin até hoje.

Então, ter scripts de travamento um pouco mais complexos ao usar hashes de chave pública em vez de apenas chaves públicas é o preço que pagamos por endereços mais curtos. É um pouco desnecessário em retrospecto, mas se você conseguiu projetar e programar um sistema revolucionário e descentralizado de pagamentos eletrônicos completamente sozinho, acho que pode ser perdoado por fazer o hash de algo quando não precisava de fato.

Em conclusão, criar um hash da chave pública é bastante simples e, quando você entende a razão por trás de encurtar a chave pública em primeiro lugar, o design do P2PKH e do P2WPKH faz muito mais sentido.