Our Zero-Trust Infrastructure

Published on August 30th, 2018

Krypton is an app that turns your phone into a U2F Authenticator.

Unlike most U2F authenticators that are standalone hardware fobs that you can plug into your computer via USB, Krypton provides the convenience of completely wireless, zero-friction use: you get a push notification that requests your approval to sign-in.

To achieve this user experience, Krypton has a companion browser extension that you install in Chrome, Firefox, Safari or Edge (coming soon). This extension securely communicates registration and authentication requests from the web page to your phone. Upon your approval, the phone communicates back the cryptographic signature required to sign you in.

In this post we dive into the details of how the Krypton app pairs your phone to your browser to guarantee secure communication.

The Krypton app and the Browser extension

Krypton phone app

The Krypton phone app, referred to as “Krypton” in this post, generates and stores your private U2F key pairs on the secure hardware on your iOS or Android phone (where available) and uses it to sign U2F authentication and registration challenges. The private key never leaves the phone.

Browser extension

The browser extension is responsible for carrying out the U2F protocol with the web page you’re on and most importantly, securely communicating the origin of the page you’re on (the domain) to the Krypton app. The browser extension forwards U2F signing requests to the Krypton app on your phone which, upon approval, returns the signature back to the web page for authentication.

Communicating over an Untrusted Channels

Pairing establishes an authenticated and encrypted communication channel over an untrusted medium.

When the extension asks Krypton for a signature, this request must be (1) authenticated to ensure that it is coming from an authorized browser and (2) encrypted to hide sensitive data like where you are authenticating and the actual U2F signature.

The browser extension uses several untrusted communication channels to talk to the Krypton app on your phone:

AWS SNS is a service for delivering push notifications, utilizing APNS (iOS) and Firebase (Android) under the hood. The extension embeds underling encrypted, authenticated Krypton requests inside these push notifications. Authentication request messages are sent simultaneously on all channels to maximize performance.

Pairing Protocol

Browser Pairing

First, the user initiates pairing on the browser extension. The extension generates a new key pair for this new pairing and displays the public key in a QR code. The user scans the extension’s QR code with the Krypton app.

Krypton Pairing Protocol

1: Getting the extension’s session public key

Scanning the QR code is the only communication mechanism assumed to be free of tampering. The QR code is NOT assumed to be confidential, it only contains a public key.

2: Sending Krypton’s session public key

s_pub_key is encrypted under c_pub_key to prevent an active adversary from switching out s_pub_key to another public key. An adversary would have to know c_pub_key to be able to insert its own public key. This creates a race: the extension only remembers and responds to the first Krypton client to send the message in step (2). The next step allows Krypton to confirm that the browser extension paired with it and not any other client.

3: extension_hello

If some other client completes step (2) first, Krypton will timeout while waiting to receive a extension_hello. In the case of a timeout, the user would be told to try again. They would pair again by re-initiating the pairing process which would cause both the app and the extension to generate new session key pairs.

4: krypton_hello

The browser extension is now paired to the Krypton phone app. Key pairs have been established, that only the extension and Krypton app know and public keys securely shared for encrypted, authenticated communication.

Secure Communication Protocol

When the user navigates to a page that requests a U2F operation, the following protocol is initiated by the browser extension.

  1. The request body is the U2F protocol request and includes the challenge data that needs to be signed as well as any additional meta-data needed by Krypton like the application id (website origin). The extension packs these items, along with a random request_id and the current time unix_seconds, into a sign_request that is encrypted and signed, and sends it to the Krypton app.

  2. Upon receiving sign_request, the Krypton app asks the user for their approval (if needed). The approval request body tells the user which web site is requesting this authentication.

  3. If the user rejects, the Krypton app simply sets sign_response to a rejection constant. If the user approves, Krypton performs a signature using the data in the body per the U2F protocol specification.

  4. As shown in step (4), sign_response is encrypted and signed and sent back to the extension. Upon receipt of the sign_response, if the browser extension receives a signature, it passes it back to the authentication hook to complete the login.

Note that for some user-set policies, requests can be auto-approved to require user interaction.

U2F Registration body

The extension forwards U2F registration protocol request challenge data from the web page to the Krypton app inside the body field above. If the user approves the request, Krypton generates a new NIST-P256 U2F key pair and returns the U2F public key along with the signed challenge to the extension.

U2F Authentication body

The extension forwards U2F authentication protocol request challenge data from the web page to the Krypton app inside the body field above. If the user approves the request, Krypton loads the corresponding U2F key pair and uses the key to create a signature to return in its response to the extension.

Cryptographic Libraries

For the public-key cryptography primitives in the protocols discussed above, Krypton utilizes libsodium. The encrypt_and_sign primitive corresponds to libsodium’s Authenticated Encryption algorithms and the encrypt primitive corresponds to libsodium’s Sealed Boxes algorithms.