SHA-256 de arquivo: como gerar e conferir sem estourar a memória

O SHA-256 de um arquivo é uma impressão digital de 64 caracteres: se o arquivo mudar um único byte, o valor muda por completo. Este guia mostra como gerar e conferir esse valor pelo terminal e em Node.js, Python e PHP, lendo o arquivo em pedaços para que arquivos grandes não consumam a memória.

Por Leonardo Gaertner · Publicado em

Para que serve o SHA-256 de um arquivo

Quem publica um arquivo (um instalador, uma imagem de sistema, um backup) costuma divulgar o SHA-256 dele. Você calcula o valor do arquivo baixado e compara com o publicado: se forem iguais, o arquivo chegou íntegro, sem corrupção no download.

Para um arquivo pequeno, o gerador de SHA-256 resolve direto no navegador, sem enviar o arquivo a nenhum servidor. O gerador de hash oferece também outros algoritmos. Este guia cobre o caso de automatizar isso em código ou no terminal.

Pelo terminal

  • Linux: sha256sum arquivo.iso
  • macOS: shasum -a 256 arquivo.iso
  • Windows (PowerShell): Get-FileHash arquivo.iso -Algorithm SHA256

O resultado são 64 caracteres hexadecimais. Compare com o valor publicado, de preferência copiando e colando, e não lendo a olho.

Em Node.js

Ler o arquivo inteiro com readFile ocupa a memória do tamanho dele. Com um stream, o Node.js entrega pedaços e o hash é atualizado aos poucos:

JavaScript
import { createReadStream } from 'node:fs';
import { createHash } from 'node:crypto';

async function sha256Arquivo(caminho) {
  const hash = createHash('sha256');
  // Lê em pedaços: o arquivo inteiro nunca fica na memória
  for await (const pedaco of createReadStream(caminho)) {
    hash.update(pedaco);
  }
  return hash.digest('hex');
}

Em Python

O objeto de hash aceita várias chamadas a update, então basta ler o arquivo em blocos de tamanho fixo:

Python
import hashlib


def sha256_arquivo(caminho: str) -> str:
    h = hashlib.sha256()
    with open(caminho, "rb") as f:
        # Lê 1 MiB por vez: o arquivo inteiro nunca fica na memória
        for pedaco in iter(lambda: f.read(1024 * 1024), b""):
            h.update(pedaco)
    return h.hexdigest()

Em PHP

O PHP já tem a função pronta, que lê o arquivo em pedaços por dentro:

PHP
<?php
function sha256Arquivo(string $caminho): string
{
    // hash_file lê o arquivo em pedaços, sem carregá-lo inteiro
    $hash = hash_file('sha256', $caminho);
    if ($hash === false) {
        throw new RuntimeException('Não foi possível ler o arquivo');
    }
    return $hash;
}

Cuidados na conferência

  • O valor só prova a integridade se veio de um canal confiável. Se um invasor troca o arquivo e o SHA-256 na mesma página, a conferência não detecta nada. Prefira o valor de um site oficial separado, ou uma assinatura digital do autor.
  • Compare o texto inteiro, com todos os 64 caracteres, e ignore a diferença entre maiúsculas e minúsculas, que não altera o valor.
  • Não use MD5 ou SHA-1 para segurança: já existem colisões práticas nos dois. Para conferir só se um download corrompeu, eles funcionam, mas o SHA-256 é a escolha padrão.
  • Um hash não é adequado para guardar senhas: ele é rápido demais. Para senhas use bcrypt, scrypt ou Argon2.

Achou um erro neste guia? Avise por e-mail.

Perguntas frequentes

Quantos caracteres tem o SHA-256 de um arquivo?

Sempre 64 caracteres hexadecimais (256 bits), seja o arquivo de poucos bytes ou de vários gigabytes.

Dois arquivos diferentes podem ter o mesmo SHA-256?

Em teoria sim, mas ninguém conhece uma forma de encontrar uma colisão no SHA-256, e a chance por acaso é desprezível. Por isso ele é aceito como impressão digital do arquivo.

Renomear o arquivo muda o SHA-256?

Não. O hash depende só do conteúdo em bytes, não do nome, da data ou do local. Mudar um único byte do conteúdo muda o valor por inteiro.

Como conferir o SHA-256 de um arquivo grande no navegador?

O gerador de SHA-256 do PraDev lê o arquivo no próprio navegador, sem enviá-lo. Para arquivos muito grandes, o terminal ou um script, como os deste guia, costuma ser mais rápido.