In recent years, web applications that utilize client-side cryptography (or ‘in-browser’ cryptography) to protect users’ private information have become increasingly prevalent. Examples of such applications include end-to-end encrypted chat/email/messaging services, cryptocurrency wallets, encrypted cloud file storage/sharing services, and many more. Perhaps one of the most widely-used applications to leverage in-browser cryptography is the encrypted email service Protonmail.
Many browser-crypto applications claim that because all of the cryptography is done on the client-side (in the web browser), and only ciphertext reaches their servers, the operators of these applications have ‘zero-access’ to users’ private information. For example, see Protonmail’s claim here.
In essence, the ‘browser crypto chicken-and-egg problem’ can be summed up as follows: if you can't trust the server with your secrets, then how can you trust the server to serve secure crypto code? One could argue that a rogue server admin (or an attacker that has gained access to the server) could maliciously alter the browser-crypto code served by the server, such that the code captures the user’s private keys or plaintext information, and sends these secrets back to the server (or somewhere else). Ptacek argues that browser-crypto applications cannot legitimately claim that they have ‘zero-access’ to their users’ private information, because the operators of these applications can simply alter their browser-crypto code any time, and capture the users’ secrets.
In the desktop software world, users are able to protect themselves from threats stemming from tampered-with files, by cryptographically verifying the integrity of files before opening or running these files. After downloading a file, but before opening or running the file, there is an opportunity for the user to verify that the checksum hash of the file matches an expected checksum, or that a digital signature on the file was made by a trusted signer. If this verification fails, then this is an indication that the file has been changed since the expected checksum was taken, or since the file was signed.
But, in a typical web application, there is no (practical) method for the user to verify the integrity of a web page containing browser-crypto code. The page is served, then the page is immediately rendered by the browser, then browser-crypto code in the page is executed as the user interacts with the page. To make matters even more complicated, new pages are continuously served in place of previous pages as the user interacts with the application; and often these pages are dynamically generated by the server. Clearly, this model does not lend itself well to providing users with a practical way of verifying the integrity of the browser-crypto code in these applications.
We propose a two-pronged solution to the ‘browser crypto chicken-and-egg problem’.
First, instead of the traditional model for web applications, where new dynamically-generated web pages are served in place of previous pages as the user interacts with the application – we propose that browser-crypto applications should be designed using the Single Page Application (SPA) model, where a static web page is served at the beginning of the user’s session, and this static page remains loaded in the user’s browser throughout the user’s session. This page (and/or its dependent files) should contain all client-side crypto code needed to support all in-browser crypto operations throughout the user’s session. Requests are sent from the static page to the server by way of AJAX or XHR calls to the server, and the static page is updated with the server’s responses to these calls.
This design, based on the SPA model, with a single static web page that remains loaded in the user’s web browser throughout the user’s session, allows for the expected checksum hash of this static page to be known in advance, and allows for the static page to be digitally signed by one or more signers. This allows for the integrity of the static page to be verified at the user’s end, after the page is served, but before the user begins to interact with the page.
The second prong of the solution is the Page Integrity browser extension. The Page Integrity extension was developed to enable the user to verify the integrity of the static page, as described above. With the Page Integrity extension loaded in the user’s web browser, the integrity of the static page can be verified by the user immediately after the page is loaded, before the user begins to interact with the page. Page Integrity can be used to display the checksum hash of the static page, so that the user can verify that it matches the expected checksum. Or, Page Integrity can be used to verify that the static page was digitally signed by a trusted signer.