monkeys
Concepts

*.monsecrets

A bundle, a.monsecrets unless you name it, is one or more profiles with their keys and secrets in a single encrypted file. pack writes one and unpack reads…

A bundle, a.monsecrets unless you name it, is one or more profiles with their keys and secrets in a single encrypted file. pack writes one and unpack reads it, and that is the only way a secret leaves the vault.

Format

Two lines of text:

monkeys bundle 1 scrypt 17 8 1
<salt and sealed bytes, base64>

The first line names the format and the scrypt cost the key was derived with, log2 N, r and p, so a bundle keeps opening after the default cost rises. The second is the salt followed by the sealed bytes, in base64. Inside, the bundle keeps the shape of the .monkeys file, namespace line and blocks, so unpack can write the file back and store each secret under its profile.

Security

The sealed bytes are ChaCha20-Poly1305, the AEAD of RFC 8439 that TLS 1.3, WireGuard and OpenSSH use. A bundle that has been altered fails to open rather than opening wrong, and a wrong passphrase fails the same way.

The key is derived from the passphrase with scrypt (RFC 7914) and a fresh 16-byte salt each time, at N = 2^17, r = 8, p = 1. Deriving it costs 128 MiB of memory and a fraction of a second, once for pack and once for unpack; that memory is what keeps a guess from being cheap to run in parallel. The passphrase is the weakest part, so it goes by another route than the file.

A header that asks for a cost outside a fixed range is refused before any work is done, so a crafted file cannot make unpack run for hours.

Sharing one

The file is safe to send over whatever you already use, and the passphrase goes another way. unpack deletes the bundle once it has done its job; pack writes it to /tmp, outside any repository. Sharing a profile walks through it.

If one is committed

A bundle has no reason to be in a repository, and .monkeys needs no ignore rule, since it is meant to be committed. If a bundle is committed by mistake anyway, what leaked is a sealed file: without the passphrase it is noise, and the fix is to delete it and change the passphrase you would have sent.

On this page