Checksum
Detecção simples de erros
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.
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:
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:
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:
- Endereços – Todo endereço Base58 (os que começam com 1 ou 3) contém um checksum. Isso ajuda a evitar perder bitcoins ao enviá-los para o endereço incorreto caso você cometa um erro de digitação.
- Chaves privadas WIF – Uma chave privada WIF é como um formato de endereço para uma chave privada. Elas também contêm checksums, então você pode ser informado caso esteja importando uma chave privada incorreta para uma carteira.
- Chaves estendidas – Toda chave privada estendida e chave pública estendida contém o seu próprio checksum. Novamente, isso permite detectar erros ao transcrevê-las.
- Mensagens de rede – Toda mensagem trocada entre os nós da rede tem um checksum anexado a ela. Isso permite detectar se a mensagem foi adulterada ou se foi corrompida durante a transmissão.
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?
Um checksum é criado pegando os primeiros 4 bytes do HASH256 de um dado.
Por exemplo:
dados = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
hash256(dados) = 05c4de7c1069e9de703efd172e58c1919f48ae03910277a49c9afd7ded58bbeb
checksum = 05c4de7c
HASH256
# ---------
# 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.