Skip to main content

GUN-101

A simple, secure file encryption tool using AES-256-GCM and Argon2id.

CI PyPI version Python versions License: MIT OpenSSF Best Practices Security Policy

What problem does this solve?

If a laptop is lost, a cloud drive is breached, or a USB stick falls into the wrong hands, the files on it are exposed. GUN-101 protects files at rest: it encrypts them so that only someone with the correct password (and, optionally, a separate keyfile) can read them, and any tampering with an encrypted file is detected and rejected before it is opened.

Overview

GUN-101 encrypts files with authenticated encryption, providing confidentiality and integrity. It supports two modes:

  1. Password-only: Encryption key derived from password alone
  2. Password + keyfile: Two-factor protection requiring both password and a separate keyfile

The design prioritizes correctness and transparency over complexity or marketing claims.

The tool uses a versioned container format (currently v2.1) to allow for future improvements while maintaining backward compatibility with v2.0 encrypted files.

Cryptographic Primitives

  • Key Derivation: Argon2id (memory-hard, winner of the Password Hashing Competition 2015)
  • Encryption: AES-256-GCM (authenticated encryption with associated data, NIST SP 800-38D)
  • Salt: 32 bytes random per encryption
  • Nonce: 12 bytes random per encryption (GCM recommended size)
  • Key Length: 32 bytes (256 bits)

Security Properties

What GUN-101 does provide:

  • Confidentiality: Passive attackers cannot decrypt without the password (and keyfile, if used)
  • Integrity: Any tampering with the encrypted container is detected and rejected before returning plaintext
  • Brute-force resistance: Argon2id maximizes the cost of guessing passwords (memory-hard, GPU-resistant)
  • Two-factor protection: When a keyfile is used and stored separately, an attacker who knows the password still cannot decrypt without the physical keyfile

What GUN-101 does NOT provide:

  • Protection against malware on the encryption/decryption machine
  • Protection if both the encrypted file and keyfile are stolen (two-factor mode only)
  • Protection against side-channel attacks, coercion, or future cryptographic breaks
  • Secure deletion of plaintext or temporary files

Usage

Installation

pip install gun101

Generate a keyfile (for two-factor mode)

gun101 generate-keyfile /path/to/keyfile

This creates a 32-byte random keyfile and prints its SHA-256 fingerprint. Store the keyfile on a separate device (e.g., USB drive) and record the fingerprint.

Encrypt a file

gun101 encrypt secrets.pdf --keyfile /path/to/keyfile

Encrypts secrets.pdf to secrets.pdf.gun101. Omit --keyfile for password-only mode.

Password requirements: Must be at least 10 characters long and contain at least one uppercase letter, one lowercase letter, one digit, and one special character.

Password input: Password can be entered via interactive prompt or provided through the GUN101_PASSWORD environment variable (see Security Design for trade-offs).

Decrypt a file

gun101 decrypt secrets.pdf.gun101 --keyfile /path/to/keyfile

Decrypts to secrets.pdf (removes .gun101 extension). Omit --keyfile for password-only mode.

Password requirements: Must be at least 10 characters long and contain at least one uppercase letter, one lowercase letter, one digit, and one special character.

Password input: Password can be entered via interactive prompt or provided through the GUN101_PASSWORD environment variable (see Security Design for trade-offs).

Verify a keyfile fingerprint

gun101 keyfile-fingerprint /path/to/keyfile

Prints the SHA-256 fingerprint to confirm you have the correct keyfile.

Command Reference

The complete reference for the external interface — every command, input, output, environment variable, exit code, and the container file format — is in docs/CLI.md. A summary follows:

gun101 encrypt <file> [--keyfile <path>] [--output <path>]
  Encrypts <file>. If --output not given, writes to <file>.gun101

gun101 decrypt <file> [--keyfile <path>] [--output <path>]
  Decrypts <file>. If --output not given, strips .gun101 extension or appends .decrypted

gun101 generate-keyfile <path>
  Generates a keyfile at <path>. Prints fingerprint after generation.

gun101 keyfile-fingerprint <path>
  Prints the SHA-256 fingerprint of a keyfile.

gun101 info
  Prints program and container configuration (protocol, version, Argon2 parameters, library versions).

Design Decisions

Why Argon2id?

  • Resists GPU/ASIC cracking via high memory usage
  • Resists side-channel attacks via data-independent memory access
  • Recommended by OWASP and NIST SP 800-63B for password hashing

Password Composition Rules

GUN-101 enforces a password policy requiring at least 10 characters with uppercase, lowercase, digit, and special character. While NIST 800-63B de-emphasizes composition rules for online authentication (where rate limiting applies), GUN-101 retains them for the following reasons:

  1. Offline attack scenario: Encryption tools face offline brute-force attacks where rate limiting cannot be applied
  2. Entropy enhancement: Composition rules increase password entropy, making brute-force attacks more expensive
  3. User familiarity: Many users are accustomed to these rules and they provide a baseline strength guarantee
  4. Compatibility with Argon2id: Combined with memory-hard Argon2id, this provides strong protection against guessing attacks

Users seeking maximum security should consider using longer passphrases (14+ characters) that meet these requirements, or randomly generated passwords of sufficient length.

Why AES-256-GCM?

  • Provides both confidentiality and integrity (authenticated encryption)
  • Eliminates padding oracle vulnerabilities present in CBC mode
  • Standardized and widely vetted

Key Concatenation

The keyfile bytes are appended to the password UTF-8 bytes before Argon2id input. This ensures the derived key depends on both factors.

Error Handling

All errors produce generic messages (e.g., "Decryption failed") to avoid leaking information about what went wrong.

Limitations

  • No perfect memory wiping: Python's garbage collection prevents guaranteed key erasure from memory
  • Password strength enforcement: Passwords must be at least 10 characters long and contain uppercase, lowercase, digit, and special character
  • No forward secrecy: Compromised key reveals all past messages encrypted with it
  • No deniability: Encrypted files are identifiable by their structure

Dependencies

  • Python >= 3.10
  • argon2-cffi >= 23.1.0
  • cryptography >= 42.0.2

Reproducible Builds

For security-critical applications, exact dependency versions should be pinned to prevent supply chain attacks and ensure reproducible builds. A requirements.lock file is provided with exact versions and cryptographic hashes for all direct and transitive dependencies:

pip install --require-hashes -r requirements.lock

This lockfile includes:

  • argon2-cffi==25.1.0
  • cryptography==50.0.0

Testing

Run the test suite with:

pytest tests/ -v

Coverage of the gun101 package is measured with pytest-cov and must stay at 80% or above (see pyproject.toml); recent runs report ~88%.

Feedback and Contributing

Found a bug or have a feature request? Please open a GitHub issue — use the bug report or feature request template.

Want to contribute? Read CONTRIBUTING.md for setup instructions, coding standards, and security-sensitive contribution rules, then open a pull request.

Security vulnerabilities must not be reported as public issues. Report them privately by emailing adityaraj1234@duck.com (see Reporting a Security Vulnerability).

Reporting a Security Vulnerability

GUN-101 treats security reports with the highest priority. Do not open a public GitHub issue for a security vulnerability. Instead, email the maintainer directly at adityaraj1234@duck.com with the subject prefix [GUN101-SEC].

What we commit to:

  • Acknowledgement of receipt within 48 hours
  • A fix timeline within 7 days
  • Coordinated public disclosure only after a patched release is available

The full process — supported versions, what is in and out of scope, how to structure a report, and how reporters are credited — is in SECURITY.md.

Project Documentation

License

MIT License - see LICENSE file.

Warning

This software is provided as-is without warranty. Use at your own risk. The author is not liable for any data loss or security breach resulting from the use or misuse of this software.

Remember: Encryption is only as strong as your password and your ability to keep the keyfile (if used) secure. No tool can protect against a compromised endpoint or a coerced user.

Metadata

Release files for gun101 2.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gun101 2.2.2
File Size Uploaded Provenance
gun101-2.2.2.tar.gz 103.8 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for gun101 2.2.2
File Interpreter ABI Platform
gun101-2.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 126.9 kB

Release files / gun101-2.2.2.tar.gz

Download URL gun101-2.2.2.tar.gz
Size 103.8 kB
Tags Source
SHA-256 checksum
How to use checksums
bf3cdf1ddeaadf55a14977abeb2cbe1b16b48be753e2a04c58243df0f8979139
BLAKE2b-256 checksum
How to use checksums
a1271088092031697ffab5774fe51a1dcf88178b3a9348f31a1317355c48d76b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Release files / gun101-2.2.2-py3-none-any.whl

Download URL gun101-2.2.2-py3-none-any.whl
Size 23.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4a28d353a7c5c5f249ef61256f4316727cef09059e663a40a18ec6c0e5ceea30
BLAKE2b-256 checksum
How to use checksums
e91db67572131b6634d17088f2c72182b1c643ace20d2033e64f6154f5e3620e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Security for gun101 2.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for gun101-2.2.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page