PoW-to-Open

Proof-of-Work to Open — wrap any file in a standalone HTML document that brute-forces its own decryption key when opened.

Difficulty

Calibrates against a PBKDF2 benchmark on this machine and picks a bit width.

Measuring hardware…
How this works

The builder picks a random integer secret in the range [0, 2bits), derives an AES-GCM-256 key from it with PBKDF2-HMAC-SHA256 (using a fresh 16-byte salt and the chosen iteration count), and encrypts your file. The secret is not stored. Only bits, iterations, salt, IV, and ciphertext are embedded in the output HTML.

The output file contains inline JavaScript that opens navigator.hardwareConcurrency Web Workers on load. Each worker walks a disjoint slice of the key space and, for every candidate, re-derives the PBKDF2 key and calls crypto.subtle.decrypt. AES-GCM's authentication tag acts as the validator: a wrong key throws, a right key returns plaintext. No format sniffing or plaintext heuristic is needed.

Workers visit keys in a random-looking order rather than 0, 1, 2, …, so low-valued keys are not found faster than high-valued ones. The order is candidate = reverseBits(i, bits) ⊕ mask, where mask is a fresh per-run random value. Both operations are bijections on [0, 2bits), so the composition visits every key exactly once; sharding by i mod workerCount keeps worker ranges disjoint.

Two difficulty knobs are independent. Bits control the size of the search space (expected attempts ≈ 2bits−1). Iterations control the cost of a single attempt (PBKDF2 rounds). Total expected work is their product. Time-target mode benchmarks PBKDF2 on your current machine, fixes iterations at 10 000, and solves for bits.

Web-safe payloads (images, audio, video, PDF, text, HTML) are rendered inline after decryption; HTML goes in a sandbox="" iframe with an opaque origin and no scripts. Anything else gets a download link. The original filename and MIME type are preserved.

This is proof-of-work, not security. Anyone who obtains the output can brute-force it offline. You are only choosing how much computation that takes. Tune the parameters to match the cost you want to impose.