Skip to main content

← All projects

TCrypt: secrets that only open on one machine

  • .NET 10 Native AOT
  • Python
  • AES-256-GCM
  • TPM 2.0
  • systemd credentials

Most secret managers just move the problem: your passwords and API keys go into a vault, and the vault is unlocked by one powerful master password or token, which then has to live somewhere too. TCrypt ends the chain in hardware instead. The key is locked inside the server's own TPM security chip, so there's no master password to store, leak or forget.

  1. TPM chip (hardware)
  2. sealed key file on disk (useless anywhere else)
  3. systemd unseals it at service start
  4. the app decrypts its config
  5. secrets live only in memory

No "secret zero"

Nothing to type at boot, nothing in an environment variable, no master token in a file. The chip itself is the last link.

The "Suitcase" pattern

Secrets ride in a Suitcase section of the app's config, encrypted with AES-256-GCM. Change a single byte and decryption refuses.

Apps never touch the TPM

systemd's encrypted credentials do the unsealing and hand the key to the service at startup. The app just reads a file that exists only while it runs.

Bound to this box

The key is sealed to the machine's Secure Boot state. Copy the disk, the backups or the config somewhere else, and they're just noise.

Simple on purpose

The format is nonce + ciphertext + tag, Base64-encoded. Any language with AES-GCM can read it, which is why there's a Python twin.

The repos (MIT licensed)​

RickAtSnowcap/tcrypt-lib

The .NET 10 library: AES-256-GCM encrypt and decrypt, and loading the key from systemd. Native AOT friendly.

RickAtSnowcap/tcrypt-pack

A CLI that encrypts a value and writes it straight into a config file's Suitcase section.

RickAtSnowcap/tcrypt-py

The Python side, so data-loading scripts can read the same encrypted values.

RickAtSnowcap/tcrypt-lib-tests

The test suite: round trips, tamper detection, Unicode, edge cases and systemd credential loading.