ykcrypt

command module
v0.0.0-...-0f18e17 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 24, 2025 License: MIT Imports: 1 Imported by: 0

README

ykcrypt

Go Reference Go Report Card Go Version

ykcrypt is a small Go command-line tool that encrypts/decrypts files using a YubiKey PIV ECDH key agreement key as the hardware-root secret.

Features

  • 🔐 Hardware-backed encryption using YubiKey PIV slots
  • 👥 Multiple recipients - encrypt for multiple YubiKeys simultaneously
  • 🔑 Optional passphrase as second factor (Argon2id)
  • 🔄 Recipient management - add/remove recipients without re-encrypting
  • Streaming encryption - handles large files efficiently
  • 🛡️ Cipher choice - XChaCha20-Poly1305 (default) or AES-256-GCM
  • 💾 Atomic writes - prevents file corruption on failure
  • 📋 Clear error messages with troubleshooting hints

Security model (high-level)

  • Encryption uses ephemeral ECDH against the YubiKey slot public key:
    • Encryption can be done without the YubiKey if you have the exported recipient string (public key).
    • Decryption requires the YubiKey because the slot private key performs ECDH to recover the wrapping key.
  • Multiple recipients supported: Files can be encrypted for multiple recipients simultaneously (YKCRYPT2 format).
  • A random 32-byte file key encrypts the file content in streaming chunks (XChaCha20-Poly1305 or AES-256-GCM).
  • The file key is wrapped (ChaCha20-Poly1305) under a key derived from the ECDH shared secret via HKDF-SHA256.
  • Optional second factor: passphrase mixed in (Argon2id -> HMAC-SHA256) to require both YubiKey + passphrase for decryption.
  • Atomic writes: All output files are written atomically to prevent corruption.
  • Structured errors: Clear error messages with troubleshooting hints for common issues.

This is a reference implementation; for production use, review threat models, add recipient rotation, backups, recovery workflows, audits, etc.

Prerequisites

  • Go 1.22+ recommended (uses crypto/ecdh).
  • PC/SC stack installed and running (Windows: built-in; Linux: pcscd/pcsc-lite; macOS: built-in).
  • A YubiKey that supports the PIV applet.

Note: ykcrypt currently supports Windows only due to dependency on Windows Smart Card API (WinSCard) via piv-go library.

Build

Quick Build (Current Platform)
# PowerShell (Windows)
.\build.ps1

# Outputs to: bin/windows/amd64/ykcrypt.exe
Build with Version
.\build.ps1 -Version "1.2.0"
Build for All Windows Platforms
.\build.ps1 -Version "1.0.0" -Platforms "all"

# Creates:
#   bin/windows/amd64/ykcrypt.exe (with version info resource)
#   bin/windows/arm64/ykcrypt.exe
Build Options
  • -Version - Version string to embed (default: auto-detect from git tags or "dev")
  • -Platforms - Target platforms: "all", "windows/amd64", "windows/arm64", etc.
  • -Clean - Clean build artifacts before building
  • -SkipVersionInfo - Skip Windows version resource generation (faster builds)

The build script automatically embeds:

  • Version number
  • Git commit hash
  • Build timestamp (UTC)
  • Go version
  • Windows version resource (for AMD64 builds)
Manual Build
go mod tidy
go build -o ykcrypt.exe .

Usage

Provision a slot (generates EC key + stores a certificate containing the public key)
./ykcrypt init -slot 9d

This prints a recipient string of the form:

ykcrypt1:<slotHex>:<curveId>:<base64PublicKey>

Save it somewhere safe (it is not secret, but it identifies the recipient).

Export recipient string later
./ykcrypt export -slot 9d > recipient.txt

For everyday use, ykcrypt provides short commands that use sensible defaults (slot 9d, auto-detect recipient from YubiKey):

Quick encrypt:

# Encrypt file (creates secrets.txt.ykc)
./ykcrypt e secrets.txt

# Encrypt with custom output name
./ykcrypt e secrets.txt encrypted.ykc

# Encrypt and overwrite original file (replaces secrets.txt with encrypted version)
./ykcrypt e -F secrets.txt

Quick decrypt:

# Decrypt file (creates secrets.txt from secrets.txt.ykc)
./ykcrypt d secrets.txt.ykc

# Decrypt with custom output name
./ykcrypt d secrets.txt.ykc decrypted.txt

# Decrypt and overwrite original file (replaces encrypted file with decrypted version)
./ykcrypt d -F secrets.txt.ykc

You will be prompted for the PIV PIN, then touch the YubiKey when it blinks.

Full Commands (Advanced)

For more control, use the full encrypt and decrypt commands with explicit flags:

Encrypt:

RECIP="$(cat recipient.txt)"
./ykcrypt encrypt -recipient "$RECIP" -in secrets.txt -out secrets.txt.ykc

With a passphrase as a second factor:

./ykcrypt encrypt -recipient "$RECIP" -passphrase -in secrets.txt -out secrets.txt.ykc

Decrypt (requires YubiKey):

./ykcrypt decrypt -in secrets.txt.ykc -out secrets.txt

You will be prompted for the PIV PIN, and for the passphrase if the ciphertext indicates one is required.

Rewrap Command (Add/Remove Recipients)

The rewrap command allows you to add or remove recipients from an encrypted file without re-encrypting the entire payload:

Add a recipient:

# Add a new recipient to an existing encrypted file
./ykcrypt rewrap --add "ykcrypt1:9d:1:..." --in secrets.ykc --out secrets-shared.ykc

# Add multiple recipients
./ykcrypt rewrap --add "ykcrypt1:..." --add "ykcrypt1:..." --in secrets.ykc

# Add recipients from a file (one per line)
./ykcrypt rewrap --add-file recipients.txt --in secrets.ykc

Remove a recipient:

# Remove a recipient by slot key (hex)
./ykcrypt rewrap --remove 9d --in secrets.ykc --out secrets.ykc

You must have access to one of the current recipients' keys (your YubiKey must be able to decrypt the file) to perform rewrap operations.

Cipher Selection

You can choose between XChaCha20-Poly1305 (default) or AES-256-GCM:

# Encrypt using AES-256-GCM
./ykcrypt e --cipher aes secrets.txt

# Or with full command
./ykcrypt encrypt --cipher aes -in secrets.txt -out secrets.ykc

Operational notes

  • The init command defaults to the PIV management key value default. In real deployments you should change PIN/PUK/management key.
  • Slot policies are set to require PIN + touch on use (PINPolicyAlways, TouchPolicyAlways).
  • If you lose the YubiKey (and passphrase, if used), you lose access to the encrypted data.

File format

ykcrypt supports two file formats:

  • YKCRYPT1: Single recipient format (legacy, still fully supported)
  • YKCRYPT2: Multiple recipient format with metadata support

The ciphertext begins with a fixed header and then a sequence of (uint32 length, ciphertext bytes) chunks terminated by length 0. The header includes the ephemeral public key(s), salts, nonce prefix, and wrapped file key(s). The full header is used as AAD for chunk AEAD.

For detailed format specification, see FORMAT.md.

Troubleshooting

Common errors and solutions:

Error Cause Solution
security status not satisfied (6982) Touch timeout Touch YubiKey within 15 seconds after PIN entry
verification failed (63cx) Wrong PIN Re-enter PIN (x = retries remaining)
authentication blocked (6983) PIN blocked Use PUK to unblock via YubiKey Manager
data not found (6a82) Empty slot Run ykcrypt init first
no yubikey reader found No YubiKey Plug in YubiKey; on Linux run pcscd

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

  • piv-go - Go library for YubiKey PIV
  • age - Modern file encryption tool
  • sops - Secrets management with multiple backends

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Documentation

Overview

Copyright © 2025 Logicos Software

ykcrypt - YubiKey-based File Encryption Tool

This is the main entry point for the ykcrypt command-line tool. ykcrypt provides secure file encryption using YubiKey PIV ECDH key agreement, combining hardware security with modern cryptography.

Security Model:

  • Uses ECDH key agreement with YubiKey-stored private keys
  • Supports XChaCha20-Poly1305 and AES-256-GCM ciphers
  • Optional passphrase as second factor using Argon2id
  • Requires PIN and physical touch for decryption

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL