Command Palette

Search for a command to run...

encryptd

07.202607.2026Full Stack DeveloperLive Site
  • Rust 1.85+
  • TypeScript 5+
  • napi-rs
  • aes-gcm crate
  • PBKDF2-HMAC-SHA256
  • pnpm
  • Vitest
  • GitHub Actions
encryptd

Rust-powered AES-256-GCM environment file encryption as a native Node.js addon. CLI + library, zero dependencies, cross-platform.

Challenge

Managing .env files across environments (local, staging, production) and teams is a security risk. Committing plaintext secrets to git is dangerous. Existing solutions:

  • Require external services (AWS KMS, HashiCorp Vault, Doppler) adds infrastructure complexity
  • Use symmetric encryption in pure JS slower, no hardware acceleration, larger attack surface
  • Lack a simple CLI + library dual interface
  • Don't provide cross-platform native binaries out of the box

Goal: A zero-dependency, cross-platform, AES-256-GCM encrypted .env solution that works as both a CLI tool and a library, with native performance via Rust.

Interface screenshot
Project screenshot
Project screenshot

Solution

encryptd A Rust native addon (via napi-rs) that encrypts/decrypts .env files using AES-256-GCM with PBKDF2 key derivation. Published to GitHub Packages, installable via pnpm/npm.

How It Works

StepEncryption Process
1Generate random 16-byte salt
2PBKDF2-HMAC-SHA256 (100,000 iterations) derives 32-byte key
3Generate random 96-bit nonce
4AES-256-GCM encrypt → produces ciphertext + auth tag
5Hex-encode salt, nonce, ciphertext, auth tag → write as JSON
StepDecryption Process
1Parse JSON, hex-decode all fields
2PBKDF2 derives identical key from passphrase + salt
3AES-256-GCM decrypt (auth tag verified automatically)
4Output plaintext to stdout

Each encryption uses a fresh random nonce → same input produces different output every time (semantic security).

CLI Usage

# Encrypt .env → .env.enc
ENV_PASSPHRASE="your-secret" npx encryptd encrypt
 
# Decrypt .env.enc → stdout (pipe to file or eval)
ENV_PASSPHRASE="your-secret" npx encryptd decrypt
 
# Custom paths
ENV_PASSPHRASE="s3cr3t" npx encryptd encrypt .env.prod .env.prod.enc
ENV_PASSPHRASE="s3cr3t" npx encryptd decrypt .env.prod.enc

Library Usage

import { encrypt, decrypt } from '@vernonthedev/encryptd'
import { readFileSync, writeFileSync } from 'fs'
 
// Encrypt
const plaintext = readFileSync('.env', 'utf-8')
const encrypted = await encrypt(plaintext, process.env.ENV_PASSPHRASE!)
writeFileSync('.env.enc', encrypted)
 
// Decrypt
const encrypted = readFileSync('.env.enc', 'utf-8')
const plaintext = await decrypt(encrypted, process.env.ENV_PASSPHRASE!)
// Use plaintext...

Output Format (.env.enc)

{
  "salt": "a1b2c3d4e5f6...",
  "nonce": "f0e1d2c3b4a5...",
  "ciphertext": "9f8e7d6c5b4a...",
  "tag": "1a2b3c4d5e6f..."
}

All fields hex-encoded. Portable across platforms.

Tech Stack

LayerTechnology
Native CoreRust 1.85+, aes-gcm, pbkdf2, napi-rs
Bindingsnapi-rs (zero-copy FFI, TypeScript types auto-generated)
CLITypeScript, commander.js
Buildnapi build (cross-compiles 4 targets), tsc
TestVitest (unit + integration)
CI/CDGitHub Actions (build matrix: macOS ARM64/x64, Linux x64, Windows x64)
RegistryGitHub Packages (scoped @vernonthedev/encryptd)
Project screenshot
Project screenshot

Platform Support (Prebuilt Binaries)

TargetBinaryCI Runner
macOS ARM64 (Apple Silicon)encryptd-darwin-arm64.nodemacos-latest (M1)
macOS x64 (Intel)encryptd-darwin-x64.nodemacos-latest
Linux x64 GNUencryptd-linux-x64-gnu.nodeubuntu-latest
Windows x64 MSVCencryptd-win32-x64-msvc.nodewindows-latest

No Rust toolchain required for consumers pnpm add downloads the correct .node binary automatically.

Security Design

PropertyImplementation
AlgorithmAES-256-GCM (authenticated encryption)
Key DerivationPBKDF2-HMAC-SHA256, 100,000 iterations
Salt16 bytes, cryptographically random per encryption
Nonce96 bits, cryptographically random per encryption
Auth Tag128-bit, verified on decrypt (tamper-proof)
Memory SafetyRust no buffer overflows, use-after-free
DependenciesMinimal: aes-gcm, pbkdf2, napi-rs, serde

My Role

Solo Developer / Maintainer

  • Designed the encryption scheme (AES-256-GCM + PBKDF2 parameters)
  • Built the Rust native addon with napi-rs FFI boundaries, error handling, memory management
  • Implemented TypeScript bindings with full type safety (auto-generated .d.ts via napi-rs)
  • Created CLI with commander.js argument parsing, env var handling, stdin/stdout streaming
  • Configured GitHub Actions matrix build for 4 targets with artifact upload to GitHub Packages
  • Published to GitHub Packages with Changesets for versioning/changelog
  • Wrote comprehensive tests (Vitest) covering encrypt/decrypt roundtrips, wrong passphrase, corrupted files, CLI integration

Installation

pnpm add @vernonthedev/encryptd
# or
npm install @vernonthedev/encryptd

Requires @vernonthedev/encryptd scope access to GitHub Packages, or build from source.

Development

pnpm install
pnpm napi-build   # Compile Rust → native binaries (4 targets)
pnpm build        # Compile TypeScript
pnpm test         # Vitest unit + integration tests

GitHub

Zero-dep, native-speed .env encryption. Rust core, TypeScript API, works everywhere Node runs.

Command Palette

Search for a command to run...