# Rotate a key without losing or transplanting records

Use the complete synthetic fixture below in a notebook or text file. No live target, paid service or secret is needed. Make your own decision before opening the worked assessment. Then take the implementation option below, a local project in which you repair running code until its tests pass, and keep its test output with your written answers.

A document service is replacing a compromised wrapping key. Decide which operations are safe and design evidence for migration and recovery.

## Supplied material

```text
Record contract: AES-GCM with an opaque random data key per document; each encryption requires a fresh nonce under that data key. Associated data is canonical encoding of tenant ID, document ID and record schema version. The data key is wrapped by a KMS key.
R1: tenant north, document 7, schema 2, wrapping key K-old, data key D1, nonce N1, ciphertext C1.
R2: tenant south, document 7, schema 2, wrapping key K-old, data key D2, nonce N2, ciphertext C2.
Migration M1: unwrap D1 and rewrap the same D1 under K-new; leave C1 and its encryption nonce unchanged.
Migration M2: edit R1 plaintext, encrypt again using D1 and N1.
Migration M3: copy C1 into R2 and replace the visible tenant field with south.
Backup B from Monday contains K-old-wrapped data keys. Current data has all been rewrapped, but B has not been restore-tested.
Threat update: the K-old wrapping credential was exposed; whether plaintext data keys were extracted is unknown. K-old remains enabled for a seven-day overlap.
Legacy client L negotiates an obsolete cipher suite; its certificate uses the same private key as a second forgotten endpoint.
```

## Task 1

Classify M1–M3 as allowed or rejected under the record contract and explain which cryptographic input changes.

Your assessment:

## Task 2

Draw a rotation state machine covering new writes, reads during overlap, retry-safe migration and retirement.

Your assessment:

## Task 3

Separate wrapping-key compromise from possible data-key compromise, and describe what evidence changes the rewrap-versus-reencrypt decision.

Your assessment:

## Task 4

Write backup restoration and shared-TLS-key discovery tests before authorizing deletion or retirement.

Your assessment:

## Decide the fixed cases

### Is each migration allowed under the record contract?

Choose from: Allowed; Rejected.

- M1: rewrap D1 under K-new; C1 and its nonce unchanged: ______
- M2: edit R1's plaintext and encrypt again with D1 and N1: ______
- M3: copy C1 into R2 and change the visible tenant to south: ______

### Decide the key questions.

Choose from: Yes; No.

- Can K-old be deleted now that current data is rewrapped?: ______
- Does rewrapping undo a possible disclosure of D1?: ______

## Evidence

- Operation decision table with key/nonce/AAD reasoning.
- Migration ledger with old/new key IDs, document identity and completed verification.
- Compromise assessment and backup restore acceptance criteria.
- Legacy endpoint inventory and ownership record.

## Rubric

Score each criterion with the anchor whose evidence your answer shows: 0, 1 or 2 points. Every anchor describes something a reviewer can point to in your work. Aim for at least 7 of 8, with no unresolved critical failure.

### 1. Correctly distinguishes rewrap, fresh encryption and authenticated-context substitution. (2 points)

- 0 points: Allows M2 or M3, or rejects M1 as nonce reuse.
- 1 point: M1 allowed and M2 and M3 rejected, but one reason is wrong, for example that M3 fails because the key differs rather than because the associated data no longer matches.
- 2 points: M1 allowed: only the wrapping of D1 changes, and C1 and N1 are untouched, so nothing is encrypted again. M2 rejected: new plaintext under D1 with the same nonce N1 breaks AES-GCM’s uniqueness requirement. M3 rejected: decrypting C1 with south, document 7, schema 2 as associated data fails authentication.

Your score:

### 2. Migration is retry-safe and separates read overlap from new-write policy. (2 points)

- 0 points: A single big-bang rewrap, with no plan for reads during the overlap or for a run that stops halfway.
- 1 point: New writes use K-new and reads accept both keys, but a rerun after a crash could process records twice or skip them, or retirement is not gated on evidence.
- 2 points: A state machine in which new writes use K-new only, reads follow the key ID stored with each record during the seven-day overlap, migration records the old and new key ID per document and skips records already rewrapped on a rerun, and K-old retires only when the ledger shows every record and backup migrated and verified.

Your score:

### 3. Compromise reasoning addresses exposed data keys and retained backups. (2 points)

- 0 points: Says rewrapping fixes the exposure.
- 1 point: Says data keys may have been exposed, but not which evidence changes the plan, or leaves out backup B.
- 2 points: Separates the cases: if only the wrapping credential leaked, rewrapping protects data from now on; if data keys could have been unwrapped while it was exposed, which is unknown here, the affected records need new data keys and an incident assessment. Backup B still depends on K-old and needs its own path.

Your score:

### 4. Retirement evidence includes restore tests and every endpoint sharing trust material. (2 points)

- 0 points: Disables or deletes K-old on schedule, or replaces the TLS key on client L’s endpoint only.
- 1 point: Requires a restore test of B but does not inventory the second endpoint that shares the TLS key, or the reverse.
- 2 points: Acceptance criteria: restore B in an isolated environment and decrypt a sample with a tightly scoped old key before rewrapping it; list every endpoint presenting the shared TLS key, replace it on all of them and record their owners; retire K-old only after both are signed off.

Your score:

Critical failures (resolve before calling the case complete):

- [ ] Reuses D1,N1 for M2.
- [ ] Deletes the only unwrap key for a required backup.
- [ ] Claims rewrapping reverses past plaintext disclosure.

## Implementation option: Bind ciphertext to the correct record

Repair authenticated context binding in exercise.mjs until all 10 tests pass, then add a test that reproduces migration M3: ciphertext copied from one tenant’s record into another’s.

Keep: Failing and passing test output, and the added M3 test with the associated data it expects.

Download: https://softwaresecurity.com/downloads/projects/encrypted-records-0959d731656638c9.zip (Node.js 22+ · no dependencies, 10 tests). Instructions: https://softwaresecurity.com/labs/#project-encrypted-records

## Worked assessment (read after completing the case)

M1 is rewrapping, so it need not re-encrypt C1 and does not reuse a nonce for a new encryption. M2 violates uniqueness by encrypting new plaintext under D1,N1. M3 fails when decryption authenticates the expected south/7/schema-2 context; trusting attacker-supplied context would defeat the binding. Rewrap does not undo disclosure of D1 or plaintext; proven or plausible data-key compromise requires a separately assessed data re-encryption/incident response plan. Keep the old unwrap capability only as tightly scoped and time-bounded as recovery requires. Do not delete K-old until retained backups have a verified restoration or migration path. Inspect every endpoint using the shared TLS key, not only L.

Original teaching material: CC BY 4.0. Attribution: Software Security.
