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?
-
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.
-
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).
-
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):
-
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.
-
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.
-
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.
-
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).
-
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)
.
-
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.
-
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.