Description: "8,432 lines of Python, 200 bit-flips, 460 fuzzed inputs, and one honest flaw. Here's what happened when I attacked ATLOCK v5 before releasing it."
TL;DR: I built a single-file security suite in pure Python. Before release, I locked it in a clean virtual environment and tried to wreck it. Most things held. One thing made me frown. You can try the current version (v4) today, and v5 is already built and waiting for a milestone. 👇
🎬 The setup
Everyone says "my tool is secure." Almost nobody publishes the receipts.
So I did something slightly uncomfortable: I took ATLOCK v5 (not public yet), dropped it into a fresh venv, and attacked it like a stranger would. No GUI clicking, no gentle demos. Raw crypto functions, corrupted files, wrong passwords, forged keys.
python -m venv atenv && source atenv/bin/activate
pip install cryptography argon2-cffi pillow numpy qrcode requests
python ATLOCK_v5.py --selftest
First, some context on what we're even looking at:
| ATLOCK v4 (public today) | ATLOCK v5 (built, unreleased) | |
|---|---|---|
| Size | 3,074 lines · 23 classes | 8,432 lines · 55 classes |
| File encryption | Fernet (AES-128-CBC + HMAC) | AES-256-GCM, chunked, key-committing |
| Password hashing | PBKDF2-SHA256, 200k iterations | Argon2id (64 MiB floor, 128 MiB for vault) |
| Sharing files | none | X25519 + Ed25519 public-key encrypt & sign |
| Recovery | none | Shamir secret sharing (3-of-5) |
| 2FA | none | TOTP + FIDO2 hardware keys |
| Built-in self-test | none | 33 checks + a corruption fuzzer |
Fun fact: v5 is nearly 3x the code of v4. So the real question was: did the extra code add security, or just extra places to crash?
🧪 Round 1: The built-in self-test
$ python ATLOCK_v5.py --selftest
[OK] Zip-slip / traversal names rejected
[OK] Doctored-header KDF ceiling is enforced (no DoS via .atl file)
[OK] Empty (0-byte) file container round-trips
[OK] Recovery key split into shares (3 of 5) rebuilds exactly
[OK] Frozen v1 / v2 / v3.0 containers from ATLOCK 5.0 still open
...
----------------------------------------
ALL PASSED (33/33)
Passing your own tests is the easy part, of course. So I stopped trusting them and wrote my own.
💥 Round 2: Try to corrupt it
The attack: seal a 5 MB random file, then flip one random bit, anywhere in the encrypted blob. Do that 200 times. If even one flip decrypts to wrong data without complaint, that's silent corruption, the nightmare scenario.
bitflip_200: rejected=200 silent_corruption=0 unexpected_crash=0
truncation (5 cut points): rejected=5/5
wrong password: AtlockAuthError
same input sealed twice -> different ciphertext: True
200 out of 200 rejected. Zero silent corruption. Zero crashes.
Then I let the built-in fuzzer loose:
$ python ATLOCK_v5.py --fuzz 300
fuzzed 300 container mutations, 100 garbage shares, 60 junk imports:
no crashes, no silent corruption.
That's 460 hostile inputs, no drama.
⚡ Round 3: Is it slow? (Security that's painful gets switched off)
| Operation | Result |
|---|---|
| Seal 5 MB file | 0.77 s |
| Open 5 MB file | 0.63 s |
| Container overhead | 134 bytes |
| Argon2id (64 MiB, t=3) | 0.16 s |
| Argon2id (128 MiB, t=4, vault) | 0.45 s |
| PBKDF2 200k (what v4 uses) | 0.05 s |
This is the part I find genuinely interesting. v4's PBKDF2 takes ~50 ms. An attacker with a GPU rig loves that. v5's Argon2id makes each guess cost 128 MiB of RAM, which is exactly what GPUs are bad at. Same login delay for you, a far worse deal for them.
🔐 Round 4: Public-key mode (the new toy)
Two identities, Alice and Bob. Alice encrypts and signs a file for Bob.
| Scenario | Outcome |
|---|---|
| Bob decrypts | ✅ works, signature verified |
| Alice tries to open Bob's file | ❌ "encrypted for a different identity" |
| Flip one byte in the file | ❌ rejected |
| Edit the file after signing | ❌ signature check fails |
| Shamir: any of the 10 possible 3-of-5 combos | ✅ rebuilds the key exactly |
| Shamir: only 2 shares | ❌ refused |
Everything behaved. Except...
😬 The thing I'm not happy about
I tested sender pinning: Bob says "I only trust files from this key," then I hand him a file signed by someone else.
>>> atl_pk_decrypt_file(enc, out, "bobpass", expected_sender_pub=wrong_key)
{'signed': True, 'signer_matches': False}
It decrypted anyway. The app shows WARNING: this is NOT the sender key you pasted!, but it does not stop.
Is that a bug? Honestly, it's a design choice, and I can argue both sides:
- Warn-only: the user stays in control, and you might genuinely want to read a file first and ask the sender later.
- Hard-fail: if you pinned a key, you already told the app you don't want anyone else. A warning is a polite way to get ignored.
I lean towards hard-fail when a key is pinned. Where do you land? This is my real question for the comments. 👇
🔎 Other things the scan flagged
I ran bandit over both files:
| v4 | v5 | |
|---|---|---|
| High | 0 | 1 |
| Medium | 0 | 3 |
- The 1 "High" is SHA-1, used for the Have I Been Pwned password check. That API requires SHA-1, and only the first 5 characters of the hash ever leave your machine (k-anonymity). Flagged, explained, fine.
-
The 3 "Mediums" are
urlopencalls. Worth pinning URL schemes in the final release. Noted.
Also caught a docs bug while reading: the v5 header still says "UI is unchanged from v5". A copy-paste leftover from earlier versions. Embarrassing, tiny, getting fixed.
🧱 What I did NOT test (be honest, right?)
ATLOCK is Windows-first, and my sandbox was Linux. So:
- ✅ Tested: all crypto, container format, fuzzing, Shamir, public-key, signatures, CLI
- ❌ Not tested here: the GUI, Windows Hello, DPAPI (falls back to a dev mode off-Windows), BitLocker checks, camera/intruder capture, the startup watchdog, FIDO2 with a real YubiKey
The project's own docs say it plainly too: a pure-Python tool cannot stop an attacker who is already running code as you, and secure-delete can't be guaranteed on SSDs. ATLOCK raises the cost; it doesn't claim magic. I'd rather you hear that from me than discover it later.
🚀 Try it, then come back for v5
ATLOCK v4 is public right now:
Here's the deal I'm offering:
- Grab v4 and try it for a few days. Lock a file. Break a password on purpose. Tell me what annoys you.
- Wait a little. v5 is already finished (everything above came from it), but I'm releasing it when Akhouri Systems crosses 1,000 downloads.
- Right now we're at 910. That's 90 downloads away. 🎯
When it lands, you upgrade to Argon2id, AES-256-GCM, hardware-key 2FA and public-key encryption, with your existing v4 habits intact.
💬 Let's argue (nicely)
I'd really like your takes on these:
- Pinned sender key doesn't match: warn or hard-fail?
- Would you trust a pure-Python security tool with real files, or does that make you nervous? Be brutal.
- Argon2id at 128 MiB: too heavy for older laptops, or still not enough?
- What would make you switch from your current vault or file locker?
Drop a comment. The best criticism ends up in the v5 changelog with your name on it. 🏷️
Built by Akhouri Anmol Kumar · An Akhouri Systems product
Top comments (16)
Really nice write-up. I especially appreciate that you included what you did not test — that makes the security claims much more credible.
On sender pinning, I’d strongly prefer hard-fail.
If expected_sender_pub is explicitly provided, that is no longer just informational metadata; it is a security policy. Returning successfully with signer_matches=False means the cryptographic layer detected a policy violation but left enforcement to the caller/UI.
I’d probably make the semantics explicit:
That also makes the API safer for future integrations where there may be no human around to notice the warning.
One other thing I’d test before v5: make sure authentication happens before any plaintext becomes observable, especially with chunked AES-GCM. Corrupting random bits is a great test, but deliberately targeting chunk boundaries, lengths, nonces, tags, reordered/duplicated chunks, and the final truncated chunk would be interesting too.
Overall, publishing the failure cases alongside the successful tests is exactly the kind of security engineering write-up I like seeing. 👍
Thank you brooo, this is exactly the review I was hoping for. I ran your chunk-level attacks: 91 targeted mutations (length prefixes, tags, reordering, duplication, dropped and truncated final chunks, cross-seal splices) were all rejected, and 82/82 header bit-flips with the hash recomputed were rejected toooo,
Your pinning point turned out to be worse than I'd written: a pinned sender with an unsigned file also decrypted silently. V5 now fails closed with a dedicated exception, and an explicit override is required to decrypt anyway.
You also made me look at plaintext release: the streaming path hands out authenticated chunks before later ones are verified, and one viewing helper left partiaL plaintext on Disk after A failure. Both are fixed....:)
Hahaha, now this is why I enjoy security reviews. 😄
I came looking for one pinning edge case and somehow we ended up finding an unsigned-sender path, streaming plaintext exposure, and partial plaintext left on disk after failure.
That’s a very productive rabbit hole. 😂
More importantly, huge respect for actually testing the suggestions, publishing what you found, and fixing the behavior instead of defending the original design.
This is exactly how security software should mature. 🔐👍
I especially published the post and commented on post to trigger you
"Mustafa ERBAY hehehe" because I know you will use your security top tier mind and give me feedbacks, and more.
Bro Can I mention you later when ATLOCK v5 will publicly released in ATLOCK v5 repo your name?
Also Bro How can i make this post viral too?
mustafa bro, should I port ATLOCK v5 for linux and mac too?
currently it is only for windows.
reply?
You may refer to Jev, which works like an access control system. If identity verification fails, it blocks the operation entirely rather than just showing a warning.
I will definitely look at it.
bro how can I make this post viral too
There’s no guaranteed trick to make a post go viral. Virality relies on a mix of topic, headline, timing and luck.
Your security suite project is interesting. Try writing a hands‑on article about breaking your own ATLOCK, similar to this post. Stories about finding flaws and fixing them always attract developers. But don’t chase virality as your main goal. Focus on telling a genuine technical story first.
yeah, that's the point.
Mustafa ERBAY just helped me a lot.
due to him I fixed one flaw in ATLOCK v5.
Great to hear! External feedback is priceless for tightening up security tools 🔐
@akhourianmolkumar Bro, this is the spirit of true engineering.
"I tried to break it... it fought back." That is the best compliment a security tool can receive. If it doesn’t fight back, it’s useless.
Finding "1 thing you’re not happy about" is actually a win. Most people hide those flaws until they explode in production. You surfaced it now, while you can fix it.
KODA and ATLOCK are siblings in chaos. I’m shipping fast and fixing bugs in hours; you’re stress-testing boundaries and finding cracks. We are covering the full spectrum of HYNAWEB: Velocity + Resilience.
Drop the link when you patch that flaw. I’ll be first in line to test it against my Worker’s injection defenses. Let’s see if KODA’s 1µs regex filter can catch what ATLOCK misses. 😂️🐯
KODA & ATLOCK
2 greatest product ever made by 12-13
Mustafa ERBAY hehehe