I build Crypt-in alone, in Bologna. It's file encryption anchored to a €5 ESP32-S3: the root secret is generated on the chip at first boot and no command in the protocol exports it. Files open while the dongle is plugged in. Pull it out and the session closes in under five seconds.
A product like that has an obvious problem. Its author is the worst person to judge it. So in August I handed it to an AI and asked it to break it. This post is what came back, including the two places where our own conclusions turned out to be wrong.
One thing up front, because it shapes everything below: this was me running sessions with an AI. It is not an independent audit, and the report says so. That's exactly why the second half of this post is an invitation.
The setup
Three sessions, 2–3 August 2026, with Claude Opus 5 as the red team agent. The target was one dongle (chip A4CB8FF84948, firmware dd14270).
What it had:
- admin on a Windows 11 VM
- the full SDK source, compiled binaries, and our protocol and file-format notes
- real
.crinsample files - the dongle over USB passthrough
- DnSpy, USBPcap, WinPmem, x64dbg, Python with hidapi, and internet for anything else
- permission to open raw HID handles, replace DLLs and intercept any process
- a live session on request: I type the PIN while the agent listens
What it didn't have: the firmware source (it's closed), our signing key, the PIN, the 24-word seed, or any access to the licence server.
The brief was three lines. Find every way to open a .crin file without the physical dongle. Then find everything else. Then invent attacks we hadn't thought of.
Every finding had to be reproduced on the real chip, with exact response bytes, chip serial and timestamp. Anything that wasn't got excluded from the signed report.
The main question
With full source, DnSpy, admin access and the physical dongle, but no PIN, does a .crin file open?
Without the PIN, no. Source code and admin rights don't get you to the secret, because it isn't on the PC.
With the user's PIN typed in and the dongle unlocked, yes. That's the High.
F-001-REV (High): a shared unlock session
The user unlocks the app with the correct PIN. A second process opens its own HID handle to the dongle and sends no PIN at all. The chip answers it anyway: the unlock state belongs to the chip, not to the handle or process that authenticated.
From that second handle, a 0x0E decrypt request on a Word document came back with 27,206 bytes starting 50 4b 03 04 (a ZIP header), with the GCM tag verified on the chip. The file key never crossed the bus. It didn't need to.
How long is the window? In session 3 an idle dongle was still unlocked at 300 seconds and locked at 600. Back then every HID command reset the idle timer. Since firmware 2026-08-03 only PIN-gated commands do, so a ping can't keep a session alive. But an attacker using this hole sends gated commands by definition, so for them the timer keeps resetting. Auto-lock protects an idle chip, not one under attack.
What closes it: unplug the dongle and wait at least five seconds. A fast replug can leave the ESP32 powered by its own capacitors, unlock state included. We measured that too.
The fix is session binding: authenticating the handle, not just the chip. It ships with the WiFi firmware release in Q2 2027, after the April 2027 public launch. Until then it's open, and we say so.
The two smaller ones
F-ISO (Medium, fail-closed). Same root cause. The block-cipher accumulator is global to the chip, so a second handle can interleave chunks into someone else's encrypt transfer and get a valid tag over mixed data. It can also abort any transfer with one out-of-sequence chunk. The victim's own tag fails, so nothing poisoned gets silently accepted. Same fix, same milestone.
F-003/B1 (Low). The PIN travels in cleartext over USB HID: six ASCII bytes at offset 3, no challenge-response, no anti-replay. With a USB sniffer on the PC, session 3 automated the whole chain. PIN out of the pcap in 0.2 ms, replay to unlock in 3.1 ms, a full 182,958-byte PDF decrypted through the chip in 6.66 s: 6.73 seconds from capture to plaintext, no human involved. The PIN is derived from the seed, so a captured one stays valid until the seed changes. The fix, challenge-response on VERIFY_PIN, is also due in Q2 2027.
Every open finding needs the user's PC to be compromised already: malware running during the session, access to the bus or to processes. Our threat model has said that from day one. If your PC is owned, your plaintext files are owned too, and the dongle isn't the weakest link.
What held
A report that only lists what worked is a sales document, so here's what didn't:
- tampering with nonce or salt →
ERR_TAG_MISMATCH, GCM integrity holds on-chip - reusing a tag across transfers → refused, the tag is bound to its data
- a licence JWT with a forged RS256 signature →
ERR_INVALID_JWT - power-cycling mid-encrypt → clean reset to locked, no leftover state
- the old "counter wraparound" theory → 66,000 chunks (~3.63 MB) round-tripped with the tag verified
One row looks like a failure and isn't: decrypting with a header that names a different dongle still works. The "wrong dongle" check lives in the app, and that's declared. With the wrong chip the tag fails anyway.
Where we were wrong
This is the part I'd want to read if I were you.
Erratum, 29 September. The report originally said the sessions ran on a production-configured unit. Then we read the chip's eFuses directly: virgin. No Secure Boot, no flash encryption. The test ran on a -dev board, the same track the developer beta uses. The findings are about protocol and firmware logic and they stand. What doesn't stand is any claim that they were reproduced on production hardware.
Erratum, 30 September, and it's the more serious one. Session 2 had concluded that the per-dongle file_secret could not decrypt files offline. It tried 279 key and AAD variants and none matched. None of them used the derivation label the firmware actually uses. With the right one, file_secret decrypts .crin files offline, permanently. On the -dev firmware an unlocked session hands file_secret out (0x04). So on beta hardware the High isn't just an online oracle: during an unlock window an attacker can walk away with the key. Production firmware refuses that command and encrypts its flash. The honest summary is that "at rest a file doesn't open" holds for production hardware only.
Both errata sit at the top and bottom of the report, and the body stays as it was conducted. In the report's own words: rewriting an audit after the fact is what makes audits worthless.
Then October
We kept going. Between 8 and 11 October, seven more red-team rounds against the beta firmware found nine defects, two of them High:
- F1: under a concurrent request the challenge nonce could repeat, enough to compute the identity signing key.
- H1: a malformed USB control request replayed the last report any process had written, PIN in clear included.
beta-2026-10-13 fixes all nine, and they're listed in the 13 October advisory. The three findings above are still open, and they'll still be open at launch.
Now it's your turn
An AI found real bugs, later rounds found more, and we got our own conclusions wrong twice. I'd rather have humans find the rest now than customers find it in April. There are three ways in, all free, all closing 31 March 2027.
1. The developer beta (your hardware, your rules). One download from GitHub: release beta-2026-11-04b, fourteen files, fourteen published hashes. You need an ESP32-S3 with native USB, at least 8 MB of flash and a way to reach serial: two USB-C ports, or a UART header plus an adapter. The reference board is an ESP32-S3-WROOM-1 DevKitC-1 (N16R8), about €5. Flashing and activation take roughly 15 minutes, with no card and no payment. Your own dongle, flash, firmware binary, USB traffic and client are all in scope. Beta boards have unburned eFuses on purpose, so SPI dumps work, and that's part of the exercise. It's a Windows 11 client (64-bit). A Linux x86-64 CLI covers daily use and activation, but the dongle's first setup needs Windows. The executables aren't signed, so SmartScreen will complain. → cryptin.lake8.dev/beta
2. The licence server, legally. There's a clone at redteam-license.lake8.dev, on its own host, outside our network. You build the RedTeam client from the public SDK source (dotnet build -c RedTeam in jaffa2970/cryptin-sdk-beta) and attack activation, renewal, transfer, recovery, rekey, races and replay under a written safe harbour (Italian law and the EU NIS2 provisions on security research). Load testing is allowed from one IP within the public rate limit. Production license.lake8.dev is out of scope for everyone, always. → rules of engagement
3. The extraction challenge (bring a lab). Pull the identity seed off an ESP32-S3 with Secure Boot and flash encryption burned in RELEASE mode. Glitching, power analysis and decapping are allowed on your own chip. Use the challenge image from jaffa2970/cryptin-challenge, never the beta one: the first boot burns the chip for good, and the wrong image bricks it. A software win would be a product bug and our problem. A lab win confirms a limit we already declare. No claim has been received so far. → extraction challenge
What you get, and what you don't. There's no monetary bounty. I'm one developer. Every finding that leads to a fix is credited by name in the April 2027 public report, with safe harbour and response times in writing. Reports go to security@lake8.dev (PGP key on the site). And if you try hard and can't break it, tell me that too. It's a result, and it goes in the report.
Questions about the HID protocol, the .crin format or the flash layout are welcome in the comments.
Tommy, lake8.dev, Bologna