vollcrypt

Post-quantum cryptography workspace for messaging, files, WebAssembly, desktop, and database security.

View the Project on GitHub BeratVural/vollcrypt

Vollcrypt Files

High-performance, chunk-based End-to-End Encrypted (E2EE) file container engine for Node.js, WebAssembly, and Rust.


Vollcrypt Files is designed for local file encryption, cloud object storage, and secure shared-file access. It processes large files incrementally without loading them fully into memory, but it is not a real-time network, audio, or video streaming protocol.

This module provides high-performance chunked file encryption, cryptographic access control, and chunk integrity verification for large encrypted file containers.

License

This package is dual-licensed under:


Use Cases & Non-Goals

Use Cases

Vollcrypt Files is intended for:

Non-Goals

Vollcrypt Files does not provide real-time transport encryption for live network streams, audio calls, or video calls.

Those use cases require different security properties such as frame ordering, packet-loss tolerance, replay windows, rekeying, jitter handling, and low-latency authentication. They are intended to be handled by separate Vollcrypt protocol profiles such as:

Vollcrypt Files focuses on encrypted file containers for local storage, cloud storage, and secure file sharing.


Quick Start

Install Published Packages

Node.js native binding:

npm install @vollcrypt/files-node

Browser WebAssembly binding:

npm install @vollcrypt/files-wasm

Node.js Asynchronous Pipelined File API (Zero-Copy)

import { 
  generateDek, 
  generateFileId, 
  encryptFilePipelinedAsync, 
  decryptFilePipelinedAsync 
} from "@vollcrypt/files-node";

const dek = generateDek();
const fileId = generateFileId();

// Asynchronously encrypt a file using 4 parallel thread workers
const header = await encryptFilePipelinedAsync(
  "./input.txt",
  "./input.enc",
  dek,
  fileId,
  65536, // 64 KB chunk size
  [],    // wraps
  0,     // mode (0 = Password)
  4,     // thread workers
  null   // optional signInfo
);

// Asynchronously decrypt the file
await decryptFilePipelinedAsync(
  "./input.enc",
  "./input.dec",
  dek,
  4      // thread workers
);

WebAssembly (Browser) Integration

import init, { generateDek, generateFileId } from "@vollcrypt/files-wasm";

async function run() {
  await init();
  
  const dek = generateDek();
  const fileId = generateFileId();
  console.log("DEK generated:", dek);
}
run();

Architecture and File Container Design

Vollcrypt Files operates on a chunk-by-chunk file container model. The format is optimized for large local files, cloud-stored encrypted objects, random-access reads, and secure shared-file opening.

Container Block Layout

Below is the block layout visualizing the relationship between the File Header, chunk envelopes, the Merkle Tree, and out-of-order seekability:

graph TD
    classDef file fill:#eee,stroke:#333,stroke-width:1px;
    classDef chunk fill:#df5c3f,stroke:#333,stroke-width:1px,color:#fff;
    classDef node fill:#99c2ff,stroke:#333,stroke-width:1px;
    classDef root fill:#4b0082,stroke:#333,stroke-width:1px,color:#fff;

    subgraph MerkleTree ["Merkle Tree Integrity Chain (SHA-256)"]
        Root["Merkle Root (Header offset 44)"]:::root
        H_12["Node H(1..2)"]:::node
        H_34["Node H(3..4)"]:::node
        Tag1["Leaf 1: LeafHashV1(Chunk 1)"]:::node
        Tag2["Leaf 2: LeafHashV1(Chunk 2)"]:::node
        Tag3["Leaf 3: LeafHashV1(Chunk 3)"]:::node
        Tag4["Leaf 4: LeafHashV1(Chunk 4)"]:::node
        
        Root --> H_12
        Root --> H_34
        H_12 --> Tag1
        H_12 --> Tag2
        H_34 --> Tag3
        H_34 --> Tag4
    end

    subgraph FileStorage ["Encrypted Chunk Envelopes on Disk"]
        Header["Header (VOLLVALT Magic, DEK wraps, Merkle Root)"]:::file
        Chunk1["Chunk 1 Envelope (Index 0, IV1, Ciphertext1, Auth Tag 1)"]:::chunk
        Chunk2["Chunk 2 Envelope (Index 1, IV2, Ciphertext2, Auth Tag 2)"]:::chunk
        Chunk3["Chunk 3 Envelope (Index 2, IV3, Ciphertext3, Auth Tag 3)"]:::chunk
        Chunk4["Chunk 4 Envelope (Index 3, IV4, Ciphertext4, Auth Tag 4)"]:::chunk
    end

    Tag1 -.- Chunk1
    Tag2 -.- Chunk2
    Tag3 -.- Chunk3
    Tag4 -.- Chunk4

Visual Layout Diagram

+-----------------------------------------------------------+
|                      FILE CONTAINER                       |
+-----------------------------------------------------------+
| Header:                                                   |
|   - Magic Bytes ("VOLLVALT")                              |
|   - Version & Container Flags                             |
|   - File ID & Merkle Root                                 |
|   - Wrap Table & Extension Table                          |
|   - Signature (Optional, v2 only)                         |
+-----------------------------------------------------------+
| Chunk Envelopes:                                          |
|   +-----------------------------------------------------+ |
|   | Chunk 1: Index (4B) | IV (12B) | Cipher | Tag (16B) | |
|   +-----------------------------------------------------+ |
|   | Chunk 2: Index (4B) | IV (12B) | Cipher | Tag (16B) | |
|   +-----------------------------------------------------+ |
|   | ...                                                 | |
|   +-----------------------------------------------------+ |
+-----------------------------------------------------------+
|                  Merkle Root in Header                    |
|                            /\                             |
|                           /  \                            |
|                          /    \                           |
|                         /      \                          |
|                        /\      /\                         |
|                       /  \    /  \                        |
|                      /    \  /    \                       |
|                   Leaf 1 Leaf 2 Leaf 3 Leaf 4             |
+-----------------------------------------------------------+
|  Leaf 1: LeafHashV1(Chunk 1)                              |
|  LeafHashV1 = SHA-256("vollcrypt-file-merkle-leaf-v1" ||  |
|                file_id || index || len || IV1 || Tag1)    |
+-----------------------------------------------------------+

Key Capabilities

1. Multi-Mode Key Wrapping

Vollcrypt Files supports multiple ways to wrap and protect the file-specific Data Encryption Key (DEK):

[!NOTE] New containers SHOULD use Argon2id. PBKDF2-based wrapping SHOULD only be used when compatibility with constrained or legacy environments is required.

2. Chunked File Container Engine

[!NOTE] File Container Write Model Vollcrypt Files stores the Merkle Root in the file header. During encryption, implementations may either:

  1. write a placeholder header, encrypt chunks sequentially, compute the Merkle Root, and rewrite the header on seekable outputs such as local files; or
  2. build the encrypted container in a temporary file and write the final header once the Merkle Root is known.

This design is intentional for encrypted file containers. Vollcrypt Files is not intended to be used as a live real-time transport stream protocol.

3. Signed, Hash-Linked Group Manifest

To support multi-member groups:

graph LR
    classDef gen fill:#4b0082,stroke:#333,stroke-width:1px,color:#fff;
    classDef op fill:#99c2ff,stroke:#333,stroke-width:1px;

    Genesis["Genesis Block<br/>(prev_hash: [0;32])<br/>Signed by Founder"]:::gen
    Add["AddMember Block<br/>(prev_hash: H(Genesis))<br/>Signed by Admin"]:::op
    Remove["RemoveMember Block<br/>(prev_hash: H(Add))<br/>Signed by Admin"]:::op
    
    Genesis --> Add
    Add --> Remove
Revocation & Manifest Limits
Revocation Model

Vollcrypt group revocation has multiple modes:

  1. Lazy Revocation: Removed members stop receiving future group keys. Historical files may remain decryptable if the removed member previously cached the required keys.
  2. Forward-Only Revocation: New files are encrypted under a new group key epoch. Old files are not automatically re-encrypted.
  3. Strict Revocation: Existing files are rewrapped or re-encrypted under a new key epoch. This is more expensive but prevents removed members from opening files.
Manifest Scaling

For large groups, manifest size and verification cost grow with the number of operations and members. Applications targeting very large groups should consider checkpointing, manifest compaction, or epoch snapshots.

4. Merkle Tree Integrity Verification

5. Bounded-Memory Parallelism

To maximize CPU and NVMe SSD throughput, Vollcrypt Files implements bounded-memory, parallel pipelined file encryption and decryption:

6. Sovereign Sealing & Crypto-Shredding

7. Shield Integrity Policy


Technical Specifications

Cryptographic Algorithms

File Header Binary Layout

The header contains critical file metadata and the wraps protecting the DEK. All multibyte integers are written in Big-Endian (BE) format.

Implementations MUST NOT assume a fixed small header size. The header is length-prefixed and may grow with the number of recipients, group metadata, and extensions.

Offset Length Type Description
0 8 Bytes Magic Bytes (VOLLVALT)
8 1 u8 Format Version (1 = Unsigned, 2 = Signed Classical, 3 = Signed Post-Quantum Hybrid)
9 1 u8 Container Mode (e.g. 0 = Password, 1 = Recipient, 2 = Group)
10 1 u8 Cipher Suite ID
11 16 Bytes File ID
27 4 u32 BE Chunk Size (Max 16 MB)
31 8 u64 BE Plaintext Size
39 32 Bytes Merkle Root
71 1 u8 Wrap Count
72 1 u8 Hash Algorithm (0 = SHA-256, 1 = BLAKE3)
73 3 Bytes Reserved
76 4 u32 BE Variable Length (Length of wrap entries table)
80 Var Structs Wrap Table (concatenated WrapEntry records)
80 + Var 4 u32 BE Metadata Length (v2/v3 only)
84 + Var Var Struct Signed Metadata (v2/v3 only)
84 + Var + MetVar Var Signature Signature Table (v2: 64B Ed25519, v3: Ed25519 + ML-DSA-65 Hybrid Signature)

Container Flags

The container mode determines how the file is accessed (Password, Recipient, or Group). Supported access methods are determined by the list of WrapEntry records.

Variable Length

Variable Length is the total byte length of all concatenated WrapEntry records. Parsers MUST reject headers where the sum of parsed wrap entry sizes does not exactly equal Variable Length.

Wrap Entry Binary Layouts

Each wrap entry starts with a 1-byte wrap_type and a 2-byte BE payload_len. payload_len excludes the 3-byte entry prefix (wrap_type || payload_len). Therefore, the total serialized size of a wrap entry is 3 + payload_len.

Type 0: Password PBKDF2 (Payload Length = 60)

Type 1: Password Argon2id (Payload Length = 68)

Type 3: Group Wrap (Payload Length = 60)

Type 4: Hybrid KEM (Payload Length = 1180)

Type 5: Threshold SSS Wrap (Payload Length = 58)

Reconstructing the 32-byte Threshold Master Secret (TMS) requires at least t valid shares. The KEK is derived via HKDF-SHA256:

Shares are exported externally as portable strings in the format vcs_<base64url(payload)> (without padding), where the 59-byte payload consists of:

For direct recipient wrapping, this field represents the recipient key version. For group-mediated recipient wrapping, a separate group-mediated wrap profile SHOULD be used. (Type 2 is unsupported/legacy).

Canonical Encoding and Parser Rules

Implementations MUST:

A container with zero wraps may be parsed for inspection, but it is not decryptable through normal APIs. Normal encrypted containers MUST contain at least one valid WrapEntry. Zero-wrap containers MAY be used to represent key-shredded files whose ciphertext remains stored but whose DEK can no longer be recovered.

Chunk Envelope Binary Layout

Each encrypted chunk is stored as a sequential binary chunk envelope:

Offset Length Type Description
0 4 u32 BE Chunk Index (0-based)
4 12 Bytes IV / Nonce (12 bytes)
16 Var Bytes Ciphertext (Plaintext size)
16 + Var 16 Bytes AES-256-GCM Authentication Tag

Technical Foundations

Cryptographic Security Policies

  1. Memory Protection: All sensitive keying materials (including Key Encryption Keys, ephemeral Diffie-Hellman secrets, and recipient secret keys) implement the Zeroize and ZeroizeOnDrop traits to ensure they are scrubbed from memory immediately after use.
  2. No Unsafe Code: The Rust cryptographic core is implemented without unsafe code. Node.js and WebAssembly bindings are thin wrappers around the safe Rust core.

Chunk Key and IV Derivation

For chunk i, implementations derive separate AEAD key and IV material using domain-separated HKDF labels.

chunk_key_i = HKDF-SHA256(
  ikm = DEK,
  salt = file_id,
  info = "vollcrypt-file-chunk-key-v1" || chunk_index_u32_be,
  length = 32
)

chunk_iv_i = HKDF-SHA256(
  ikm = DEK,
  salt = file_id,
  info = "vollcrypt-file-chunk-iv-v1" || chunk_index_u32_be,
  length = 12
)

The same (chunk_key, chunk_iv) pair MUST never be reused for different plaintext chunks.

Hybrid KEM KEK Derivation

hybrid_secret = x25519_shared_secret || ml_kem_shared_secret

KEK = HKDF-SHA256(
  ikm = hybrid_secret,
  salt = file_id,
  info =
    "vollcrypt-file-hybrid-kem-v1" ||
    recipient_id[16] ||
    recipient_key_version_u32_be ||
    kem_suite_id ||
    cipher_suite_id,
  length = 32
)

Chunk AEAD Associated Data

Each AES-256-GCM chunk encryption authenticates the following associated data:

AAD_FileChunk_V1 =
  "vollcrypt-file-chunk-aad-v1" ||
  header_hash[32] ||
  file_id[16] ||
  chunk_index_u32_be ||
  chunk_size_u32_be ||
  plaintext_size_u64_be ||
  chunk_plaintext_len_u32_be

Implementations MUST reject chunks if AEAD authentication fails. The header hash is derived as:

header_hash = SHA-256(canonical_header_without_mutable_fields)

Merkle Tree Integrity Verification

To prevent malicious storage servers from replacing, reordering, or swapping chunk envelopes, Vollcrypt Files constructs a Merkle Tree over canonical chunk leaf hashes.

For format version 1, each leaf is computed using SHA-256 by default:

LeafHashV1_Sha256 =
SHA-256(
  "vollcrypt-file-merkle-leaf-v1" ||
  file_id[16] ||
  chunk_index_u32_be ||
  chunk_plaintext_len_u32_be ||
  iv[12] ||
  auth_tag[16]
)

For the optional BLAKE3 high-performance profile, LeafHashV1 and internal Merkle tree nodes are computed using BLAKE3:

LeafHashV1_Blake3 =
BLAKE3(
  "vollcrypt-file-merkle-leaf-v1" ||
  file_id[16] ||
  chunk_index_u32_be ||
  chunk_plaintext_len_u32_be ||
  iv[12] ||
  auth_tag[16]
)

The ciphertext payload is intentionally excluded from the Merkle leaf because AES-256-GCM already authenticates the ciphertext through the authentication tag.

Memory Zeroization and JS/WASM Runtimes

Rust-owned secret material is zeroized using Zeroize and ZeroizeOnDrop.

When using Node.js or WebAssembly bindings, JavaScript runtimes may copy secrets in ways that cannot be fully zeroized by the native library. Callers SHOULD avoid immutable strings for passwords and SHOULD clear user-owned Uint8Array / Buffer values after use.


Programmatic Integration Examples

Out-of-Order Seek & Verify

This example uses the published low-level exports from @vollcrypt/files-node. The readHeaderPrefix, FileHandle, and MerkleProofProvider helpers are application-owned I/O abstractions.

import {
  HeaderClass,
  decryptChunk,
  verifyMerkleProof,
  chunkLeafHash
} from '@vollcrypt/files-node';

async function seekAndDecryptChunk(
  file: FileHandle,
  targetByteOffset: number,
  dek: Uint8Array,
  proofProvider: MerkleProofProvider
): Promise<Buffer> {
  const headerPrefix = await readHeaderPrefix(file, 16 * 1024 * 1024);
  const { header, headerLen } = HeaderClass.parse(headerPrefix);

  const chunkSize = header.chunkSize;
  const plaintextLength = header.plaintextSize;
  const fileId = header.fileId;
  const merkleRoot = header.merkleRoot;

  const chunkIndex = Math.floor(targetByteOffset / chunkSize);
  const totalChunks = Math.ceil(plaintextLength / chunkSize);

  if (chunkIndex >= totalChunks) {
    throw new Error("Target offset exceeds file size");
  }

  const isLastChunk = chunkIndex === totalChunks - 1;
  const chunkPlaintextLen = isLastChunk
    ? (plaintextLength % chunkSize || chunkSize)
    : chunkSize;

  const envelopeSize = 32 + chunkPlaintextLen;
  const targetEnvelopeDiskPos = headerLen + chunkIndex * (32 + chunkSize);
  const envelopeBuffer = Buffer.alloc(envelopeSize);
  await file.read(envelopeBuffer, 0, envelopeSize, targetEnvelopeDiskPos);

  const parsedIndex = envelopeBuffer.readUInt32BE(0);
  if (parsedIndex !== chunkIndex) {
    throw new Error(`Chunk index mismatch: expected ${chunkIndex}, got ${parsedIndex}`);
  }

  const envelope = {
    chunkIndex: parsedIndex,
    iv: envelopeBuffer.subarray(4, 16),
    ciphertext: envelopeBuffer.subarray(16, 16 + chunkPlaintextLen),
    tag: envelopeBuffer.subarray(16 + chunkPlaintextLen, envelopeSize)
  };

  const leafHash = chunkLeafHash(envelope);
  const proof = await proofProvider.getProof(chunkIndex);

  if (!verifyMerkleProof(leafHash, chunkIndex, totalChunks, proof, merkleRoot)) {
    throw new Error(`Security exception: chunk ${chunkIndex} failed Merkle validation`);
  }

  return decryptChunk(dek, fileId, chunkIndex, envelope);
}

Advanced API Reference (Bindings)

Sovereign Sealing & Shield Policy API Examples

Sealing a Container (Node.js)

const { sealContainer } = require("@vollcrypt/files-node");

// Irreversibly seal the container and sign the sealed marker with the owner's signing key
await sealContainer("container.dat", {
  mode: "seal",
  reason: "GDPR right to be forgotten request",
  signInfo: {
    kind: "plain",
    signerPk: ownerPublicKey,
    signerSk: ownerPrivateKey,
    keyLogId: keyLogId,
    timestamp: Math.floor(Date.now() / 1000)
  }
});

Verifying a Container with Shield Integrity Policy

const { verifyContainer, decryptFilePipelinedAsync } = require("@vollcrypt/files-node");

const policy = {
  releaseMode: "verified", // "verified" (double-pass fail-closed) or "streaming" (fail mid-stream)
  signature: "required",  // "required" (must have valid owner signature) or "optional"
  rollbackPin: 5,         // enforce manifest epoch >= 5
  founderAnchor: true,    // verify founder anchor matches genesis
  onTamper: "abort"       // "abort", "report", or "recover"
};

// Check integrity upfront
const report = verifyContainer("container.dat", policy);
if (report === "ContainerSealed") {
  console.log("Container is sealed.");
} else if (report !== "Success") {
  console.error("Integrity check failed: " + report);
} else {
  // Safe to decrypt under policy
  await decryptFilePipelinedAsync("container.dat", "plaintext.txt", dek, 4, policy);
}

Published Packages


Building and Testing

Build Node.js Crate

cd vollcrypt-files/node
npm install
npm run build:debug
npm test

Build WebAssembly Crate

By default, the WebAssembly module compiles with 128-bit SIMD acceleration enabled (target-feature=+simd128). To compile:

cd vollcrypt-files/wasm
npm install
npm run build
npm test

To compile a portable fallback build without SIMD features, override the target flags:

RUSTFLAGS="" npm run build

Performance & Optimizations

Vollcrypt Files has undergone targeted performance optimizations to achieve peak single-core throughput and resolve encryption/decryption asymmetry:

Benchmark Results (AMD Ryzen 5 7500F @ 3.70 GHz)

Device Profile for Tests:

Pipelined Performance Metrics Suite

| Metric | Balanced Profile (256MB) | Max Profile (1GB) | Detail | | — | — | — | — | | Throughput | 3.56 GB/s | 3.31 GB/s | Aggregate gigabytes per second | | Cycles/Byte | 0.97 | 1.04 | CPU clock cycles per byte encrypted | | Instructions/Byte | 1.21 | 1.30 | CPU instructions executed per byte | | Allocations/Chunk | 0 | 0 | Number of heap allocations per chunk | | Bytes Copied/Byte Encrypted | 1.0 | 1.0 | Total buffer copy amplification ratio | | Worker Idle Time | 56.5% | 81.3% | Time workers spent waiting for queue | | Queue Wait Time | 11.3% | 15.0% | Average time chunks spent in queue | | I/O Wait Time | 45.2% | 65.1% | Average time spent in disk/stream I/O | | Merkle Time / Total | 0.01% | 0.00% | Percentage of time spent in Merkle tree | | HKDF Time / Total | 0.02% | 0.00% | Percentage of time spent in HKDF subkeys | | AEAD Time / Total | 43.44% | 18.65% | Percentage of time spent in AEAD crypto | | Energy Estimate | 21.05 J/GB | 22.65 J/GB | Estimated energy consumption per GB | | Time to First Verified Plaintext | 0.172 ms | 1.668 ms | Latency to verify and decrypt chunk 0 |

Chunk Latency & Throughput (Single-Core)

| Operation | Input Size | Latency (median) | Latency (p99) | Throughput | | — | — | — | — | — | | encrypt_chunk | 4 KB | 4.30 μs | 28.50 μs | 908.43 MB/s | | decrypt_chunk | 4 KB | 3.60 μs | 4.40 μs | 1085.07 MB/s | | encrypt_chunk | 64 KB | 36.90 μs | 66.80 μs | 1693.77 MB/s | | decrypt_chunk | 64 KB | 37.10 μs | 56.60 μs | 1684.64 MB/s | | encrypt_chunk | 1 MB | 691.60 μs | 778.90 μs | 1445.92 MB/s | | decrypt_chunk | 1 MB | 675.50 μs | 723.30 μs | 1480.38 MB/s | | encrypt_chunk | 4 MB | 2586.30 μs | 2970.20 μs | 1546.61 MB/s | | decrypt_chunk | 4 MB | 2641.20 μs | 2651.90 μs | 1514.46 MB/s | | encrypt_chunk | 16 MB | 10425.80 μs | 11724.60 μs | 1534.65 MB/s | | decrypt_chunk | 16 MB | 10564.10 μs | 10630.60 μs | 1514.56 MB/s |

Competitor Comparison (1 GB Single-Threaded & Multi-Threaded)

All baseline timings measured dynamically on the same AMD Ryzen 5 7500F test system:

Benchmark Results (Intel Core i5-12450H)

Device Profile for Tests:

Pipelined Performance Metrics Suite

| Metric | Balanced Profile (256MB, 1MB chunk) | Max Profile (1GB, 8MB chunk) | Detail | | — | — | — | — | | Throughput | 0.71 GB/s | 0.74 GB/s | Aggregate gigabytes per second | | Cycles/Byte | 0.55 | 0.53 | CPU clock cycles per byte encrypted | | Instructions/Byte | 0.69 | 0.66 | CPU instructions executed per byte | | Allocations/Chunk | 0 | 0 | Number of heap allocations per chunk | | Bytes Copied/Byte Encrypted | 1.0 | 1.0 | Total buffer copy amplification ratio | | Cache Misses/GB | N/A | N/A | Modeled cache misses per gigabyte | | Branch Misses/GB | N/A | N/A | Modeled branch mispredictions per gigabyte | | Worker Idle Time | 86.4% | 92.8% | Time workers spent waiting for queue | | Queue Wait Time | 15.0% | 15.0% | Average time chunks spent in queue | | I/O Wait Time | 69.2% | 74.3% | Average time spent in disk/stream I/O | | Merkle Time / Total | 0.20% | 0.01% | Percentage of time spent in Merkle tree | | HKDF Time / Total | 0.57% | 0.04% | Percentage of time spent in HKDF subkeys | | AEAD Time / Total | 12.99% | 7.14% | Percentage of time spent in AEAD crypto | | Energy Estimate | 134.21 J/GB | 128.59 J/GB | Estimated energy consumption per GB | | Time to First Verified Plaintext | 0.682 ms | 4.769 ms | Latency to verify and decrypt chunk 0 |

Chunk Latency & Throughput (Single-Core)

| Operation | Input Size | Latency (median) | Latency (p99) | Throughput | | — | — | — | — | — | | encrypt_chunk | 4 KB | 72.37 μs | 90.15 μs | 53.98 MB/s | | decrypt_chunk | 4 KB | 80.88 μs | 336.33 μs | 48.30 MB/s | | encrypt_chunk | 64 KB | 182.53 μs | 209.93 μs | 342.41 MB/s | | decrypt_chunk | 64 KB | 168.51 μs | 376.97 μs | 370.89 MB/s | | encrypt_chunk | 1 MB | 1173.14 μs | 1754.10 μs | 852.42 MB/s | | decrypt_chunk | 1 MB | 1171.14 μs | 1198.10 μs | 853.87 MB/s | | encrypt_chunk | 4 MB | 4509.95 μs | 4652.09 μs | 886.93 MB/s | | decrypt_chunk | 4 MB | 4650.11 μs | 4795.83 μs | 860.19 MB/s | | encrypt_chunk | 16 MB | 17892.73 μs | 19608.63 μs | 894.22 MB/s | | decrypt_chunk | 16 MB | 18179.62 μs | 21220.74 μs | 880.11 MB/s |

Competitor Comparison (1 GB Single-Threaded)

All baseline timings measured dynamically on the same Intel Core i5-12450H test system:

Benchmark CLI

Vollcrypt Files includes a dedicated benchmark and resource monitoring harness binary named vollcrypt. You can use this CLI to run automated suites, sweep configurations, profile specific parameters, and inspect real-time CPU/RAM/Disk stats:

# Run the full automated suite (generates markdown files under reports/)
cargo run --release -p vollcrypt-files-bench --bin vollcrypt -- bench --suite auto

# Profile specific configurations with JSON output
cargo run --release -p vollcrypt-files-bench --bin vollcrypt -- bench --profile balanced --json

# Profile max configuration and compare against local OpenSSL/Age baselines
cargo run --release -p vollcrypt-files-bench --bin vollcrypt -- bench --profile max --compare

# Sweep chunk sizes (from 4 KB to 16 MB)
cargo run --release -p vollcrypt-files-bench --bin vollcrypt -- bench --sweep chunk-size

# Sweep worker threads to evaluate parallel scaling
cargo run --release -p vollcrypt-files-bench --bin vollcrypt -- bench --sweep workers

Test & Security Scorecard

The current test suite includes stress, fuzzing, tampering, replay, forgery-resistance, and safe-default policy tests.

ON THIS PAGE