TeddyID Password Manager Technical Description

This is a technical description of how our password manager works, for those who understand cryptography and want to know what's under the hood.

Using our browser extension or 1.5 factor authentication requires having an account at teddyid.com. Users are identified and authenticated by two factors: browser cookie and TeddyID mobile app. Each user account can be associated with multiple browsers and only one instance of the mobile app.

Each browser holds a private RSA key, it is stored in the local storage against our domain. The app also holds a private RSA key. These keys are used for exchanging other keys (see below) among browsers and the app. The private key stored in the browser is AES-encrypted, and the encryption key is stored on our server and delivered to the browser only when needed.

User passwords are encrypted on an AES key (password encryption key — PEK) stored in local storage. Each browser and the app hold a copy of this key. Ciphertext of the password is stored on our servers. To copy PEK to another browser or the app, PEK is RSA-encrypted with the public key of the destination device (browser or app) and sent through our servers. Hence our servers never see PEK in clear text and are unable to decrypt it.

Browser stored PEKs are additionally encrypted with an AES key unique for each browser and user. Only encrypted PEK is stored in browser's local storage, and the encryption key is stored on our server and delivered to the browser when it connects to our server. If user loses his laptop, he can disable all browsers on that laptop in browser control panel, then we'll destroy the corresponding PEK encryption keys in our database and unpair these browsers from the user account.

All browser keys (RSA and PEK) are generated in the browser seeded by entropy delivered from our server (there aren't good cross browser PRNGs in javascript).

The browser extension injects our javascript into each page and that javascript tries to find login/signup forms. This javascript then communicates with an iframe that is loaded from our domain (hence has access to the local storage that stores the private key and encrypted PEK) which in turn communicates with our server via ajax requests. All encryption/decryption is done in browser within iframe loaded from our domain. No encryption keys are copied to the site's page.

If user enters a new password and agrees to save it, we encrypt the password with PEK and send ciphertext to our server. When user wants to use this password, we pick a random picture and send it both to his browser and to his app, user makes sure the pictures match, taps "Yes" on the phone, we send password's ciphertext to the browser, the browser decrypts it with PEK, fills it into the password field and submits the form.

Each new browser is paired to user account by scanning a QR code with the app and confirmed by email (if available). This is done only once for each browser (unless user clears his cookies).

This is a high level description of how we secure users' passwords. You can learn more by reading our source code https://www.teddyid.com/js/teddypass.js (works on site's page) and https://www.teddyid.com/js/teddypass_server.js (works in iframe loaded from our domain), which we intentionally keep unobfuscated and unminified.