I keep asking, what is the threat model for end-to-end encryption in JS? Like, is there an Alice, Bob, Carol, Eve story under which E2E in JS makes sense?
The canonical example that doesn't make sense is when Alice and Bob want to communicate privately using Eve as a webmail/chat provider who wants to snoop in on the communications. Alice and Bob can't just trust Eve to provide a copy of E2Ejs in a <script> tag on EveMail.com, because then they're trusting Eve to provide a legitimate encryption implementation, trusting Eve not to log their keystrokes in JS, etc.
I can understand E2E js as a server-side library in Node (though I suspect it would be safer to run a battle-hardened library like GPG with node FFI).
But, in client-side web code, how could this ever make sense?
Eve is not the threat. Eve is going along serving email for Alice and Bob just fine for quite a while.
Then one day Fred compromises Eve. Fred can dump data directly out of Eve's database. Depending on how Fred gains access, full disk encryption, database encryption, row-level encryption, etc. might or might not present themselves as layers of security that he must bypass. If Fred has compromised the running service, he will likely have access to the data and any keys, source material needed to derive the keys, or external decryption mechanisms (HSMs, database-side services) from within the service itself.
If the messages inside of the database have been encrypted on the clients with keys not held in the server (E2E), Fred now has another layer of defense in front of him, only this one requires Fred to inject script into the clients to scrape the necessary keys. When the client is running Javascript in the browser, this is obviously easier than on clients deployed through some other mechanism, but still more difficult than being able to get everything Fred needs in memory in the server.
Mainly, it's another layer of defense, and if the service is using it for other clients, a browser-based client would need to have it to function anyway (even if that weakens the security of the users choosing to use it).
An alternate scenario is that Eve is also not a threat, but is instead a business that doesn't want the liability of having certain material in the plain inside of its premises ever.
But Eve is where the attacks are going to come from. Whether it's Eve's intention, or was under coersion by Fred makes no difference to the end user. Browser E2E encryption is at best marginally harder to break, but it gives the user a bigger sense of privacy than it deserves, may be to the detriment of the unlearned user.
I would argue that collecting keys from all of the user's browsers and dumping the database is more difficult than dumping the database alone, and that makes it worth doing.
If as Fred my window of opportunity before I'm detected is small, I might only be able to get keys from users that are active within a small window. I may have to deal with CDN TTLs just to get my code to those users in the first place. The deployment setup might make it a little harder to change the code than just modifying a plaintext file on disk on the server (personally the project I'm working on right now packs static assets into the server binary making them easy enough for Eve to update, but a bit more effort for Fred). In more complex scenarios, there may be many things standing between Fred and injecting code into the browser that aren't in the way of reading the database.
It really depends on the specifics of the threat that you're modeling for and how your environment works. For example, if we only focus on scenarios in which we are concerned about an attacker that has wholly compromised the service as you are describing here, we would similarly conclude that TLS serves no purpose as the attacker is already receiving the decrypted data at the other end of the pipe.
> An alternate scenario is that Eve is also not a threat, but is instead a business that doesn't want the liability of having certain material in the plain inside of its premises ever.
One great example of this Eve is https://mega.nz - by design their servers never have access to the encryption key for any uploaded file, and files are shared by including said key in the hash of the URL. This is done for perfect legal deniability of any material on the site. As long as you trust Mega to not alter their code (you can defend-in-depth against this with various methods, including running an open-source client), and you send sharing links only to trusted parties, the content of your data cannot be detected.
As others have posted, JS is much more than script tags in the browser. There's also React Native, Electron, Node, and many other less well known platforms for JS outside of the browser.
Additionally, browser E2E encryption depends on trusting the provider just as WhatsApp or iMesssage depend on trusting Facebook or Apple.
The browser is really just another delivery mechanism for code that runs on the client and you can verify the hash of code delivered from the server just as you can with desktop or mobile apps. All E2E encrypted apps will require some trust from the author except when they are open source and you can verify the hash.
At a minimum, the E2E could be viewed as a best-attempt at security and would provide protection against information becoming exposed in the event of a database breach.
EDIT: To be clear, the browser is a code distribution platform, just like the App Store. Both the browser and App Store can distribute both closed and open source apps, and both closed and open source apps can securely implement E2E encryption. In both cases you placing trust in the author of the code, except in the case that it is both open source AND you verify the checksum, in which you can be reasonably secure that you know exactly what code is running.
> EDIT: To be clear, the browser is a code distribution platform, just like the App Store.
Not exactly the same, and the difference is important.
An iOS app is an iOS app is an iOS app: every user gets the same app. Malicious updates to bonafide releases cannot be targeted to specific users and will be distributed to everybody. Same for playstore.
A browser effectively requests an update, directly, every single time the app is started.† Updates can be targeted very precisely, both to a time and a user.
Circumventing this difference is not a detail, and eliding that when talking about browsers, honestly, implies regular use. Including the behaviour described above.
† An exception is a trick using web workers and github which appeared on HN a while back. That was an actual novice use for JS crypto.
The only case that obfuscating code from the user is useful for is DRM. That's not what end-to-end encryption is about. End-to-end encryption is about allowing two users to send messages to each other using keys of users that each user owns on their own device, so no server in the middle can eavesdrop. That use-case isn't impacted by each user being able to reverse-engineer the code they're running. It's probably better if the code they're running is open-source so they can possibly verify it or get someone else to verify it for them.
That doesn't make it any less secure, there are plenty of open source cryptography libraries and apps like Signal. Closed source doesn't equate to secure.
Crypto happening in the browser (or any browser-based “app”) is not ever going to be ok from a dozen different security perspectives. That makes Node the only possible platform where it makes sense, and that’s what I said.
> is not ever going to be ok from a dozen different security perspectives.
What dozen perspectives?
> Any of the other examples can easily be decompiled or reversed.
reply ... I don’t think I said any of those things?
Sorry, I interpreted "decompiled or reversed" as insecure. I'm curious why there's a problem if the frontend code can be reversed? Or another way to ask this is, how is that any different from an open source app?
> I keep asking, what is the threat model for end-to-end encryption in JS?
Even if there were no specific attack vector guarded by client side encryption, others reasons for JS-/client-side encryption may exists.
I could imagine some legal reasoning like 'The data was already encrypted when the client stored it on our servers, we had not knowledge of the illicit content.'.
For a share-hoster that alone might be reason enough to feel the need for JS-/client-side encryption.
You are right, you'd still have to trust the webmail/chat provider if you want to chat securely. Tanker still protects against data leaks from the app servers in this case.
We also provide SDKs for Android and iOS. They protect against more threats as you can install an app you know the provenance and the app doesn't auto update like a website that you reload every time you open your browser. If you are concerned about security, you could even compile the apps yourself in this case.
You can either see it as weak, best-effort security against accidental data leaks and such.
Or you can follow the mega model where the hoster wants to protect itself from legal demands of monitoring user uploads that stop short of demanding encryption backdoors.
It is a fairly weak and narrow security model. Nothing that should be used if you need serious security against powerful attackers.
It might be great as an alternative to a "we store all data encrypted, pinky promise!" type of model, where eg you encrypt all messages on the backend before storing it in the DB, to reduce the potential impact of breaches, rogue employees, etc.
I kind of like it for that, to be honest. There's a difference between trusting the good intentions of a company as a whole, and the good intentions and flawless skill of every single employee of it and it's subcontractors.
I wonder if there's something about this approach that I'm missing.
Ask HN: wouldn't you prefer that your data is browser-JS e2e encrypted than server-encrypted or not encrypted at all? In the context of "this is a web app. There's no mobile app or desktop app".
I'm specifically talking about the (rather common?) case in which your threat model does contain morally misguided employees, black hat hackers and stupid mistakes, but not nation state level adversaries.
I think one issue is that for anyone with a cryptography/information security background "e2e encryption" evokes a very strong security claim where you treat the whole service provider as potential eavesdropper against which the protocol protects you, only conditional on mathematical proofs.
Carving out a much more complicated boundary around various kinds of lapses on the other hand muddies the water. It can still make sense, but it is difficult to convey that clearly. More than a pinky promise, less than certifiable security.
Also I would claim that black hat hackers could very well get into your production system and just inject some JS that exfiltrates cryptographic keys from users. It's blunt and far more easily caught than a targeted attack, but it can still possible and thus the system would fall short of that threat model.
You assume the client side code is served by the middleman. But it can also be a browser based "app" that is loaded from the hdd. Unfortunately Chrome et.al has taken a step away from this model and deprecated app manifest (? cant remember the proper name) in favour of the more convenient service worker that is able to push updates in the background. Serverless/offline web apps didnt really take off. Theres ChromeOS and FirefoxOS for feature phones. But "web apps" for desktop are currently nw.js/Electron apps. It would however be just fine to use the local browser and not ship an entire browser with the web app. Most browsers allow "chromeless" mode (without address bar etc). But there needs to be a more relaxed security mode when running code as an app. Because its almost useless now with CORS and some features requiring SSL which you cant have when loading from hhd.
Prevention of passive monitoring by commonly installed SSL interception boxes in corporate environments. This is something I would consider if I was designing a app where users complain about their employers for example. Won't stop a state level agency but it will stop the average sysadmin dead.
Cloudflare is an extremely-common service that does SSL-interception on tons of websites.
If I hosted a website (with some kind of user-messaging functionality) on Cloudflare, and I trusted Cloudflare to not modify the data that went through them, but I was worried that they may be recording all the data that went through them, then using a javascript end-to-end encryption library would be perfect for my case.
You can use subresource integrity in the script tag which uses a sha hash to confirm the script is what is designated in the html. However, the html could be changed in transit so the only real way this can work is if you do that AND expose the sha hash to the user who has the last known valid sha hash locally that they can manually check against. It's not pretty, but it works.
There are two clear scenarios where this makes sense:
1. When the client code is content-addressed, and that content addressing is enforced by the browser
e.g. https://ipfs.io/ipfs/Qmfgh... with browsers supporting dweb protocols natively as Firefox is working on
2. When the web ui is served over localhost from an app you've downloaded and can independently verify. This could be a local only app, or it could be a p2p app.
It could be useful in a scenario where you trust the service provider to provide a legitimate encryption implementation.
If I trust Eve to provide an E2E service, in the same way I trust Whatsapp (not a given by any means), then an open source implementation of those tools lowers barriers to entry. That's a mixed bag in that it potentially enables bad security models, but overall I think access to tools is a good thing
Download (and check the hash, like any other application) a static one page "app" that you can open anywhere later and use to communicate/post information from any network you happen to be at?
The issue with client-side, in-browser encryption is that you cannot audit or trust the software. Without fingerprinting/certification of the entire javascript-source the server could serve a manipulated source code that exfiltrates data, targeted only at specific users, i.e. not the auditors. Think NSLs or sufficiently crafty industrial espionage. CSPs do not save you here.
You can't TOFU in-browser JS, you can't trust audits and if any 3rd-party code is loaded into the environment you can't trust the entire origin.
Innovator - To help me ride my bike on dangerous mountain trails, I made a sturdy frame and fat, knobby tires.
HN - The bike is the wrong tool for transportation in mountains. For absolute safety you must only use a cable car or funicular.
Innovator - But cable cars and funiculars are impractical for the mountain trails I want to ride, and my current road race bike with weak frame and skinny tires is dangerous off-road.
HN - A sturdy frame and fat, knobby tires only provide the illusion of safety, which is worse than no safety at all. Never go to the mountains unless you're in a cable car or funicular.
Innovator - To help communicate with other HN readers, I created an analogy about mountain bikes and their tire size!
HN - Not a good analogy to compare tire sizes for mountain biking to information security in Javascript. You should be comparing bicycle locks.
Innovator - My analogy still makes sense though? Consider my physical safety to be roughly equivalent to information security. While bike locks could certainly work for the analogy as well they just weren't the choice we decided to go with.
HN - Your analogy falls apart with edge cases X, Y and Z', bike locks have been used for analogies since.....
Subresource integrity can help a bit. You still need to bootstrap from a trusted source though (eg a minimal index.html stored locally). And at that point, you really are back to figuring out a way to distribute a "known good" piece of software.
Ed: it might, for example be easier to email an attached minimal html file, than a 50mb electron app (multiply by 5 for working on the five major platforms; windows, Linux, Macos, Android and ios). That email might be internal, or signed however you usually sign mails (gpg, s/mime). Or you could host it on a minimal, secure webserver that only served static files over ssl etc
A known good entry point could be delivered over a content-addressed medium like IPFS, and if you layer on SXG the consumer might still be able to validate the origin of the entry point.
CSP would only be necessary if the SRI-covered stuff had bugs that let it accidentally load unverified resources. (To be clear, I think CSP is a necessary defense-in-depth measure for everyone, but this case doesn't uniquely require it.)
This is FUD. That's nothing you can't say about all info security practice. Fingerprints and certs you say? Been done since forever, it's called SSL and SHA-2.
There are risks, and there are procedures for mitigating risk. If you're building an app for privacy and security, you are going to take the appropriate measures, and let your users knows how to use. For instance, you are not going to load some random 3rd party adware into the app, obvi.
At the end of the day, people have to combine a care for their security with available best practices, and then move on with life. People can't thrive in the either/or of infosec's paranoid-hermit mentality (and tech's "people can't understand" paternalism).
Part of that is because by the time you're asking an ordinary user (not a super-opinionated "sophisticate" on HN) to install a Chrome extension, you're 95% of the way towards getting them to install a desktop application anyways, and that remaining 5% of effort is often worth the extra flexibility the Electron app gets you.
This is what the webext-signed-pages [1] extension does. This only works in a secure manner with Firefox though because Chrome extensions don't have access to the content of the HTTP responses [2].
You need the opposite of an extension, because in-browser crypto is incompatible with having any other "untrusted" extension. What you need is something with a reduced but secure feature set.
Ideally, it would be something the browser supported internally (without external js or plugins) with very minimal javascript entrypoints to decode/encode.
> The issue with client-side, in-browser encryption is that you cannot audit or trust the software.
I agree. A few months ago I experimented on ways [1] to automate side-channel verification of JS bundles (and other built assets) while linking them to the sources.
It's based on trusting both the public CI/CD server (to reproducibly build the sources as they are obtained from the repository) and the public repository provider (to serve everyone the same sources), which in a FOSS environment is a given (if services like GitHub and Travis are in the threat model, there's not much to be done). It was a PoC/WIP, but it seems there might be a use case for side-channel verification.
The threat models for this kind of "mistrust" in built assets (assuming traceability and transparency) would be:
- Any kind of MitM (proxy/cache/load balancer) in the path of the assets
- Hosting provider being compromised (unlikely but still a probability)
- Malicious external content being injected at runtime (XSS, CDN)
I'm surely missing more, and I'd love to discuss at lengths about what others may have setup to do side-channel verification (ie: when even TLS and/or the CA chain of trust can't be trusted).
Even doing it on a CLI doesn't help since the server might deliver something else to the browser.
And if you have dynamically generated HTML then you can't really authenticate it either.
To trust an application need in-browser fingerprinting of the whole page as it was served to the user and then pin that fingerprint. Combined with fairly strict CSPs.
Also, how do I trust the revelio.json? There's no signature.
> Even doing it on a CLI doesn't help since the server might deliver something else to the browser.
That is indeed one of the hurdles I encountered, ideally the browser itself should be in charge of verifying these claims (resource integrity helps in this case).
> And if you have dynamically generated HTML then you can't really authenticate it either.
In the case of SSR/PHP/other means of backend-generation of HTML, yes. I initially limited the PoC to SPAs and deterministic JS bundles.
> Also, how do I trust the revelio.json? There's no signature.
For now, as I said it's a work in progress, but indeed a way to authenticate the tamper-proof properties of the manifest is necessary. This however brings up the issue of a chain of trust, which is what apparently Tanker is trying to provide with their product. Yet, it raises the question: why should they be trusted ? The commercial viability argument (we don't screw up to stay in business) is not enough IMHO, trust should be based on mathematical proofs, not business rules.
In theory it's possible, sure. But in practice webapps are not set up for reproducible, auditable, signed builds with zero dynamic execution of 3rd-party code and making those signatures available in a standarized format. Plus browsers lack the tools to make this kind of fingerprinting effortless to verify for the user.
Sure, but how often do users do this in practice for any apps? I know I don't check the fingerprints for Signal or WhatsApp or iMessage on my phone.
And even if the actual binary I'm running is secure, plenty of apps that claim to provide E2E encryption don't give me any way to verify the key of the other user. How do I know that iMessage or Facebook Messenger aren't inserting their own key pairs me and the people I'm messaging?
Usually the first thing I check in a project like this when it ends up on HN or Reddit is their symmetric cryptography features. Not because of any particularly scientific reason, but because it's a good heuristic on whether or not it's worth the time and energy to look at the rest of the code.
> It would be nice if Tanker exposed the cryptography operations, so it could be a more re-usable library. Is this possible?
Tanker is more of a high-level library. It focuses on the ease of use, and tries to be hard to misuse, so it does the key handling and uses fixed algorithms.
We started the implementation after the Snowden revelations, tied to a web messaging platform called PEPS but after the sale of the company we realized that most of the value lied in the E2EE SDK itself, and not the messaging app.
We got there as many prospects were interested in the encryption part, but did not want yet another messaging platform.
I am still unsure about the market for this (disclaimer: I am no longer at Wallix, so I am not involved anymore with DataPeps although I created it). It was a tough sale, even as a part of an existing company with hundreds of customers. Many people felt the need for privacy, but were not ready to implement a new product or to involve developers to modify an existing product.
I do feel though that there is a need for a truly, non-profit, open source solution that handles E2EE. It would be highly beneficial for the whole developer ecosystem.
The DataPeps SDK (MIT license) is a good start. The accompanying service is currently proprietary.
Your website and documentation is all a bit opaque.
The title reads like a new encryption library for in the browser but in reality is an (advert for) encryption service, the SDK is open source because it requires your backend with its "Trustchain", the wording on the website is vague about how the Trustchain Private Key is "obtained".
Regarding the service, my main issue is that with an open source SDK you're aiming at a certain type of people, developers, like many of us, but I see no mention of the algos used which immediately causes me to lose interest (between that and the sales/marketing heavy website). If you're really targeting developers I would suggest losing the marketing babble and get down to brass tacks.
And finally, if the private key really is generated on your service, we can just pack up and go home.
What it sounds like you have is a PKI infrastructure with open source SDK and "end-to-end" encryption of things, as much as end-to-end applies for keys/trust roots generated anywhere but locally.
The Trustchain private key is generated when you create a Trustchain. It is generated on your machine. You can try it and create a Trustchain yourself here: https://dashboard.tanker.io/
> And finally, if the private key really is generated on your service, we can just pack up and go home.
It is not :)
> What it sounds like you have is a PKI infrastructure with open source SDK and "end-to-end" encryption of things, as much as end-to-end applies for keys/trust roots generated anywhere but locally.
That's pretty much it. The trust root is that Trustchain key, and Tanker never sees its private part.
> Regarding the service, my main issue is that with an open source SDK you're aiming at a certain type of people, developers, like many of us, but I see no mention of the algos used which immediately causes me to lose interest (between that and the sales/marketing heavy website). If you're really targeting developers I would suggest losing the marketing babble and get down to brass tacks.
I take note of this. The parts targeted at developers available at the moment are the documentation, the code examples, and the SDK sources. We will write and publish something that explains how it works under the hood.
>And finally, if the private key really is generated on your service, we can just pack up and go home.
Yeah, thankfully that key is generated client-side (in the browser) when you register. Seems pretty end-to-end to me.
(And sure, you could always worry that the server will serve you malicious JS while you're registering to steal your client-side-generated key, but that would be pretty suicidal for any company, not a very realistic threat!)
Knowing only you have access to tha data is a good thing. For example, we are able to host our internal employee feedbacks and reviews on our own forms without worrying about a sysadmin or database admin having access to it.
I understand the concerns about client side manipulation but that is hard to do without leaving a trail on our code commit history. Both system and product changes can only be done by code commits.
You cannot protect systems with a single perfect security solution. You have to be paranoid and have many layers in your security model. This may not be the silver bullet, but this greatly enhances the security.
> If you want your app to be fully end-to-end, you can use the lower level
> unlock mechanisms, which are all end-to-end compliant
So if I want to use the SDK in a "fully" end-to-end secure way, I first need to implement by myself a secure way to transmit the user root secret (the unlock key) between the user's devices, and make sure this key is always accessible so that users don't loose access to their data. This doesn't seem like an easy task...
No, the unlock key is for the user to keep, and never be transmitted by anyone else than the user themselves. If you do the transmission, it's not end to end anymore.
This option is only for users concerned about security, the other unlock methods are less strong but still provide security.
If it is under Apache 2 license as the repo claims, very few commercial projects are going to have an issue with using it under the open-source terms. You can't say "this is open-source under license X, but you can't use it commercially!" (well, you can, but you are creating your own license that's not compatible with open source projects either). Qt solves this by being under license(s) not all commercial users want to comply with, and selling support etc.
It seems what they are selling is not the software, but services it can use to manage exchange between users etc.
They can legally use the SDK under the open source terms without paying if they find a way of using it without Tanker's servers. For the server access, they need to pay, thus that's what they're selling.
In contrast Qt is selling licenses to the code, not access to a hosted service.
E2E encryption in JS in browser will never be secure. In a client with shared threads and untrusted content on the page it will always be vulnerable to timing attacks. It's unrealistic to create a constant-time implementation in JavaScript.
For node/backend this is great but please don't use it on a public site.
Hadn't heard of it actually, but side channels have been an issue in browser security for a long time.
Spectre caused a lot of changes in JS like disabling high precision clocks. But I'm afraid clock proxies are everywhere. The API surface is gigantic and all you need is a single call that reliably executes in constant time on the samr thread
Tanker developer here. We use libsodium as our underlying cryptographic library. It uses XChacha20/Poly1305 for symmetric encryption, Curve25519 for asymmetric encryption and signature, and Blake2 for hashing.
TweetNaCl is roughly equivalent to libsodium, on which Tanker builds. Tanker is easier to integrate into your app because it takes care of key sharing, multi-devices, user group managment, etc. These are all things you would have to handle by yourself using just a cryptographic library like TweetNaCl.
Can you describe (briefly, in plain english) how it is able to securely encrypt on the client side? i.e. how does it hide its secret key from prying eyes?
The keys are generated client-side, and encryption is done client-side, the encrypted data is then sent to the app. On sharing, the key is encrypted for the recipient and sent to them through the Tanker server.
Neither Tanker nor the app can see the clear data or keys.
This really does answer the question, spot on. The client side app does see the key(s) but it does not send them to the server. This is how E2E encryption works, browser or otherwise.
I'm not sure specifically how Tanker is storing the client-side keys. Generally the client-side keys would be encrypted using an OS-level keychain.
Hi, other Tanker dev here. In the browser, we use IndexedDB (via dexie). Keys are encrypted using a secret that has to be provided when starting a Tanker session.
On mobile we use an SQLCipher DB encrypted with the same secret.
The canonical example that doesn't make sense is when Alice and Bob want to communicate privately using Eve as a webmail/chat provider who wants to snoop in on the communications. Alice and Bob can't just trust Eve to provide a copy of E2Ejs in a <script> tag on EveMail.com, because then they're trusting Eve to provide a legitimate encryption implementation, trusting Eve not to log their keystrokes in JS, etc.
I can understand E2E js as a server-side library in Node (though I suspect it would be safer to run a battle-hardened library like GPG with node FFI).
But, in client-side web code, how could this ever make sense?