plaintext.world What's this?

Your key is being generated...

Persistence unavailable

It appears that your browser does not permit long term data storage.

While you may still use this app to receive new messages, you must not close it before you have received them or they will be permanently lost!

Storage full

Unable to persist a new key. This is likely because your storage is full.

While you may still use this app to receive new messages, you must not close it before you have received them or they will be permanently lost!

Alternatively, you can delete your old keys to free up space for new ones, but in doing so you will be unable to receive any message(s) bound to those key(s).

Frequently asked questions

What's this?

A little utility that allows you to receive private messages over a public channel, such as a forum or chat room. While it can provide some guarantees* regarding the secrecy, integrity and repudiation of the message, you are still responsible for validating the identity of the peer you are attempting to communicate with.

* purely theoretical, see Terms and Conditions for the legalese but the short version is: it's worth exactly how much you paid for.

How do I use it?
  1. When you want to receive a message from someone, you should open the app and copy the generated link to your clipboard. You may then send it over a public channel (forum, blog comment, chat room, etc.) and then wait for a reply.
  2. After your friend opens the link that you've sent, they'll type in their secret message and send you the scrambled response over a public channel (could be the same one they received the request on, or another that you visit frequently).
  3. Once you've received your reply, click it (if a link) or paste it in the app (if a text) and you'll be able to see the secret. Make sure to save it for later, you can only unscramble it one time!

Important! anyone that can see your message can also reply to it. Because each key may only be used once, you must make sure that the message you are trying to unscramble is sent by the person you are trying to receive the secret from. If you waste your key on the wrong message, you'll have to start over from step 1.

Is it secure?

Ehh, about a 7 / 10 all things considered:

Your secrets are mostly safe from me. While this app is served via the web, it doesn't connect to the internet once loaded. All your data remains on your device, unless you explicitly send it to someone else as instructed. This means that you can run it locally if you save this webpage to a .html file and open it from your computer. This is actually the safest way to run it, as the servers that deliver the app could be compromised in the future. To make sure that you have an untampered copy, ask a nerd you trust to audit the source code (which is intentionally kept unobfuscated) and then have them send you the copy that they're certain is safe to use.

Everything you send is (based on current knowledge) safe to make public but, there's no way to guarantee that you're sending it to the right person. Most platforms will provide some relief against this by pinky-promising that usernames may not be reused and that messages are not tampered with, but even if that's true, the peer account (i.e. your friend) may have been compromised and could be under the control of someone else that initiated the request on their behalf.

Your own device could have been compromised (e.g. via a virus or other malware that you may have inadvertedly installed or was installed by a vendor), in which case pretty much anything that you do can be considered insecure. For the layperson, there's no practical way to defend against this or even detect that it has happened: you need to trust the manufacturers of the hardware (e.g. physical computer / phone), of the operating system, of the browser used to open the page and everyone that set those things up unless you did it yourself.

Finally, there's the open question on whether the underlying cryptography is itself secure or how long will it continue being so. Again, there's no easy answer here and you have to balance the secrecy of your message against the cumulative human knowledge, some of which may be unpublished. If the contents of your message might be of interest to government agencies, you should consider pen and paper instead; that's probably what they do to protect against one another.

I'm being told This message does not seem to be intended for you but I'm certain that's not the case. What gives?

If you're being truthful, it looks like you've lost your keys. Don't worry, it happens to the best of us. The most common reasons for this error are (in rough order of probability):

  1. You've already used your key to unscramble another message. All keys are one-time-use so if you made a bad choice or forgot to save the message, you'll have to start over.
  2. You've followed a link or pasted a message in a different context from the one you used to generate the secret request. Usually this means that you've opened the link in a different browser, on a different device, or moved the .html app to a different location on your device. It could also mean that you've generated the key using a locally stored app and tried to unscramble with the web version, or viceversa. In all cases, consider replicating the original environment in which you issued the request and try again.
  3. Your browser deleted the key. This will happen if you've initially opened the app in a private / incognito window that you've since closed. It can also happen during a scheduled update, due to lack of available storage or simply because you haven't used the app in a while. Keep in mind that keys are ephemeral (i.e. they are not intended for long-term use). How long is too long is a question best answered by your browser configuration and thus, beyond the scope of this FAQ. This developer's expectation is around a week before you have to start over.
Why am I getting a The message is corrupted or was truncated in transit error?

This happens when the scrambling key was successfully exchanged but an error was encountered while unscrambling the message.

The most common cause is that you didn't paste the entire message (maybe you forgot a character or two at the end?) or the browser (or platform) truncated the link because it was too long.

It's also possible that the platform performed some unsafe substitutions that altered your message (e.g. by converting - into the nearly identical ).

If you have received a link, you may try manually copying the part after # into the pastebin, possibly after undoing any unsafe transformations that may have been performed.

If the situation persists, you may have to start over, possibly using a different platform for exchanging keys.

I've received my secret. How do I reply?

In short, you cannot.

Part of the reason is that only using keys once is a bit more secure, but the primary reason is that exchanging scrambled messages over a public platform frequented by humans is rather inconsiderate to the other participants.

If you want to have a longer private conversation with someone, arrange with them to exchange contact information as "the secret". This could be an email address, phone number or even a meeting place, preferably in a loud, public area where you can talk without being overheard once you've confirmed their identity.

How does it work?

Normal operation involves a ECDH[1][2] key exchange, followed by a SHA-256-based HKDF expansion into an AES key and IV. GCM is used to ensure message integrity against a 16 byte tag.

  1. When the would-be recepient opens the app, a public / private key pair is generated. The first "secret request" message contains the public key in raw format, base64-encoded as per RFC 4648 using the urlsafe alphabet and with padding removed. The private key is preserved in localStorage for later use, keyed by the SHA-256/128 hash of the corresponding public key in raw format (prior to base64 encoding).
  2. When the sender obtains the would-be-receiver's public key, it generates and then immediately discards a new key pair. It uses this private key to derive a ECDH secret and expand it into a AES-GCM key and IV, which are then used to bootstrap the block cipher and encode the message. The base64-encoded response will contain the concatenation of: publicKey, SHA-256/128(peerPublicKey) and aesGcm(message).
  3. In the final step, the receiver obtains the peer's encrypted message, extracts (and then discards) the previously stored private key corresponding to the hash included in the message, uses it in combination with the peer's public key to obtain the ECDH secret, then decrypts and displays the secret message.
  4. While the handshake is technically complete by this point, no further messages are possible because both parties have deleted their private keys, as well as the derived secret. An observer may notice that strictly speaking, the same properties could be ensured via the use of a single asymmetric key. WebCrypto does in fact provide this option via RSA, but ECDH was preferred due to faster key generation (important when using ephemeral keys) as well as smaller overall message size (important when transmitting data in the fragment portion of a URL).
Terms and Conditions

Copyright© 2023 Radu Dan

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.