Skip to content

hakavlad/tird

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Logo

πŸ“œΒ manΒ page Β  πŸ“‘Β Specification Β  πŸ“„Β InputΒ Options Β  πŸ“–Β Tutorial Β  ❓ FAQ Β  πŸ“₯Β Installation


Releases PyPI CodeQL trivy Bandit Semgrep

Β Table of Contents

About

tird /tΙͺrd/ (an acronym for "this is random data") is a file encryption tool focused on

  • minimizing metadata and
  • hiding encrypted data.

With tird, you can:

  1. Create files filled with random data to use as containers or keyfiles.
  2. Overwrite the contents of block devices and regular files with random data to prepare containers or destroy residual data.
  3. Encrypt file contents and comments with keyfiles and passphrases. The encrypted data format (cryptoblob) is a padded uniform random blob (PURB): it looks like random data and has a randomized size. This reduces metadata leakage from file format and length and allows cryptoblobs to be hidden among random data.
  4. Create steganographic (hidden, undetectable) user-driven filesystems inside container files and block devices. Unlike VeraCrypt and Shufflecake, tird containers do not contain headers; the user specifies the data locations inside the container and is responsible for keeping those locations separate. Any random-looking region of a file or block device may be used as a container.
  5. Prevent fast access to decrypted data using time-lock encryption.

tird is designed to resist coercive key-disclosure attacks (rubber-hose cryptanalysis) and offers built-in plausible deniability β€” even when encrypted files are stored outside containers.

Warning

Before using tird, please read the "Warnings" section. Security depends not only on the tool but on your actions: secure key storage, operating in a safe environment, and avoiding debug mode with real data.

πŸ”œ Format stabilization and a formal specification are planned for v1.0.0.

Goals

  • πŸ›‘οΈ File protection: Ensure protection of individual files, including:
    • Symmetric authenticated encryption.
    • Minimizing metadata leakage.
    • Hiding encrypted data.
    • Resisting coercive attacks.
  • ⏳ Stable format: Ensure a stable encrypted-data format with no cryptographic agility for long-term storage.
  • βšͺ Simplicity: Ensure simplicity and avoid feature creep; refuse to implement features not directly related to the primary security goals.

Features

  • PURB-format encrypted blobs: randomized size and uniformly random contents; metadata-limited (only total size leaks β€” no headers, types, or plaintext hints).
  • Padded & encrypted comments: hide metadata; no plaintext hints about content.
  • Hidden data embedding (optional): conceal cryptoblobs inside random/encrypted containers for plausible deniability.
  • Time-lock encryption (optional): slow offline PoW-based key derivation to delay decryption (anti-coercion).
  • Fully committing ChaCha20-BLAKE2b AEAD: secure authenticated encryption.
  • Strong key stretching: Argon2id (libsodium "sensitive" profile) β€” 1 GiB memory, 1 lane, 4 passes (default and minimum).
  • Arbitrary key material: derive keys from passphrases, files, block devices, or directories β€” order does not matter.
  • Prompt-based CLI: intuitive and interactive, no flags to memorize.
  • [TODO] Stable, documented format: planned for long-term archival and interoperability.

Usage

You don't need to memorize command-line options to use tird. This tool features a prompt-based CLI: simply start it, select a menu option, and answer the questions that will follow.

$ tird

                       MENU
    β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    0. Exit              1. Info & Warnings
    2. Encrypt           3. Decrypt
    4. Embed             5. Extract
    6. Encrypt & Embed   7. Extract & Decrypt
    8. Create w/ Random  9. Overwrite w/ Random
    β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
A0. Select an option [0-9]:

Input Options

There are 4 groups of input options: A (Action), D (Data), K (Keys), P (Proceed). They are numbered for ease of description.

+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| A0. Select an option | A. Select an action    |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| D1. Input file path  |                        |
| D2. Comments         | D. Enter data,         |
| D3. Output file path |    data location,      |
| D4. Output file size |    data size           |
| D5. Start position   |                        |
| D6. End position     |                        |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| K1. Keyfile path     | K. Enter values        |
| K2. Passphrase       |    related to          |
| K3. Time cost        |    key derivation      |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| P0. Proceed?         | P. Confirm to continue |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+

A detailed description of these options with examples can be found here.

Payload

The payload that will be encrypted during cryptoblob creation consists of:

  • Contents of one file (optional): A regular file or a block device (entire disk/partition). If omitted, an empty file payload is encrypted.
  • Comments (optional): Arbitrary UTF‑8 string, up to 1 KiB. By default the input file name is used. Decrypted comments are shown at decryption.

Specifying the payload in the UI looks as follows:

D1. File to encrypt (opt): list.txt
    I: path: 'list.txt'; size: 6,493 B (6.3 KiB)
D2. Comments (default='list.txt'): Epstein client list, txt
    I: comments will be shown as ['Epstein client list, txt']

Input Keying Material

tird provides the option to use the contents of keyfiles and passphrase to derive one-time keys.

  • Keyfiles (optional): Zero, one, or multiple keyfile paths; order of inputs does not matter. A keyfile path may be:
    • A regular file. The contents of the keyfile will be hashed, and its digest will be used for further key stretching and key derivation.
    • A block device. Handled the same as a regular keyfile: contents will be hashed.
    • A directory. All files within the directory will be hashed and used as keyfiles.
  • Passphrase (optional): Up to 2048 bytes (after NFC normalization); may be omitted.

Specifying IKM in the UI looks as follows:

K1. Keyfile path (optional): foo
    I: path: 'foo'; size: 1 B
    I: reading and hashing contents of 'foo'
    I: keyfile accepted
K1. Keyfile path (optional):
K2. Passphrase (optional):
K2. Confirm passphrase:
    I: passphrase accepted

Encrypted Data Format

256 shades of grey

Data encrypted with tird cannot be distinguished from random data without knowledge of the keys. It also does not contain identifiable headers. tird produces cryptoblobs that contain randomized padding with uniform random data (PURBs). This minimizes metadata leaks from the file format and makes it possible to hide cryptoblobs among other random data.

The cryptoblob scheme:

+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| CSPRNG output:                                         |
|     Salt for key stretching used with Argon2 (16 B)    |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| ChaCha20 output:                                       |
|     Ecrypted pad_ikm (8 B)                             |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| CSPRNG/BLAKE2 output:                                  |
|     Randomized padding (0-25% of the unpadded size)    |
|     + MAC tag (32 B)                                   |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| ChaCha20/BLAKE2 output:                                |
|     Encrypted payload file contents + MAC tags (0+ B)  |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| ChaCha20/BLAKE2 output:                                |
|     Encrypted padded comments (1 KiB) + MAC tag (32 B) |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+
| CSPRNG output:                                         |
|     Salt for prehashing IKM used with BLAKE2 (16 B)    |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+

For more details, refer to the specification.

Low Observability and Minimizing Metadata

While the content of an encrypted message is protected, its size, its provenance, its destination… are not. Data is hidden, metadata is shown.

β€” Loup Vaillant


Vs.
  • PURB format:
    • Encrypted files look like random data.
    • Encrypted files have a randomized size: do not reveal the payload size.
  • Comments are constant-padded, no reveal its size or existence.
  • Do not prove that the entered keys are incorrect.
  • Prompt-based CLI: no leakage of used options through shell history.
  • The output file path is user-defined and is not related to the input file path by default.
  • Optional: hiding encrypted data in containers.

Hidden File System and Container Format

tird employs a technique that is described as follows:

Concealing data within encrypted data or within random data. The message to conceal is encrypted, then used to overwrite part of a much larger block of encrypted data or a block of random data (an unbreakable cipher like the one-time pad generates ciphertexts that look perfectly random without the private key).

You can encrypt files and embed cryptoblobs into containers starting at arbitrary positions. After writing the cryptoblob, you will need to remember its location in the container (the starting and ending positions), which will be used later to extract the cryptoblobs. In this way, you can create a hidden, headerless, user-driven file system inside a container:

  • It is hidden because it is impossible to distinguish between random container data and cryptoblob data, as well as to determine the location of written cryptoblobs without knowing the positions and keys.
  • It is headerless because containers do not contain any headers; all data about cryptoblob locations must be stored separately by the user.
  • The starting position of the cryptoblob in the container is user-defined, and the user must store both the starting and ending positions separately from the container. This is why it is called a user-driven file system.

Any file, disk, or partition larger than the minimum cryptoblob size (831 B) can be a valid container. Cryptoblobs can be embedded into any area.

Examples of Valid Containers Include:

  1. Specially generated files with random data.
  2. Disk areas containing random data. For example, you can overwrite a disk with random data, format it in FAT32 or exFAT, and use a large portion of the disk, leaving a few dozen MB from the beginning. The disk will appear empty unless you add some files to it.
  3. LUKS encrypted volumes.
  4. VeraCrypt containers, even those that already contain hidden volumes.

Example of Container Structure:

+β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+ <β€” Position 0 of the container
|         |             |
|         | Random data |
|         |             |
|         +β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+ <β€” Cryptoblob1 start position
| Header- |             |
| less    | Cryptoblob1 |
|         |             |
| Layer   +β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+ <β€” Cryptoblob1 end position
|         | Random data |
| Cake    +β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+ <β€” Cryptoblob2 start position
|         |             |
|         | Cryptoblob2 |
|         |             |
|         +β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+ <β€” Cryptoblob2 end position
|         | Random data |
+β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+

Visualization of Embedding

The next image visualizes how hard it is to distinguish one random data entry from another and the process of embedding cryptoblobs in a container.

Β Show Images

Empty container with random data: Container

One cryptoblob embedded in the container: Embedded1

Two cryptoblobs embedded in the container: Embedded2

Three cryptoblobs embedded in the container: Embedded3

Animation: visualization of embedding: GIF: visualization of embedding

Storing and Carrying Concealed Encrypted Data

Please look at the following screenshot.

Screenshot

It looks like this 16 GB volume contains only one 8.7 MiB file. Is it really true? Maybe yes, maybe no.

The file system tells us that there is only one file here. But is there really only one file on the volume? We cannot determine this using the file system. In fact, data may be located outside the file system and be undetectable by file system tools. The 15.2 GiB of space marked as free may be occupied by a hidden file system. This "free" space may be taken up by hidden encrypted data.

Can we disprove the existence of this data? Yes, for example, by examining the entropy level of this free space using binwalk. Low entropy indicates a likely absence of hidden data. High entropy does not, by itself, prove the presence of encrypted hidden data. Areas with high entropy can be either just residual data or hidden encrypted data.

If you are interested in hiding data outside the visible file system, then tird is at your service to provide an Invisibility Cloak for your files.

Time-Lock Encryption

TLE image

Time-lock encryption (TLE) can be used to prevent an adversary from quickly accessing plaintexts in the event of an IKM compromise (in case of user coercion, for example). In our implementation, it is actually a PoW-based time-lock key derivation. The "Time cost" input option specifies the number of Argon2 passes. If you specify a sufficiently high number of passes, it will take a significant amount of time to perform them. However, an attacker will require the same amount of time when using similar hardware. The execution of Argon2 cannot be accelerated through parallelization, so it is expected that the time spent by an attacker will be approximately the same as that spent by the defender.

This TLE implementation works offline, unlike tlock.

Set the desired "Time cost" value:

K3. Time cost (default=4): 1000000
    I: time cost: 1,000,000
    W: decryption will require the same "Time cost" value!

Plausible TLE: The adversary does not know the actual value of the time cost, so you can plausibly misrepresent the number of passes. The adversary cannot refute your claim until they attempt to decrypt the cryptoblob using the specified time cost value.

Debug Mode

Warning

Debug mode is not intended for use in production!

Start tird with the --unsafe-debug option to look under the hood while the program is running.

Enabling debug mode additionally shows:

  • File operations:
    • Opening and closing of file descriptors.
    • Real paths to opened files.
    • Movement of file pointers.
  • Byte strings related to cryptographic operations: salts, passphrases, digests, keys, nonces, and tags.
  • Some other information, including various sizes.

Tradeoffs and Limitations

  • tird does not support:
    • Public-key cryptography.
    • File compression.
    • ASCII armored output.
    • Reed–Solomon error correction.
    • Splitting the output into chunks.
    • Use of standard streams for processing files (not intended for automated scripts).
    • Low-level block device reading and writing on MS Windows. As a result, these devices cannot be used as keyfiles, cannot be overwritten, and cannot be encrypted or embedded.
  • tird does not provide:
    • A graphical user interface.
    • A password generator.
  • tird cannot handle (encrypt/embed) more than one file in one pass. Encryption of directories and multiple files is not supported.
  • tird does not fake file access, modification, and creation timestamps (atime, mtime, ctime).
  • tird's encryption speed is not very high (up to 420 MiB/s in my tests).

Warnings

Crypto can help, but it won’t save you from misuse, vulnerabilities, social engineering, or physical threats.

β€” Loup Vaillant

DANGER MINES

  • ⚠️ The author does not have a background in cryptography.
  • ⚠️ The code has no automated test coverage.
  • ⚠️ tird has not been independently security audited by humans.
  • ⚠️ tird is ineffective in a compromised environment; executing it in such cases may cause disastrous data leaks.
  • ⚠️ tird is unlikely to be effective when used with short and predictable keys.
  • ⚠️ tird does not erase its sensitive data from memory after use.
  • ⚠️ Sensitive data may leak into swap space.
  • ⚠️ tird does not sort digests of keyfiles and passphrases in constant-time.
  • ⚠️ Overwriting file contents does not guarantee secure destruction of data on the media.
  • ⚠️ You cannot prove to an adversary that your random data does not contain encrypted information.
  • ⚠️ tird protects data, not the user; it cannot prevent torture if you are under suspicion.
  • ⚠️ Key derivation consumes 1 GiB RAM, which may lead to performance issues or crashes on low-memory systems.
  • ⚠️ Integrity/authenticity over availability β€” altering even a single byte of a cryptoblob prevents decryption.
  • ⚠️ Development is not complete, and there may be backward compatibility issues.

LLM reports

Requirements

  • Python >= 3.9.2
  • cryptography >= 2.1 (provides HKDF and a fast ChaCha20 implementation)
  • PyNaCl >= 1.2.0 (provides fast implementations of Argon2 and BLAKE2)
  • colorama >= 0.4.6 (Windows-specific)

TODO

Write or improve the documentation:

  • Features
  • User Guide
  • Specification
  • Design Rationale

Feedback

Please feel free to ask questions, leave feedback, or provide critiques in the Discussions section.