Releases: ErickShepherd/pydlock
Release list
pydlock v2.0.6
Branding and packaging-metadata polish — no code changes.
-
Project logo. Added a brand mark — a padlock formed by an ouroboros
serpent (Python + padlock + a sealed loop) — underbrand/: a light/dark
README lockup (<picture>theme-swap), the mark tile, and black/white
transparent mono variants. The wordmark uses Sora (SIL OFL 1.1), vendored
with its full license. -
Docs logo. The Read the Docs sidebar now shows the mark (furo
light/dark logo). -
Project URLs. Standardized the PyPI project links:
Documentation
now points at the released docs (/en/stable/rather than/en/latest/),
added aChangeloglink to the GitHub releases, and renamedBug Tracker
toIssues.
pydlock 2.0.5
Documentation site + metadata polish — no code changes. Sphinx docs hosted on Read the Docs (shipped in-tag, fixing the tag-based "stable" build), API reference for lock/unlock, encrypt/decrypt, and the prompt helpers, and a Documentation URL in the PyPI project links.
Full details: CHANGELOG.md
v2.0.4
Citation metadata only — no code changes.
- Added
.zenodo.jsonand an author ORCID inCITATION.cff, so this release is archived on Zenodo with a citable DOI and correct software metadata.
v2.0.3
Docs & packaging release — no code changes.
- New "Problems this solves" section in the README
- Corrected the quoted wrong-password message to match the actual output
- Added the previously-missing PyPI trove classifiers (Security :: Cryptography, Utilities) and expanded keywords
- Removed a stale docstring note about Windows executables
See CHANGELOG.rst for details.
pydlock 2.0.2 — audit remediation
2026-07-08 - Version 2.0.2
Audit remediation release (whole-file :code:audit-repo pass, 2026-07-08). No
on-disk format change; every fix is backward compatible.
-
Security: a malformed envelope always fails cleanly. A crafted, deeply
nested JSON header made :code:json.loadsrecurse past the interpreter limit
and raise an uncaught :code:RecursionError, leaking a traceback on hostile
input. :code:decryptnow bounds the raw header length before parsing and
catches :code:RecursionErrorin the malformed-envelope handler, so such a
file returns the clean :code:Nonesentinel, fast, with no traceback. A
valid-JSON but non-object header (e.g. a bare number or list) is likewise
rejected as corrupt via an :code:isinstanceguard, closing an adjacent
:code:AttributeErroron the same untrusted-input path. -
CLI: a failed unlock now exits non-zero. The CLI discarded the
:code:lock/:code:unlockreturn value, so a failed :code:unlock(wrong
password) exited :code:0and scripts could not detect the failure. It now
exits :code:1on failure. -
File permissions are preserved across a round-trip. The atomic write
created its temp file :code:0600and swapped it into place, silently
tightening a :code:0644file to owner-only on every lock/unlock. The
original file's mode (and best-effort owner/group) is now copied onto the
temp before the swap; a newly created file keeps the safe :code:0600
default. -
Diagnostics go to stderr with one honest message. Decrypt diagnostics
printed to stdout (where decrypted plaintext may be piped) and
:code:"Incorrect password."mislabelled genuine corruption/tamper. Both
failure paths now print a single
:code:"Could not decrypt (wrong password or corrupt file)."to stderr. -
Tests and internals. Added a CLI test module covering :code:
__main__
(verb dispatch, the encrypt/decrypt aliases, abspath coercion, encoding
forwarding, and the failure exit code) plus regression tests for each fix
above, and extracted a shared :code:_normalise_passwordhelper. Refreshed
stale header dates.
v2.0.1
pydlock v2.0.1 — first published v2 release. A dead-simple password padlock for files: pydlock lock <file> / unlock, or from Python.
Breaking: new on-disk file format. Files locked by pydlock 1.x still decrypt transparently (re-locking upgrades them); the last 1.x release stays installable via pip install 'pydlock<2'.
New in v2
- Salted, memory-hard scrypt KDF (
n=32768, r=8, p=1) with a fresh per-file random salt, replacing the unsalted single-pass SHA-256. Cipher remains Fernet (AES-128-CBC + HMAC-SHA256); no custom crypto. - Self-identifying, versioned on-disk envelope (
PYDLOCKmagic + JSON header of KDF params + salt). Hardened against malicious headers: scrypt cost parameters are validated and bounded before use, so a crafted file can't force excessive memory/CPU on decrypt. - Transparent v1 legacy decryption — non-magic (v1) files are detected and decrypted with the old scheme, so nothing is stranded.
- Binary files no longer corrupted — raw-bytes I/O; executables round-trip losslessly.
- Crash-safe atomic writes.
- Removed the
python/rundecrypt-and-execute subcommands (a security footgun). encrypt/decryptCLI aliases + apydlockconsole entry point.- Packaging:
pyproject.toml(hatchling), declared thecryptographydependency, offline pytest suite, ruff, CI (Python 3.10–3.13), OIDC Trusted Publishing.
2.0.1
- Fix: the public
password=argument accepted bytes but crashed on astr; passwords are now accepted as str or bytes. (2.0.0 was a pre-release validated on TestPyPI and never published to production PyPI.)