We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Key Management and Rotation

Encrypted data is only as safe as the key used to encrypt it. But a single unversioned key means replacing it makes every value encrypted with the old key unreadable!

Instead, use a keyring. This isn't as complex as it sounds: start with one key and call it version 1 (v1):

DOCUMENT_ENC_KEY_V1=A927FD...

Then, whenever you encrypt a value, store its key version with the ciphertext:

Ciphertext Key Version
0xdeadbeef... v1
0xfeedface... v1
... ...

Rotate Without Losing Data

When you need to rotate your key, add a new one and change the active version:

DOCUMENT_ENC_KEY_V1=A927FD...
DOCUMENT_ENC_KEY_V2=3B1C9A...
DOCUMENT_ENC_ACTIVE_VERSION=v2

Your application should always decrypt with the version recorded on the payload and encrypt with the current active version. That way, old ciphertext remains readable after rotation.

If a key was compromised, rotate it and re-encrypt live data as soon as you can. This limits future exposure, but it can't protect ciphertext an attacker already copied with the old key.

Losing an encryption key can mean permanently losing the data it protects. Treat rotation, backup recovery, access control, and key retirement as one lifecycle.

Assignment

Bearly Secure already routes TOTP secrets through encryptStringWithKeyring and decryptStringWithKeyring in src/storage/keyring.ts, but both are insecure pass-throughs, and the app treats the keyring as optional. Complete the versioned keyring so TOTP secrets are encrypted at rest with the active key.

  1. DATA_ENCRYPTION_ACTIVE_VERSION=v1
    DATA_ENCRYPTION_KEY_V1=replace_with_64_hex_characters
    

Run and submit the CLI tests from the project root.