🎓 A1Learner
🔍

Rust SHA-256 Fingerprints

A SHA-256 fingerprint is a cryptographic hash that stays the same across machines and across years. The speed hashers in the earlier lessons only had to work inside one programme.

Hash one word

Sha256 reads the bytes and finalize ends the job. The word abc has a world-famous answer.

let mut hasher = Sha256::new();
hasher.update(b"abc");
println!("abc = {:x}", hasher.finalize());

Even nothing has a fingerprint

Empty input still earns a full digest. This one is printed in test suites everywhere.

let mut hasher = Sha256::new();
hasher.update(b"");
println!("empty = {:x}", hasher.finalize());

Feed it in pieces

A file can stream through in chunks. The digest cannot tell where the cuts were.

let mut hasher = Sha256::new();
hasher.update(b"ab");
hasher.update(b"c");
println!("ab then c = {:x}", hasher.finalize());

One letter changes everything

Change abc to abd and the digest lands somewhere unrelated. This landslide is called the avalanche effect.

println!("abd = {:x}", Sha256::digest(b"abd"));

Count the bytes

SHA-256 always answers with 32 bytes. The hex form doubles that to 64 characters.

let digest = Sha256::digest(b"abc");
println!("bytes = {}", digest.len());

Example

// Cargo.toml: sha2 = "0.10"
use sha2::{Digest, Sha256};

fn fingerprint(text: &str) -> String {
    let mut hasher = Sha256::new();
    hasher.update(text.as_bytes());
    format!("{:x}", hasher.finalize())
}

fn main() {
    println!("abc = {}", fingerprint("abc"));
    println!("abd = {}", fingerprint("abd"));
    println!("empty = {}", fingerprint(""));
    let mut chunked = Sha256::new();
    chunked.update(b"ab");
    chunked.update(b"c");
    println!("chunks match = {}", format!("{:x}", chunked.finalize()) == fingerprint("abc"));
}

Key points

  • Add sha2 = "0.10" to Cargo.toml
  • The standard library ships no cryptographic hash
  • Use update to feed bytes, in one call or in many chunks
  • Use finalize to close the job and take the digest
  • A digest is a fingerprint, not a box
  • Nothing can be unpacked from it
  • The input is gone by design
  • Publishers print a SHA-256 beside a download
  • Your digest either matches it, or the file is not the file
  • For passwords, reach for a password hash like Argon2 or bcrypt instead
  • SHA-256 is fast, and fast is what password guessing wants
  • A SHA-256 fingerprint is the same on every machine and in every year.

In this example, a small helper hashes a whole string in one go. The word abc lands on its famous published digest. The word abd, one letter later, lands somewhere unrelated. Empty input still earns a full digest. At the end, a second hasher eats ab and c in two bites. Its digest matches the one-shot abc exactly. Chunk borders leave no trace.

Note

Hashing is not encoding

Base64 can be undone by anyone, but a digest cannot be undone at all, by anyone, key or no key

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

A download page prints a SHA-256 beside the file. What does matching it prove?