Skip to content
1Claw Academy
Curriculum/Foundations4 minBeginner · Lesson 7 of 13

Lab: check that the vault file is opaque

Lab

Take the claim that the local vault is encrypted at rest and verify it yourself with strings, xxd and a wrong passphrase.

Two lessons ago you created a local vault and were told the file is encrypted with a passphrase-derived key. That is a claim about a file on your disk, and claims about files on your disk can be checked rather than believed.

Concept

This uses openssl on a file you create, so it works whether or not you set up a local vault. The construction is the same shape: a passphrase, a key derivation, and an authenticated cipher.

  1. 1

    Write a plaintext env file and encrypt it with a passphrase.

    bash
    mkdir -p /tmp/vlab && cd /tmp/vlab
    printf 'STRIPE_KEY=sk-live-9f2a\nDB_PASSWORD=prod-pw-42\n' > plain.env
    openssl enc -aes-256-cbc -pbkdf2 -iter 200000 \
      -pass pass:correct-horse -in plain.env -out vault.enc
  2. 2

    Look at the plaintext file the way anyone with read access would.

    bash
    strings plain.env
  3. 3

    Now do the same to the encrypted one. Count the matches rather than trusting your eyes.

    bash
    strings vault.enc | grep -c 'sk-live\|prod-pw'
    # -> 0
  4. 4

    Look at the actual bytes. The Salted__ header is the only thing that is not ciphertext.

    bash
    xxd vault.enc | head -2
  5. 5

    Try a wrong passphrase. It fails rather than returning garbage, because the padding check catches it.

    bash
    openssl enc -d -aes-256-cbc -pbkdf2 -iter 200000 \
      -pass pass:wrong-guess -in vault.enc
    # -> bad decrypt
  6. 6

    And the right one.

    bash
    openssl enc -d -aes-256-cbc -pbkdf2 -iter 200000 \
      -pass pass:correct-horse -in vault.enc
  7. 7

    Last check, and the one worth remembering. Encrypt the same file a second time with the same passphrase, then compare the two results.

    bash
    openssl enc -aes-256-cbc -pbkdf2 -iter 200000 \
      -pass pass:correct-horse -in plain.env -out vault2.enc
    
    shasum -a 256 vault.enc vault2.enc
    cmp vault.enc vault2.enc
  8. 8

    Same content, same passphrase, completely different bytes.

    text
    <hash-a>  vault.enc
    <hash-b>  vault2.enc
    vault.enc vault2.enc differ: char 9, line 1
  9. 9

    Clean up.

    bash
    cd /tmp && rm -rf vlab

The random salt is what makes those bytes differ, and the consequence is larger than it looks. Two vaults holding identical content are indistinguishable from two vaults holding nothing in common, so an observer who can see your encrypted files cannot tell which of them are copies, which have changed, or which two users share a password.

Watch out

The reverse is the failure to recognise: a format that produces identical ciphertext for identical input is leaking equality. That is how ECB-mode images famously stay legible, and it is why deterministic encryption is a deliberate trade rather than a default.

Three things worth taking from a check that took two minutes.

  • The salt is stored in the clear at the start of the file, and it is not secret. It exists so that the same passphrase produces a different key for every file, which is what stops one precomputed table from opening all of them.
  • The iteration count is the cost you pay on every unlock and the cost an attacker pays on every guess. 200000 here, and a deliberately large scrypt work factor in the real local vault, are the same idea.
  • A wrong passphrase produced an error rather than plausible-looking wrong output. That is the integrity check doing its job, and it is why authenticated modes are preferred.
Watch out

None of this protects a file someone can read while it is unlocked, or a passphrase in your shell history. Encryption at rest answers exactly one question: what an attacker gets from the file alone.

Check your understanding

3 questions
1

The salt sits in the clear at the start of the file. Is that a weakness?

2

What is the iteration count actually buying?

3

A wrong passphrase produced 'bad decrypt' rather than garbage. Why does that matter?