1Password uses a multi-layered approach to protect your data in your account, and Secure Remote Password (SRP) is one of those very important layers. Today we’re announcing that our Go implementation of SRP is available as an open source project. But first, I’d like to show you the benefits SRP brings as an ingredient in the 1Password security parfait.
- Parfaits: delicious and secure
- SRP: a hell of a layer
- How 1Password uses SRP
- Implement SRP in your own app
Donkey: Oh, you both have layers. Oh. You know, not everybody likes onions. Cake! Everybody loves cake! Cakes have layers!
Shrek: I don’t care what everyone likes! Ogres are not like cakes.
Donkey: You know what else everybody likes? Parfaits! Have you ever met a person, you say, “Let’s get some parfait,” they say, “Hell no, I don’t like no parfait”? Parfaits are delicious!
Parfaits: delicious and secure
The first layer of security in 1Password, your Master Password, protects your data end to end – at rest and in transit – but we wanted to go further. The second layer is something we call Two-Secret Key Derivation. It combines your Secret Key with your Master Password to greatly improve the strength of the encryption. Thanks to your Secret Key, even if someone got your data from our servers, it would be infeasible to guess your Master Password.
That still wasn’t enough for us, though. When we first started planning how we were going to securely authenticate between 1Password clients and server, we had a wish list. We wanted to ensure that:
- your Master Password is never transmitted or stored on the server.
- eavesdroppers can’t learn anything useful.
- the identity of user and server are mutually authenticated.
- the authentication is encryption-based.
There was actually one other requirement that wasn’t exactly part of the list but applied to every item in the list: we didn’t want to roll our own solution. We know better than to roll our own crypto, and we wanted to find a proven solution that’s been around and has stood the test of time.
We wanted this layer to be just right.
SRP: a hell of a layer
It took us a while to find what we needed for this layer. (Apparently the marketing department of augmented password-authenticated key agreement protocols is underfunded.) But we eventually found SRP, which ticked all our boxes. SRP is a handshake protocol that makes multiple requests and responses between the client and the server. Now, that may not sound very interesting – and I’m not one to show excitement easily – but SRP is a hell of a layer. With SRP we can:
- authenticate without ever sending a password over the network.
- authenticate without the risk of anyone learning any of your secrets – even if they intercept your communication.
- authenticate both the identity of the client and the server to guarantee that a client isn’t communicating with an impostor server.
- authenticate with more than just a binary “yes” or “no”. You actually end up with an encryption key.
All this makes SRP a great fit for 1Password, and it keeps your data safe in transit. As an added bonus, because SRP is encryption-based, we end up with a session encryption key we can use for transport security (the fourth layer) instead of relying on just Transport Layer Security (TLS).
So that’s four layers of protection for your 1Password account: Master Password, Secret Key, SRP, and TLS. Now I’d love to show you how SRP works step by step in 1Password.
How 1Password uses SRP
Before any authentication can be done, the account needs to be enrolled. 1Password does this when you create an account. To use SRP, you’ll need a couple different things:
- a key derivation function (KDF) that will transform a password (and, in our case, also your Secret Key) into a very large number. We’ve chosen PBKDF2.
- an SRP group consisting of two numbers: one very large prime and one generator. There are seven different groups; we’ve chosen the 4096-bit group.
To enroll, the client sends some important information to the server, and the server saves it:
- The client generates a random salt and Secret Key.
- The client asks the user for a Master Password.
- The client passes those three values to the KDF to derive x.
- The client uses x and the SRP group to calculate what’s called a verifier.
- The client sends the verifier, salt, and SRP group to the server.
- The server saves the verifier and never transmits it back to the client.
Now the account is ready for all future authentication sessions.
To authenticate, the client and server exchange non-secret information. Then the client combines that with a secret that only it knows and the server combines it with a secret only it knows:
- The client requests the salt and the SRP group from the server.
- The client asks the user for the Master Password and Secret Key.
- The client passes those three values (minus the SRP group) to the KDF to derive x.
- The client:
- Generates a random secret number a.
- Uses the SRP group to calculate a non-secret counterpart A.
- Sends A to the server.
- The server:
- Generates a random secret b.
- Uses the SRP group to calculate a non-secret counterpart B.
- Sends B to the client.
So A and B are exchanged, but a and b remain secrets. Through the power of math, the client (with x, a, B) and the server (with the verifier, A, b) can both arrive at the same very large number using different calculations. This is the number that 1Password uses as a session encryption key.
The last step is verification. After all, no amount of fancy math will help if the numbers don’t match up between client and server.
To verify, the client and server exchange encrypted messages:
- The client encrypts a message with the session encryption key and sends it to the server.
- The server decrypts the message and verifies it.
- The server encrypts its own message with the same session encryption key and sends it to the client.
- The client decrypts the message and verifies it.
If the client and server both used the correct inputs then they’ll both have the same session encryption key, which allows them to decrypt and verify the message. If they don’t use the correct inputs, everything fails.
The verification process proves to the server that the client has x, which can only be derived using the correct Master Password and Secret Key. It also proves to the client that the server has the verifier, which ensures that the client is communicating with the 1Password server, not an impostor.
Now that it has been verified, the session encryption key can be used to encrypt every message between the client and server going forward.
As you can see, it’s critical to remember your Master Password and keep your Secret Key safe if you ever want to authenticate your 1Password account. They’re also very important layers, after all. 🙂 And, like any good parfait, everything comes together to create something better than the individual layers alone.
Implement SRP in your own app
We love SRP so much that we want to see it used in more of the apps we use. That’s why we want to help you get started with SRP in your own project. Our Go implementation of SRP is available as an open source project:
This package provides functions for both clients and servers, and you only need to BYOKDF (Bring Your Own Key Derivation Function, like any good party). It’s the same code we’re using on our server and in the 1Password command-line tool, so we welcome security researchers to take a look and report any issues through the 1Password Bugcrowd bug bounty program.
SRP is one of the less appreciated parts of 1Password, and I hope I’ve explained it well enough for you to implement it in your own project. You can read more about how we use SRP in the 1Password Security Design White Paper. Leave a comment if you have any questions, or file an issue if you see something that can be improved.
Until next time, enjoy that parfait!