
End-to-end encryption in the browser - fausto95
https://blog.excalidraw.com/end-to-end-encryption/
======
m1el
I appreciate the effort, but this is one of those cases in which there isn't
much security added by encryption.

If I assume the website owner is malicious (or subverted by powers that be), I
cannot trust the JS code provided by the website. Key disclosure is as trivial
as one line hidden somewhere in megabytes of JS code delievered from the
server. Which makes "end-to-end" part nearly meaningless.

~~~
_bxg1
How does that differ from a native app? In any E2E context you have to trust
the client code.

Sure, there are a couple extra steps needed here:

\- The website author needs to avoid casually throwing in dependencies (unlike
perhaps the average JS project)

\- HTTPS for loading code resources is crucial; maybe even CDNs need to be
avoided

\- The user needs to avoid having browser extensions enabled

But the fundamental problem doesn't seem different nor intractable.

~~~
m1el
I can build a native app from the codebase myself. I can be sure that a native
up won't change in-between launches.

> In any E2E context you have to trust the client code.

I don't have to trust code which is continuously being delievered from the
server. This is an intractable problem.

~~~
_bxg1
Others have said it's open-source. Build it yourself, inspect what your
browser downloads, hash and compare like normal.

~~~
vbezhenar
How do you hash your browser downloads? Also you need to perform that on every
request. It should be possible with additional addons, but definitely not out
of the box.

~~~
_bxg1
You can easily open the dev tools, view the payloads, and copy them locally.
It would be trickier to prevent evaluation before you've done so, but all you
have to do is not enter anything sensitive until you've checked

------
lukeschlather

        const encrypted = await window.crypto.subtle.encrypt(
          { name: "AES-GCM", iv: new Uint8Array(12) /* don't reuse key! */ },
          key,
          new TextEncoder().encode(JSON.stringify(content))
        );
    

This looks wrong. The iv should be a randomly generated string that is only
used once. I'm not super familiar with modern Javascript, but I think you're
just initializing a bunch of null bytes.

Honestly, I feel like whoever designed AES intended for people to make this
mistake, because half of the sample code I see has this error, and it would
have been easily avoided by specifying the IV length in the standard and
requiring libraries to automatically generate it and prepend it to the
ciphertext rather than letting callers have control over how it is initialized
and stored.

~~~
wildduck
Well on the site it was said

"We encrypt the content with that random key. In this case, we only encrypt
the content once with the random key so we don’t need an iv and can leave it
filled with 0 (I hope…)."

Anyone think that is a good idea?

~~~
dchest
It's a good idea if you encrypt with the same key _once_ — you can avoid
attaching nonces to your ciphertext (less code and data), and have only
16-byte key in the URL.

In fact, using a random IV with AES-GCM is not exactly safe: 12-byte nonce is
too small to avoid collisions with many encryptions. The recommendation is to
not encrypt more than 2^32 messages with the same key if you use the random
nonce.

~~~
vbezhenar
What would happen if an attacker gets two different messages with identical IV
and key?

~~~
dchest
They'll get the XOR of the two original messages, and also can break
authentication: [https://crypto.stackexchange.com/questions/26790/how-bad-
it-...](https://crypto.stackexchange.com/questions/26790/how-bad-it-is-using-
the-same-iv-twice-with-aes-gcm/68525#68525)

~~~
vbezhenar
That's scary, thanks!

------
vjeux
Super excited to see that excalidraw made the front page! We published an
article yesterday explaining how the end to end encryption works when sharing
a link: [https://blog.excalidraw.com/end-to-end-
encryption/](https://blog.excalidraw.com/end-to-end-encryption/)

~~~
mkl
Any chance you could add actual pen-like drawing? That would make it much more
versatile, and make it fit its description better ("Excalidraw is a whiteboard
tool that lets you easily sketch diagrams that have a hand-drawn feel to
them."). Bonus points for using PointerEvents to change the line width with
the pen's pressure.

Saving the diagram automatically and restoring when the site is revisited is a
nice touch.

~~~
lipis
There is an issue up for grabs:
[https://github.com/excalidraw/excalidraw/issues/25](https://github.com/excalidraw/excalidraw/issues/25)

------
seemslegit
As with every in-browser encryption deployment - what's the threat model here
?

> I now sleep much better at night. If the hosting service gets compromised,
> it doesn’t really matter as none of the content can be decrypted without the
> key.

Which can be easily exfiltrated by the compromiser as they are now in a
position to deliver and run arbitrary javascript in your users browser where
the keys reside

Also, why can't I draw an actual non-flawed circle ?

~~~
SamBam
> As with every in-browser encryption deployment - what's the threat model
> here ?

I believe the biggest win is that existing content will not be accessible to a
hacker even if they fully compromise the website, unless users re-open them.
So, sure, plenty of content _may_ get compromised if the site gets hacked, but
some large percentage of old content will not be.

> Also, why can't I draw an actual non-flawed circle ?

Adding sloppiness when white boarding is a common pattern to indicate
roughness. It subtly cues the viewer not to treat it as a completed product,
and allows them more freedom to make changes. If you wanted clean lines, there
are many web drawing tools for that too.

~~~
seemslegit
> I believe the biggest win is that existing content will not be accessible to
> a hacker even if they fully compromise the website, unless users re-open
> them. So, sure, plenty of content may get compromised if the site gets
> hacked, but some large percentage of old content will not be.

The attacker won't need to wait for the users to open a specific drawing -
just browse to the website, from there they can grab the keys for all drawings
they have assuming that not that many of them exist in the first place and the
attacker has the list of key ids from the compromised backend.

It does call for a much more noisy and visible attack which is by itself a
valuable mitigation.

~~~
SamBam
Either I'm not understanding you, or you're not understanding the tech. The
website does not store _any_ of the keys. They exist as a url fragment that
only the user has ever seen.

So if I create an image today and encrypt it, only I see the key. If you hack
the website tomorrow, you have access to my encrypted content, but not the
key.

 _Now_ that you control the website, you can modify the code so that the key
gets sent up every time a user encrypts or decrypts something. But you don't
have any access to anything created before you hacked it, if no user decrypts
it.

------
DVassallo
Looks neat!

End-to-end encryption in the browser is not perfect security, as other
comments are saying, but it’s significantly better than having user data in
clear on a MySQL database somewhere.

PS. I’m the founder of Userbase.com — an open source service to help you build
end-to-end encrypted web apps like this.

------
j4_hnews
One of the problems with hacking the hashtag (#) in the URL is that this
fragment identifier is supposed to be used to identify a portion of the
document. As such unexpected things can happen when you try to exploit the
hash tag for other purposes.

For example, with older of versions of Microsoft Office you cannot use a pound
character in a hyperlink:

[https://support.microsoft.com/en-us/help/202261/you-
cannot-u...](https://support.microsoft.com/en-us/help/202261/you-cannot-use-a-
pound-character-in-a-file-name-for-a-hyperlink-in-an)

Some email applications may unexpectedly strip the tag, attempting to be smart
about handling it in the RFC 3986 sense (not anticipating this use-case at
all). When the data appended to the # is a dependency to view the link, it can
more easily render the link unusable.

~~~
jakearmitage
What would be a valid alternative?

------
rattray
For anyone else uninitiated:

> Excalidraw is a whiteboard tool that lets you easily sketch diagrams that
> have a hand-drawn feel to them.

It appears to be free open-source software on an MIT license.

[https://github.com/excalidraw/excalidraw](https://github.com/excalidraw/excalidraw)

------
ejstronge
More information about the project (I’m unaffiliated, just wanted to learn
more!) [https://blog.excalidraw.com/reflections-on-
excalidraw/](https://blog.excalidraw.com/reflections-on-excalidraw/)

------
reimertz
Awesome work! Definitely not common knowledge that parameters after # isn't
sent over the wire. Can be used in fun ways.

I did the same thing but for text with
[https://anolog.org](https://anolog.org).

Sadly, since I used anonymous gists hosted on Github as my Data store, which
they shut down last year, the service doesn't work anymore. :(

------
sneak
From one of HN's own stars:

Javascript Cryptography Considered Harmful:
[https://www.nccgroup.trust/us/about-us/newsroom-and-
events/b...](https://www.nccgroup.trust/us/about-us/newsroom-and-
events/blog/2011/august/javascript-cryptography-considered-harmful/)

There are some out of date bits, but the core of the post is still as true as
it was back in 2011.

~~~
minitech
Very little of that article is applicable. The website is served over HTTPS,
the browser has a crypto API now. The encryption in this project decreases the
impact of any future compromise of the server (if a share link is never
visited post-compromise, it’s safe) _and_ makes it necessary for an attacker
to show their hand by serving malicious code to the client. (With browsers as
they are now, that can be made hard to detect, but it’s a start. There’s
always the risk of serving it up to someone who’s logging every response.)

~~~
sneak
All the other js resources on the page can still backdoor the app, though, and
exfiltrate your keys. SRI and no longer executing javascript served with the
right content-type in an img src is helpful along these lines, but even with
SRI on every script tag, the sub-scripts pulled in from the integrity-checked
third party js can pull in arbitrary further resources which can then
overwrite your functions to steal your keys.

Even a strict CSP doesn't totally close the hole.

It's sort of crazy how difficult (that's a euphemism—I would term it
"impossible") it is to even attempt to secure browser-based crypto, over and
above the normal challenges involved in crypto implementation. I wouldn't use
clientside js crypto for anything more secret than a grocery list.

------
imglorp
I like that this is nice and simple and intuitive: if I want a bazillion menus
and options there are many other tools. I also like the hand-drawn font.

------
marcus_holmes
Wait, so you're sending the key in the url?

I thought urls weren't encrypted in HTTPS? Am I missing something?

~~~
inetknght
URLs are encrypted. Hostnames aren't encrypted in HTTPS, unless TLS SNI is
encrypted.

The problem with URLs is that a lot of products will log the URL to disk, and
many operators forget or aren't aware they might need to have security plans
around data in the logs.

~~~
tialaramex
A worse and impossible to mitigate problem in other scenarios is that user
agents will cheerfully "bookmark" or "favourite" a URL or just let you "share"
it and it's often not obvious to the end user that this shares their current
state which they probably don't want not just the thing they're looking at.
Example: you try to share the forum help link but instead give the recipient
your logged in account...

This is the reason not to put authentication tokens into URLs for example.

When the state users want to bookmark or share literally is the state that's
encrypted anyway this mismatch isn't a threat. If I send you the URL for this
drawing of a cat and then I'm astonished you can now see the drawing of the
cat I've got real problems technology can't fix.

~~~
marcus_holmes
yeah, this.

Having the key in the url seems insanely insecure to me.

~~~
henriquez
Why? It makes it easy to share a sketch with someone else while still
preventing the server from decrypting the data. Anything stored in a location
hash (after the # symbol) does not get passed to the server.

The threat model the author tried to work around is not the user dumbly
compromising their own work. The author wants to prevent proprietary and PII
data from being stored on their own server. End-to-end encryption
significantly reduces the author's potential liability hosting something like
this in case something goes wrong.

~~~
inetknght
> _Why? It makes it easy to share a sketch with someone else while still
> preventing the server from decrypting the data. Anything stored in a
> location hash (after the # symbol) does not get passed to the server._

I'll hit the URL bar and hit control-C. That's way better than any javashit
which wants to touch my clipboard.

Copying the current URL also copies the key in that case. Now I'm accidentally
sharing my encryption information with another user.

~~~
henriquez
That's literally the use-case of pasting the link to your sketch to someone.
The app itself is not touching your clipboard. Take a careful look at how this
works, it's perfectly innocuous.

------
lisper
Another similar effort:

[https://github.com/Spark-Innovations/SC4](https://github.com/Spark-
Innovations/SC4)

(Disclosure: SC4 is my project.)

------
kn8
I'm a fan of [https://precursorapp.com/](https://precursorapp.com/), but will
give excalidraw a go.

------
jakearmitage
This works well for sharing stuff like notes, drawings, etc. But what if your
platform was more like a forum or a chat room? How could you share the keys?

------
ckocagil
Is this going to be legal in the US under EARN IT?

~~~
dwheeler
Almost certainly not. EARN IT doesn't technically forbid encryption, it just
lets an unelected board decide the legal requirements for communication
without being sued into oblivion. But the unelected board will be under the
control of those who object to encryption they can't break.

It would probably be legal if the program also sent the crypto keys somewhere
for later use.

------
peterwwillis
JavaScript "encryption" is like sending someone a letter in a package with a
TSA lock on it, asking them to communicate secretly with you. They send you
back the package with the lock, and instructions on how to communicate
securely. You send the package back with the lock and your message encrypted
according to the instructions.

It doesn't matter what your encryption scheme is. The TSA lock means the TSA
can control the content. But the user assumes their communication isn't
controlled by the TSA, because they are receiving instructions that appear
normal.

