◇ OpenCyber Academy
Engineering · Chapter 4 · English

Chapter 4 — Programming I

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

Chapter 4 — Programming I

Lesson map

Lesson 04 published. Map, example, EX010.

flowchart TD
  N0["Learning outcomes"]
  N1["4.1 Bytes are not text"]
  N2["4.2 Using hashlib"]
  N3["4.3 Canonical formats"]
  N4["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4
  N4 --> EX["Worked example"]
  EX --> Q["Exercise EX010"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["4.1 Bytes are not text"]
  N2["4.2 Using hashlib"]
  N3["4.3 Canonical formats"]
  N4["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> Q["EX010"]
[Learning outcomes]
    |
    v
[4.1 Bytes are not text]
    |
    v
[4.2 Using hashlib]
    |
    v
[4.3 Canonical formats]
    |
    v
[Synthesis]
    |
    v
[Worked example] --> [Exercise EX010]

Learning outcomes

You will (1) represent bytes, text and hexadecimal correctly; (2) use the standard library's hash functions; (3) avoid common encoding errors that break cryptographic checks.

4.1 Bytes are not text

Cryptographic functions operate on bytes, not characters. In Python, "litres" is text and b"litres" is bytes; converting between them requires an explicit encoding such as UTF-8. Aiyana's first bug comes from hashing a reading on one system with a different encoding from another, so equal readings produced different digests. She learns to fix one canonical encoding in the specification, to convert once at the boundary and to keep bytes everywhere inside. Hexadecimal is a display format for bytes: two hex characters represent one byte, which is why a 32-byte SHA-256 digest prints as 64 characters.

4.2 Using hashlib

The hashlib module provides SHA-256 and other functions from FIPS 180-4. A hash maps input of any length to a fixed-length digest; changing one bit changes about half the output bits. Aiyana writes small functions that hash a reading string and print the hexadecimal digest, then checks published test vectors from the standard to confirm she is calling the function correctly. She learns the difference between calling update repeatedly on a hash object, which hashes the concatenation, and hashing each piece separately, which gives different results that confused her first test.

4.3 Canonical formats

Two programs must agree byte for byte before hashes or signatures can match. Aiyana defines a canonical reading format for Ridgeway: fixed field order, semicolon separators, integer litres and timestamps in UTC with a trailing Z. She avoids floating-point litres because 18342.0 and 18342 would hash differently. She also avoids letting a dictionary's printing order define the bytes. This discipline anticipates later chapters, where readings are authenticated with HMAC and firmware with signatures; both fail, harmlessly but confusingly, if sender and receiver disagree about the exact bytes.

Worked example

Aiyana fixes a failing test by encoding readings as UTF-8 once, using integer litres and UTC timestamps, then confirms her SHA-256 calls against a FIPS 180-4 test vector.

Synthetic case. The reading format is invented for Ridgeway; FIPS 180-4 is real.

Errors and limits

Hashing is not encryption: anyone can compute a digest. Mixing text and bytes silently changes results, so specify encodings explicitly.

Exercises

Synthesis

Correct cryptographic programming starts with bytes, explicit encodings, verified test vectors and a canonical format both sides agree on.

Continue studying — chapter 04 of 50

← Chapter 03 (draft) · Course chapter index · Chapter 05 (draft) →