Encrypt a file with a password using AES-256-GCM, in a documented format that records everything needed to open it again, and read it back a megabyte at a time
Initializing in your browser…
Encrypt and password-protect your PDF documents. Set user and owner passwords, control printing, copying, and editing permissions with 128-bit AES encryption.
Percent-encode and decode against four character sets, build query strings, and take a URL apart
Encode and decode text, files and JSON as base64, base64url or hex, checked by decoding the result back
A 64 KB file is encrypted with a password, and the question is whether anything other than this page can open the result. The numbers below are the ones the project's own test prints for that file.
Input
binary.bin, 65,536 bytes, password of 24 characters
binary.bin.tbxenc, 65,680 bytes
byte 0..7 54 42 58 43 52 59 50 31 the ASCII "TBXCRYP1" byte 8 01 format version byte 9 01 PBKDF2-HMAC-SHA256 byte 10..13 00 09 27 C0 600,000 iterations byte 14 01 AES-256-GCM byte 15..18 00 10 00 00 1,048,576 byte chunks byte 19 10 16 byte salt byte 20..35 the salt, random per file byte 36..39 the nonce prefix, random per file then the encrypted metadata block, then one chunk Decrypted again and compared: identical original SHA-256 1c301ad851944db207cc26142fb6deba8475b33cae79079687dc24ce085920d2 round trip SHA-256 1c301ad851944db207cc26142fb6deba8475b33cae79079687dc24ce085920d2 144 bytes of overhead: 40 header, 4 length field, 84 encrypted metadata (68 of JSON plus a 16 byte tag), 16 chunk tag
Everything a reader needs is in the file: which cipher, which key derivation function, how many iterations, the salt and the chunk size. That is the difference between a file only this page can open and a file anyone with the specification can open, and the project's test opens exactly this file with node:crypto and nothing else. The file name is inside the encrypted metadata rather than in the clear, so contract.pdf does not announce itself. Each chunk is sealed separately with the header, its own index and a final-chunk flag as additional authenticated data, which is what makes a reordered, duplicated, dropped or truncated chunk fail rather than decrypt into something else. And because the metadata block is the first thing the key touches, a wrong password and an altered file are two different messages instead of one.
Encrypt a file with a password, using AES-256-GCM and a key stretched from the password with PBKDF2 at 600,000 iterations, all inside this page. The output is a documented container that records every parameter needed to open it again, so a file made here is not hostage to this page still existing: the project's own tests decrypt these files with node:crypto from the written specification alone.
The measure of a file encryption tool is not whether its own decryptor reads what its own encryptor wrote. It is whether anything else can, given the password and the specification. The container this writes begins with the eight ASCII bytes TBXCRYP1, then a format version, an identifier for the key derivation function, the iteration count as a 32-bit big-endian integer, an identifier for the cipher, the chunk size, the salt length and the salt, and a four-byte nonce prefix. All of that is forty bytes, and it is followed by a length-prefixed encrypted metadata block and then the data chunks. Nothing has to be guessed and nothing has to be selected on the page.
The key is PBKDF2-HMAC-SHA256 over the password and the salt, at the iteration count stored in the file. The default is 600,000, which is the figure in OWASP's Password Storage Cheat Sheet for that function. Because the number lives in the file, it can be raised later without making a single existing file unreadable, and 200,000 and 1,200,000 are offered for a slow device and for a stronger setting respectively.
The file is read and written a megabyte at a time. Each chunk is sealed with AES-256-GCM under a nonce of the file's random prefix followed by the chunk index, and the additional authenticated data is the whole header, a tag byte, the chunk index and a flag saying whether this is the last chunk. That combination is what makes a reordered chunk, a duplicated chunk, a dropped chunk, a truncated file or an edited header fail to open rather than decrypt into something plausible. Reading in chunks is also what removes the size ceiling: measured in Chrome, reading a file into one buffer and encrypting it in a single call fails at 2,048 MB with a RangeError, while the same browser encrypts a real 2,048 MB file here in 4.2 seconds.
The original file name, its exact length and its media type go into the encrypted metadata block rather than into the clear, so an encrypted contract does not announce that it is a contract. That block is also the first thing the key touches, which is what makes the error messages honest: if it fails, the password is wrong; if it opens and a later chunk fails, the password was right and the bytes have changed. Those are two different messages here rather than one.
After encrypting, the tool decrypts the result again and compares the SHA-256 of what came back with the SHA-256 of the original, showing both digests. It runs automatically for files up to 100 MB and can be turned off. The point is that nothing is handed over that has not been read back.
AES-256-GCM is the only cipher offered. The previous version also offered AES-CBC as an equal choice with no warning; AES-CBC carries no authentication tag, and measured on a 160 byte file, flipping one bit of the ciphertext produced 160 bytes back with 17 of them changed and nothing reported. Files from that version still open here, both the GCM and the CBC kind, and a CBC one is labelled as unauthenticated when it does.
Encrypt before emailing, and share the password through a different channel. The recipient can open it here or with any tool that implements the format.
Encrypt files before they are uploaded, so the storage provider holds ciphertext. The 2 GB measurement above is the relevant one for a disk image or a database dump.
The format is written out in the source and in the project's tests, so the file can be opened later with node:crypto and forty lines of code even if this page has gone.
A file that was altered in transit fails its authentication check and says which block failed, rather than decrypting into corrupted bytes.
The file cannot be opened. There is no recovery mechanism and no back door: the key exists only as a function of the password and the salt in the file.
Yes, and that is the point. The container format is written out in full in the source, and the project's test suite implements it a second time with node:crypto and checks both directions: files written here are opened there, and files written there are opened here.
Because it is in the file. The previous version made you pick AES-GCM or AES-CBC at decrypt time and used that choice to decide how long the initialisation vector was; getting it wrong produced the message "Decryption failed. Check your password" when the password was correct. Now the file says which cipher it used, and AES-CBC is no longer offered for new files because it cannot detect tampering.
It reads and writes a megabyte at a time, so the limit is disk rather than memory. Measured in Chrome, a real 2 GB file encrypts in about 4.2 seconds; the previous version read the whole file into one buffer and failed at that size with a RangeError.
It is the figure OWASP currently gives for PBKDF2-HMAC-SHA256, and it is what the default writes. It is not Argon2, which is designed to resist a graphics card far better than PBKDF2 does; the Web Crypto API does not offer Argon2, and adding a JavaScript implementation would be slower and harder to verify. A long random password matters more than the iteration count either way.
It is the entropy of a password of that length drawn uniformly at random from the character classes it uses. It is an upper bound, and the page says so: a password you thought of yourself has far less, because a cracker tries words and patterns long before it tries at random. The number is only honest for a password a generator produced.
Yes. Those files had no header, so they are recognised by shape and tried with AES-GCM and then AES-CBC. When one opens as AES-CBC the page says so and explains that nothing can vouch for those bytes, because that mode has no authentication tag.
Conversions run on your device in JavaScript. The values you enter are never sent over the network.