OpenCyber Academy
Rapid course · Lesson 6 · English
Course code: OCA-017Lesson 06: OCA-017-A006

Twelve characters are not the digest

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Lesson map

Lesson 06. Map, example, EX052.

flowchart TD
  H["sha256 of the bytes"] --> X["hexdigest, 64 characters"]
  X --> S["slice the first 12"]
  S --> Q{"Is the slice the key?"}
  Q -->|No| K["The lookup used the full digest"]

The page shows a prefix. The dict key is the whole fingerprint.

Logical drawing

computed
  hexdigest, 64 hex characters
printed
  the first 12 only
lookup
  the full digest, before the slice
three prefixes on the page
  0edf30e2fa30
  3e5d3b83407c
  ffcab6e8630a

Learning outcomes

After this chapter, you should be able to:

  1. Separate hexdigest from the slice h[:12].
  2. Say which value is the dict key.
  3. Refuse a note that treats a prefix as the stored fingerprint.

6.1 The slice is a reading aid. The key is the full digest.

hashlib.sha256(data).hexdigest() returns 64 hexadecimal characters. That length is the whole SHA-256 result written in hex: 256 bits, four bits to a character. The print uses h[:12], so the page keeps the first 12 characters and drops the other 52. Twelve hex characters are 48 bits. They are enough to tell these three rows apart on a classroom page. They are not the value the script stored for the lookup.

The lookup happens before the slice is a problem for a careful reader, because the code computes h once and then uses that same h twice. known_bad.get(h, 'no match') searches for the 64-character string. The f-string then prints h[:12]. A classmate who copies only the visible prefix has not copied the key. Two different files can share a 12-character opening in principle. This run's three openings differ, and that fact does not promote the prefix into an identity.

Kornblum (2006) describes a way to notice files that are almost the same. This script does not do that. It asks whether the full digest is exactly the one key. A one-byte change in the byte string would miss. The chapter does not print the hidden 52 characters, because the lab did not print them.

Lesson table; scroll horizontally to read all columns →

Piece Role in this file
hexdigest() 64-character fingerprint
h[:12] The characters on the page
known_bad.get(h, ...) Lookup of the full fingerprint
The other 52 characters Computed, not printed

6.2 Worked example

Lesson table; scroll horizontally to read all columns →

Offered reading What the file does Decision
3e5d3b83407c is on the installer row First 12 of that row's digest Keep
The key is those 12 characters The key is the unprinted full digest Refuse
"Paste the prefix into a new list as the key." The list was built from hexdigest() Refuse
The three prefixes differ True of this run, and still a prefix Keep

Synthetic case. The lab page shows prefixes only.

Errors and limits

Do not invent the hidden characters in order to look complete.

Apply

  • EX052 — Prefix. Each row shows 12 hex characters. Is that slice the dict key, and does this page print the other 52 characters?
    Show marking criteria
    Rubric: 3 = no; hexdigest is 64 characters; the lookup uses the full digest; the page prints h[:12] only; do not fill in the rest;; 2 = the key is the full digest and the rest is unprinted;; 1 = the prefix only;; 0 = none.
Worked answers

EX052. No. hexdigest is 64 characters. The lookup uses that full digest. The page prints the first 12 only. Do not fill in the rest.