Checksum

Detecção simples de erros

Diagrama mostrando como um checksum é usado para detectar erros em dados.

Um checksum é um pequeno pedaço de dado que permite verificar se outro pedaço de dado está igual ao esperado.

Eles são mais comumente encontrados dentro de endereços para detectar erros de digitação. Isso ajuda a evitar enviar bitcoins para o endereço errado.

Checksum

Crie um checksum para alguns dados.

Alguns bytes de dados para os quais você quer criar um checksum

0 bytes

Primeiros 4 bytes de hash256(dados)

Esperado:

Os dados originais com o checksum anexado

0 bytes

Para sermos mais precisos, um checksum pode ser adicionado ao fim de um dado para criar um dados+checksum combinado.

Então, quando você reinsere esse dado inteiro em algum lugar mais tarde, dá para garantir que está tudo correto verificando se o dados ainda bate com o checksum:

Diagrama mostrando alguns dados com um checksum válido.

Se você cometesse um erro, o dados não bateria com o checksum (ou vice-versa) e você seria alertado de que o dado está incorreto de alguma forma:

Diagrama mostrando alguns dados com um checksum inválido.

Este tipo de checksum não ajuda na correção de erros. O checksum detecta erros, mas não vai ajudar dizendo onde está o erro nem como ele deve ser corrigido.

Localização

Onde os checksums são usados no Bitcoin?

Aqui estão alguns exemplos de onde os checksums são usados no Bitcoin:

Os endereços Bech32 modernos também contêm checksums, mas são mais complexos que os checksums simples descritos nesta página.

Criando

Como você cria um checksum?

Diagrama mostrando um checksum como os primeiros 4 bytes do HASH256 de alguns dados.

Um checksum é criado pegando os primeiros 4 bytes do HASH256 de um dado.

Por exemplo:

dados          = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
hash256(dados) = 05c4de7c1069e9de703efd172e58c1919f48ae03910277a49c9afd7ded58bbeb
checksum       = 05c4de7c
Ícone Ferramenta HASH256

HASH256

SHA-256 dupla. Usada para fazer o hash de cabeçalhos de bloco, dados de transação e de praticamente qualquer coisa que precise ser hasheada no Bitcoin.

0 bytes
SHA-256
SHA-256

SHA-256(SHA-256(dados))

0 bytes
# ---------
# Funções
# ---------

require 'digest'

# função hash256 (checksums usam hash256)
def hash256(hex)
  binary = [hex].pack("H*")
  hash1 = Digest::SHA256.digest(binary)
  hash2 = Digest::SHA256.digest(hash1)
  result = hash2.unpack("H*")[0]
  return result
end

# função checksum
def checksum(hex)
  hash = hash256(hex) # passa os dados pelo SHA256 duas vezes
  return hash[0...8]  # retorna os primeiros 4 bytes (8 caracteres)
end

# ---------------
# Criar Checksum
# ---------------

# dados
data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

# checksum
puts checksum(data) #=> 05c4de7c

Verificando

Como você verifica um checksum?

Para verificar um checksum, você só precisa checar se o dado faz hash para o checksum que foi fornecido junto com o dado.

Em outras palavras, você só recalcula o checksum:

# dados originais
dados+checksum = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa05c4de7c
dados          = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
checksum       = 05c4de7c

# verificação do checksum
hash256(dados) = 05c4de7c1069e9de703efd172e58c1919f48ae03910277a49c9afd7ded58bbeb
checksum       = 05c4de7c <- bate

Este é apenas um exemplo simples, mas o processo é o mesmo em todo o Bitcoin.

# ---------
# Funções
# ---------

require 'digest'

# função hash256 (checksums usam hash256)
def hash256(hex)
  binary = [hex].pack("H*")
  hash1 = Digest::SHA256.digest(binary)
  hash2 = Digest::SHA256.digest(hash1)
  result = hash2.unpack("H*")[0]
  return result
end

# função checksum
def checksum(hex)
  hash = hash256(hex) # passa os dados pelo SHA256 duas vezes
  return hash[0...8]  # retorna os primeiros 4 bytes (8 caracteres)
end

# -----------------
# Verificar Checksum
# -----------------

# dados+checksum
datachecksum = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa05c4de7c"

# dados
data = datachecksum[0...40]

# checksum
checksum = datachecksum[40...48]

# verificação
puts checksum(data) == checksum #=> true

Confiabilidade

Quão confiáveis são os checksums no Bitcoin?

Há uma chance de 1 em 4.294.967.295 de um checksum não detectar um erro.

Um checksum tem 4 bytes de tamanho. Isso significa que existem apenas 0xFFFFFFFF (4.294.967.295) checksums possíveis, então há uma chance de que dois pedaços diferentes de dados acabem tendo o mesmo checksum.

Em outras palavras, se você cometer um erro de digitação ao inserir um endereço, há aproximadamente uma chance de um em quatro bilhões de que o checksum resultante seja inadvertidamente o mesmo e o erro de digitação não seja detectado.

Então é muito improvável, mas possível.

Seria mais confiável usar o resultado completo do hash de 32 bytes como checksum. No entanto, isso deixaria os endereços muito mais longos, então pegar apenas os primeiros 4 bytes encontra um equilíbrio entre a praticidade e manter os endereços tão curtos quanto possível.

Terminologia

Por que se chama "checksum"?

Os primeiros checksums costumavam ser literalmente a "soma" (sum) de um dado. Então, por exemplo, digamos que eu quisesse armazenar a seguinte string:

abc

Para criar um checksum simples para ela, eu poderia simplesmente dar a cada caractere um número (ex.: a = 1, b = 2, c = 3) e adicionar a soma deles ao final:

abc+6

Se eu cometesse um erro de digitação ao transcrever essa string mais tarde, assim:

abb+6

O checksum não bateria mais com a soma dos caracteres (abb = 1 + 2 + 2 = 5), e eu saberia que cometi um erro em algum lugar. Então, ao "checar" a "soma" (check the sum), consigo ver que algo deu errado em algum ponto. Daí o nome "checksum".

De qualquer forma, no Bitcoin nós na verdade usamos uma função de hash para criar o checksum, que é uma impressão digital mais confiável para o dado do que simplesmente somar caracteres. Mesmo assim, ele faz o mesmo trabalho, e é por isso que ainda chamamos esse pedaço extra de dado de detecção de erros de checksum.

Obrigado ao Greg Maxwell pela rápida aula de ciência da computação sobre (e a história dos) checksums.

Resumo

Um checksum é uma ferramenta útil para detectar erros de digitação.

Como usuário, é bom saber que coisas como endereços contêm checksums. Então, se você cometer um erro ao digitar um endereço numa carteira, pode ter bastante certeza de que a carteira vai detectar quaisquer erros e impedir você de enviar bitcoins para o endereço errado e perdê-los para sempre.

É melhor pensar nos checksums como uma rede de segurança reserva. Não há substituto para conferir um endereço duas (ou três) vezes.

Como desenvolvedor, se algo contém um checksum, você deveria sempre usá-lo para verificar se o dado está correto. É para isso que eles existem. E se você conseguir salvar uma pessoa de perder moedas, então vale o pouco tempo que leva para escrever o código de verificação do checksum.

Os checksums são usados em toda a ciência da computação, e são muito úteis para a detecção simples de erros, então são uma ferramenta conveniente para se ter na sua caixa de ferramentas de programação.

Recursos