1Password - Unlocking Windows Clients
I’m taking a detailed look at how 1Password works, originally to help examine potential risks when used in a corporate environment, and eventually because I’m just a nerd and love All Things Crypto. (See this page for an introduction and background).
Last time, I explained how the 1Password Two-Secret Key Derivation Process (2SKD) works. Briefly, it takes your email address, master password, and secret key, along with a couple other parameters, and derives a strong Master Unlock Key or MUK.
That MUK then decrypts the “master key” or “mk” for the primary account on the client, which then begins the process for decrypting that account’s data vaults. The mk is also used to unlock the mk for any additional accounts on that client, by unlocking specific entries in the “accounts” table.
That’s how it works on a Mac. Under Windows, things are a little different. I’ll talk about 1Password version 6 on Windows (I haven’t had a chance to upgrade my Windows VM to version 7).
Unlocking the Client
To unlock the Windows client, you need only one thing: the Master Password. This is (potentially) because it’s more difficult to safely store the account key on a Windows machine, or perhaps because this is the way it’s always been done and they simply haven’t updated the client to be more like the macOS approach. I’m really not sure.
Like on the Mac, the user’s master password is iterated through thousands of rounds of PBKDF2. But the number of rounds is not fixed, and actually is re-computed with every unlock. If it takes less than a second to derive the key, then the EMK is updated using a higher iteration count.
The result of this PBKDF2 step is not the actual key, however. It’s a little more complicated that that.
The Encrypted Master Key
In the “config” table is an entry for EncryptedMasterKey (EMK). This is a binary structure that includes two parts:
- EMK header
- opdata vault (a standard 1Password encrypted data format)
The header includes the iteration count and salt for the initial key-derivation step. The opdata vault contains the actual Master Key, which is then used to begin the decryption process. The Master Key is encrypted, using the key derived from the password. Hence, Encrypted Master Key.
EMK Structure
The header is composed of an 32-bit unsigned integer giving the number of iterations, another 32-bit integer providing the length of the salt, the salt itself, and then a 32-bit integer with the length of the following payload.
The payload is a standard encrypted format used by Agilebits throughout the 1Password system. It includes its own header: the string “opdata01” and a 64-bit integer giving the plaintext length. This is followed by the 16-byte initialization vector (IV), the actual AES-CBC encrypted ciphertext, and finally a 32-byte HMAC signature.
Because AES requires a fixed block size of 128 bits (16 bytes), the plaintext must be padded to bring its total length to an even multiple of 16. If it’s already at an even multiple, then a full new block of 16 bytes is randomly generated. Unlike most padding systems, however, this random padding is put at the front of the plaintext, rather than being added at the end. This helps to reduce the potential for padding-oracle and similar attacks.
To decrypt the opdata vault, we need the AES encryption key, and also the HMAC key. The HMAC key is used to generate a secure message digest, and is applied to the entire opdata structure (not including the HMAC tag itself). So the header (opdata01), plaintext length, IV, and Ciphertext, are all fed into the HMAC function using the HMAC key, and the result of this is appended to the end of the ciphertext.
When decrypting the vault, the HMAC key is used to re-generate the signature. If the signature doesn’t match the signature read from the end of the opdata vault, then it’s assumed that the ciphertext has been altered (deliberately or by accident) and the decryption fails before it even begins. If the signatures match, then it’s an indication that the ciphertext hasn’t been changed, and the decryption can proceed.
So we need two keys: a 256-bit AES key, and a similar 256-bit HMAC key, for a total of 512 bits.
Deriving the Encryption and HMAC Keys
Fortunately, we have a SHA function that produces exactly 512 bits. Remember, we feed the user’s password, the salt from the EMK header, and the iteration count (also from the header) into the PBKDF2 function. By using SHA-512 as the hashing function for PBKDF2, it generates 512 bits (or 64 bytes) of password-derived data. The first 32 bytes of the output are used as the AES key, and the second 32 bytes for the HMAC key. Here’s how it looks:
(you’ll see huge dumps like this frequently through this series. I’m trying to show raw data, highlight individual important bits, provide results of intermediate computations, and so forth. Again, the goal is to give you enough information that you can easily debug your own code, if you decide to play with the tech yourself. If you just want to see the results, look at the end of this big block.)
$ python do_emk.py
Enter EMK data (from config table) in base64 or hex: rPwIABAAAADBxTVJptTc4ShV-auZirBMkAAAAG9wZGF0YTAxQAAAAAAAAADpLFfPKxiEVt6v3fRJ-W6whU7c_zaO9b9q9UPgUQ7Q12LvjHq8-mImCneHxos4qw_jIC89Iz1BmMhWhcSdbvGlYx1XBdXhSDM2jz4h8_zCqDpjnDqUknDfHruv0gVTjPdY7fMXiPyETpHrM2NUZ2omyfFKSOeYsXdSN_c276HMVg==
Enter the master password:
Password: [update-clown-squid-bedpost]
*** EMK Structure from DB
RAW HEX acfc 0800 1000 0000 c1c5 3549 a6d4 dce1
2855 f9ab 998a b04c 9000 0000 6f70 6461
7461 3031 4000 0000 0000 0000 e92c 57cf
2b18 8456 deaf ddf4 49f9 6eb0 854e dcff
368e f5bf 6af5 43e0 510e d0d7 62ef 8c7a
bcfa 6226 0a77 87c6 8b38 ab0f e320 2f3d
233d 4198 c856 85c4 9d6e f1a5 631d 5705
d5e1 4833 368f 3e21 f3fc c2a8 3a63 9c3a
9492 70df 1ebb afd2 0553 8cf7 58ed f317
88fc 844e 91eb 3363 5467 6a26 c9f1 4a48
e798 b177 5237 f736 efa1 cc56
Iterations acfc 0800
Salt len 1000 0000
Salt c1c5 3549 a6d4 dce1 2855 f9ab 998a b04c
*** Encryption Key and HMAC Key, derived from password:
Raw derived key 5f5b a609 9b25 9989 8a32 9b52 638d 7149
3a9c 12c9 5353 9f34 3072 0afc b3f0 7014
71ed 9b82 1d30 515e e71d 5640 6747 84da
c9b3 63f2 8730 7983 541c a4a9 ddff 144f
Derived enc key 5f5b a609 9b25 9989 8a32 9b52 638d 7149
3a9c 12c9 5353 9f34 3072 0afc b3f0 7014
Derived hmac key 71ed 9b82 1d30 515e e71d 5640 6747 84da
c9b3 63f2 8730 7983 541c a4a9 ddff 144f
** Decrypting OPDATA structure
raw opdata 6f70 6461 7461 3031 4000 0000 0000 0000
e92c 57cf 2b18 8456 deaf ddf4 49f9 6eb0
854e dcff 368e f5bf 6af5 43e0 510e d0d7
62ef 8c7a bcfa 6226 0a77 87c6 8b38 ab0f
e320 2f3d 233d 4198 c856 85c4 9d6e f1a5
631d 5705 d5e1 4833 368f 3e21 f3fc c2a8
3a63 9c3a 9492 70df 1ebb afd2 0553 8cf7
58ed f317 88fc 844e 91eb 3363 5467 6a26
c9f1 4a48 e798 b177 5237 f736 efa1 cc56
Header 6f70 6461 7461 3031
PT length 4000 0000 0000 0000
IV e92c 57cf 2b18 8456 deaf ddf4 49f9 6eb0
CT 854e dcff 368e f5bf 6af5 43e0 510e d0d7
62ef 8c7a bcfa 6226 0a77 87c6 8b38 ab0f
e320 2f3d 233d 4198 c856 85c4 9d6e f1a5
631d 5705 d5e1 4833 368f 3e21 f3fc c2a8
3a63 9c3a 9492 70df 1ebb afd2 0553 8cf7
CT length (padded): 80
HMAC digest 58ed f317 88fc 844e 91eb 3363 5467 6a26
c9f1 4a48 e798 b177 5237 f736 efa1 cc56
Verifying HMAC tag
OPdata Msg 6f70 6461 7461 3031 4000 0000 0000 0000
e92c 57cf 2b18 8456 deaf ddf4 49f9 6eb0
854e dcff 368e f5bf 6af5 43e0 510e d0d7
62ef 8c7a bcfa 6226 0a77 87c6 8b38 ab0f
e320 2f3d 233d 4198 c856 85c4 9d6e f1a5
631d 5705 d5e1 4833 368f 3e21 f3fc c2a8
3a63 9c3a 9492 70df 1ebb afd2 0553 8cf7
HMAC key 71ed 9b82 1d30 515e e71d 5640 6747 84da
c9b3 63f2 8730 7983 541c a4a9 ddff 144f
Computed HMAC 58ed f317 88fc 844e 91eb 3363 5467 6a26
c9f1 4a48 e798 b177 5237 f736 efa1 cc56
HMAC signature verified.
*** decrypted opdata
Plaintext 7205 250f bddb 7663 1829 4b69 bf70 b01e
09db 23cf df4c 1ba6 be18 b910 aa11 75b5
ad14 d4fe 0938 f49f f283 28c9 3f9c 821a
6544 0753 b788 cc63 68b1 3b57 ae85 426b
Master Enc Key 7205 250f bddb 7663 1829 4b69 bf70 b01e
09db 23cf df4c 1ba6 be18 b910 aa11 75b5
(base-64) cgUlD73bdmMYKUtpv3CwHgnbI8_fTBumvhi5EKoRdbU=
Master HMAC Key ad14 d4fe 0938 f49f f283 28c9 3f9c 821a
6544 0753 b788 cc63 68b1 3b57 ae85 426b
(base-64) rRTU_gk49J_ygyjJP5yCGmVEB1O3iMxjaLE7V66FQms=
Enc+HMAC together cgUlD73bdmMYKUtpv3CwHgnbI8_fTBumvhi5EKoRdbWtFNT-CTj0n_KDKMk_nIIaZUQHU7eIzGNosTtXroVCaw==
Login Details
On macOS clients, we would use the MUK to decrypt the master key in the keysets entry for the primary account. But we don’t have the MUK, we have something else. But the vault is the same as on the Mac (it’s just stored as-is on the cloud, after all) – so we need to build the MUK. How do we do that without the user’s Secret Key?
Just as on macOS, the accounts table includes an “enc_login” field. On Windows, however, this is another opdata vault, encrypted using the keys we just derived.
$ python opdata.py
Enter 64-byte key (AES + HMAC) (hex or base64): cgUlD73bdmMYKUtpv3CwHgnbI8_fTBumvhi5EKoRdbWtFNT-CTj0n_KDKMk_nIIaZUQHU7eIzGNosTtXroVCaw==
Enter OPDATA binary (hex or base64): b3BkYXRhMDFkAAAAAAAAAOdAtGkH6N-oMZTnKBe-TadkOx6mviKTvkxolQSENTKUp6TCueQtKTBPdGg9eLBoNRph22ZYegLinJ6k5bUAD3_A9QrlaQ_W6uZv1nz1hfH3gZVTK9d4UzaRTNDtIF7-dy8QIOajiNe5hwYyGAPYA1B7YaLfeEMCi6fP2xoEvWwQ7IMV_mrxzZFsJYD1rmKS_2zZhBHQ1ywHApOmCvO4OXY=
** Decrypting OPDATA structure
raw opdata 6f70 6461 7461 3031 6400 0000 0000 0000
e740 b469 07e8 dfa8 3194 e728 17be 4da7
643b 1ea6 be22 93be 4c68 9504 8435 3294
a7a4 c2b9 e42d 2930 4f74 683d 78b0 6835
1a61 db66 587a 02e2 9c9e a4e5 b500 0f7f
c0f5 0ae5 690f d6ea e66f d67c f585 f1f7
8195 532b d778 5336 914c d0ed 205e fe77
2f10 20e6 a388 d7b9 8706 3218 03d8 0350
7b61 a2df 7843 028b a7cf db1a 04bd 6c10
ec83 15fe 6af1 cd91 6c25 80f5 ae62 92ff
6cd9 8411 d0d7 2c07 0293 a60a f3b8 3976
Header 6f70 6461 7461 3031
PT length 6400 0000 0000 0000
IV e740 b469 07e8 dfa8 3194 e728 17be 4da7
CT 643b 1ea6 be22 93be 4c68 9504 8435 3294
a7a4 c2b9 e42d 2930 4f74 683d 78b0 6835
1a61 db66 587a 02e2 9c9e a4e5 b500 0f7f
c0f5 0ae5 690f d6ea e66f d67c f585 f1f7
8195 532b d778 5336 914c d0ed 205e fe77
2f10 20e6 a388 d7b9 8706 3218 03d8 0350
7b61 a2df 7843 028b a7cf db1a 04bd 6c10
CT length (padded): 112
HMAC digest ec83 15fe 6af1 cd91 6c25 80f5 ae62 92ff
6cd9 8411 d0d7 2c07 0293 a60a f3b8 3976
Verifying HMAC tag
OPdata Msg 6f70 6461 7461 3031 6400 0000 0000 0000
e740 b469 07e8 dfa8 3194 e728 17be 4da7
643b 1ea6 be22 93be 4c68 9504 8435 3294
a7a4 c2b9 e42d 2930 4f74 683d 78b0 6835
1a61 db66 587a 02e2 9c9e a4e5 b500 0f7f
c0f5 0ae5 690f d6ea e66f d67c f585 f1f7
8195 532b d778 5336 914c d0ed 205e fe77
2f10 20e6 a388 d7b9 8706 3218 03d8 0350
7b61 a2df 7843 028b a7cf db1a 04bd 6c10
HMAC key ad14 d4fe 0938 f49f f283 28c9 3f9c 821a
6544 0753 b788 cc63 68b1 3b57 ae85 426b
Computed HMAC ec83 15fe 6af1 cd91 6c25 80f5 ae62 92ff
6cd9 8411 d0d7 2c07 0293 a60a f3b8 3976
HMAC signature verified.
*** decrypted opdata
Plaintext 7b22 6163 636f 756e 744b 6579 223a 2022
4133 2d41 5357 5759 422d 3739 384a 5259
2d4c 4a56 4434 2d32 3344 4332 2d38 3654
564d 2d48 3433 4542 222c 2022 7061 7373
776f 7264 223a 2022 7570 6461 7465 2d63
6c6f 776e 2d73 7175 6964 2d62 6564 706f
7374 227d
{"accountKey": "A3-ASWWYB-798JRY-LJVD4-23DC2-86TVM-H43EB", "password": "update-clown-squid-bedpost"}
Login details for secondary accounts are also encrypted the same way – using this key we just derived from the user’s password.
Unlocking Multiple Accounts
Let’s update the multiple-account diagram from the last installment, where we just talked about macOS. This now shows both Mac and Windows decryption chains in the same chart (though in practice, no single database would support both).
What’s next?
Also in the accounts table is the user’s email, as we learned last time, the keysets entry includes the 2SKD salt, iterations count, and algorithm information. So now we have enough information to generate the MUK.
Once we’ve done that, we decrypt the master key from the keyset, and can begin decrypting the 1Password vaults themselves.
Next Up: Into the Vaults!