7. Documents outside the chain
A notary does not keep your 40-page contract in the register: they write the number, the date and a seal. If someone changes the contract, the seal no longer matches.
Why not put the PDF on the chain
Writing on the chain costs money and every item stays visible to everyone forever. A PDF or photo is heavy and may contain information we do not want to make public. So we put only the fingerprint on the chain, 32 bytes (type bytes32), while the file lives on the project's server (the backend).
How to compute it
import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
// 1. Il file resta sul server: qui lo leggiamo come sequenza di byte.
const byte = readFileSync("referto.pdf");
// 2. L'impronta sha256 sono 32 byte: li scriviamo come 64 caratteri esadecimali.
const impronta = "0x" + createHash("sha256").update(byte).digest("hex");
console.log(impronta); // questo valore (bytes32) va nel contratto come docHashLine by line
- The first two lines take two tools already included in Node.js: one for the fingerprint, one for reading files.
readFileSyncreads the PDF and turns it into bytes.createHash("sha256")prepares the calculation,updatefeeds it the bytes,digest("hex")returns the result as letters and digits.- We prefix
0xso the contract recognises abytes32value.
The same function is used for verification: anyone who downloads the document can redo the calculation.
// Ricalcolo: l'impronta del file scaricato deve essere uguale a quella sulla catena.
function documentoIntegro(fileBytes, docHashSullaCatena) {
const ora = "0x" + createHash("sha256").update(fileBytes).digest("hex");
return ora === docHashSullaCatena.toLowerCase();
}Line by line
- The function receives the bytes of the downloaded file and the fingerprint read from the chain.
- It recomputes the fingerprint with the same method.
- It returns true only if the two match;
toLowerCase()ignores upper/lower case differences.
In the demo the backend computes the fingerprint when the file arrives (at most 5 MB, PDF, JPG or PNG only), stores the file and writes the fingerprint on the chain as docHash. At verification the public page compares the two fingerprints for each document.
A useful detail: the fingerprint proves the file has not changed since registration, not that its content was true.
Try it yourself
Save any text file, compute its fingerprint with the script above, then change one letter in the file and recompute. Compare the two fingerprints with the documentoIntegro function.
What you learned
- Only the 32-byte fingerprint is written on the chain, not the file.
- The file lives on the backend and anyone can recompute its fingerprint.
- The fingerprint proves the file is unchanged, not that it is true.