<a id="ch-09"></a>

## Chapter 9 — Programming II

<!-- open-cyber-academy:lesson-figures:start ch-09 -->
### Lesson map

Lesson 09 published. Map, example, EX025.

```mermaid
flowchart TD
  N0["Learning outcomes"]
  N1["9.1 Data structures"]
  N2["9.2 Hashing"]
  N3["9.3 Files and paths"]
  N4["9.4 Errors"]
  N5["9.5 Modules"]
  N6["Building the manifest"]
  N7["Readable output"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
  N7 --> EX["Worked example"]
  EX --> Q["Exercise EX025"]
```

### Logical drawing

```mermaid
flowchart LR
  N0["Learning outcomes"]
  N1["9.1 Data structures"]
  N2["9.2 Hashing"]
  N3["9.3 Files and paths"]
  N4["9.4 Errors"]
  N5["9.5 Modules"]
  N6["Building the manifest"]
  N7["Readable output"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX025"]
```

```text
[Learning outcomes]
    |
    v
[9.1 Data structures]
    |
    v
[9.2 Hashing]
    |
    v
[9.3 Files and paths]
    |
    v
[9.4 Errors]
    |
    v
[9.5 Modules]
    |
    v
[Building the manifest]
    |
    v
[Readable output]
    |
    v
[Worked example] --> [Exercise EX025]
```
<!-- open-cyber-academy:lesson-figures:end ch-09 -->


### Learning outcomes

You will (1) structure larger programs; (2) use dictionaries, files and hashing; (3) handle errors carefully.

### 9.1 Data structures

Dictionaries map names to values, such as file paths to digests. Lists hold ordered records. Most of Mateo's checks use both.

Mateo's checker loads the golden image manifest into a dictionary keyed by path, then walks a PC's files and looks each one up. Records of PCs are kept in a list, processed in order, and the results go into another dictionary keyed by PC name. Choosing the right structure keeps the code short and the lookups fast. Both are easy to test.

### 9.2 Hashing

A cryptographic hash such as SHA-256 produces a fixed-length digest; any change to a file changes its digest. Comparing digests is a fast way to detect changes.

The digest is much shorter than the file, so storing digests for every policy file in the image takes little space. Comparing them avoids copying whole files across the network. Mateo uses SHA-256 because it is widely supported and no practical way is known to produce two different files with the same digest.

### 9.3 Files and paths

Programs read configuration and manifest files. Paths must be handled carefully so that a check reads the intended file.

Mateo builds paths from a fixed base folder and rejects any that would point outside it, such as those containing parent-folder steps. On Windows PCs, letter case in paths may not matter, while on the analysis machine it does, so he normalises case before comparison. Small inconsistencies like these can make a checker report a file as missing when it is present.

### 9.4 Errors

If a file is missing, the program should report it, not crash or skip silently. A missing file can itself be a finding.

Mateo's checker distinguishes three outcomes: a file matches, a file differs and a file is missing. Each is reported separately. A missing policy file on a public PC may mean the restore failed or that someone removed it, and both deserve attention. Treating it as a match, or crashing so no report is produced, would hide the very problem the checker exists to find.

### 9.5 Modules

Splitting code into modules, such as one for reading data and one for checks, makes testing easier.

Mateo keeps reading, checking and reporting in separate modules. The checking module can be tested with invented data, without files or network access. If Fernhill later stores PC records in a database, only the reading module changes. Each module has its own tests, and a short main script joins them. The structure also makes it easier for Marta's staff to understand which part to change when a requirement moves.

### Building the manifest

The manifest lists each policy file in the golden image with its SHA-256 digest. It is generated when the image is released and stored with the release. A PC's files can then be compared with it at any time. Mateo stores manifests in version control so that each release has a matching manifest and differences between releases are easy to see.

He uses Python's hashlib module, part of the standard library.

### Readable output

The compare function prints the number of mismatches first, then each mismatched path.

### Testing the comparison

He tests three cases: identical files (no mismatches), one changed file (one mismatch) and one missing file (one missing report). Each case has an expected output written before the test runs.

### Worked example

Mateo writes a function that builds a digest manifest of the golden image's policy files and another that compares a PC's files with it. He tests by changing one synthetic file and confirming exactly one mismatch.

> **Synthetic case.** Synthetic.

### Errors and limits

Hashing detects change but does not say whether the change is harmful.

### Exercises

- **EX025 — Hash property.** What happens to a digest when a file changes? *Rubric:* 3 = it changes; 2 = partial; 1 = vague; 0 = none.
- **EX026 — Missing files.** How should a missing file be handled? *Rubric:* 3 = report it; 2 = partial; 1 = vague; 0 = none.
- **EX027 — Test.** How did Mateo test his compare function? *Rubric:* 3 = changed one file, expected one mismatch; 2 = partial; 1 = vague; 0 = none.

### Synthesis

Hashing and careful error handling make change detection reliable.

### Continue studying — chapter 09 of 50

[← Chapter 08 (draft)](#ch-08) · [Course chapter index](../SUBJECTS.md) · [Chapter 10 (draft) →](#ch-10)

## Worked answers

<a id="answer-ex025"></a>
**EX025.** The digest changes.

<a id="answer-ex026"></a>
**EX026.** Report it as a finding.

<a id="answer-ex027"></a>
**EX027.** By changing one synthetic file and confirming exactly one mismatch.
