services/fxaccounts/tests/xpcshell/test_credentials.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* Any copyright is dedicated to the Public Domain.
michael@0 2 * http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 Cu.import("resource://gre/modules/Credentials.jsm");
michael@0 5 Cu.import("resource://gre/modules/Promise.jsm");
michael@0 6 Cu.import("resource://services-common/utils.js");
michael@0 7 Cu.import("resource://services-crypto/utils.js");
michael@0 8
michael@0 9 let {hexToBytes: h2b,
michael@0 10 hexAsString: h2s,
michael@0 11 stringAsHex: s2h,
michael@0 12 bytesAsHex: b2h} = CommonUtils;
michael@0 13
michael@0 14 // Test vectors for the "onepw" protocol:
michael@0 15 // https://github.com/mozilla/fxa-auth-server/wiki/onepw-protocol#wiki-test-vectors
michael@0 16 let vectors = {
michael@0 17 "client stretch-KDF": {
michael@0 18 email:
michael@0 19 h("616e6472c3a94065 78616d706c652e6f 7267"),
michael@0 20 password:
michael@0 21 h("70c3a4737377c3b6 7264"),
michael@0 22 quickStretchedPW:
michael@0 23 h("e4e8889bd8bd61ad 6de6b95c059d56e7 b50dacdaf62bd846 44af7e2add84345d"),
michael@0 24 authPW:
michael@0 25 h("247b675ffb4c4631 0bc87e26d712153a be5e1c90ef00a478 4594f97ef54f2375"),
michael@0 26 authSalt:
michael@0 27 h("00f0000000000000 0000000000000000 0000000000000000 0000000000000000"),
michael@0 28 },
michael@0 29 };
michael@0 30
michael@0 31 // A simple test suite with no utf8 encoding madness.
michael@0 32 add_task(function test_onepw_setup_credentials() {
michael@0 33 let email = "francine@example.org";
michael@0 34 let password = CommonUtils.encodeUTF8("i like pie");
michael@0 35
michael@0 36 let pbkdf2 = CryptoUtils.pbkdf2Generate;
michael@0 37 let hkdf = CryptoUtils.hkdf;
michael@0 38
michael@0 39 // quickStretch the email
michael@0 40 let saltyEmail = Credentials.keyWordExtended("quickStretch", email);
michael@0 41
michael@0 42 do_check_eq(b2h(saltyEmail), "6964656e746974792e6d6f7a696c6c612e636f6d2f7069636c2f76312f717569636b537472657463683a6672616e63696e65406578616d706c652e6f7267");
michael@0 43
michael@0 44 let pbkdf2Rounds = 1000;
michael@0 45 let pbkdf2Len = 32;
michael@0 46
michael@0 47 let quickStretchedPW = pbkdf2(password, saltyEmail, pbkdf2Rounds, pbkdf2Len, Ci.nsICryptoHMAC.SHA256, 32);
michael@0 48 let quickStretchedActual = "6b88094c1c73bbf133223f300d101ed70837af48d9d2c1b6e7d38804b20cdde4";
michael@0 49 do_check_eq(b2h(quickStretchedPW), quickStretchedActual);
michael@0 50
michael@0 51 // obtain hkdf info
michael@0 52 let authKeyInfo = Credentials.keyWord('authPW');
michael@0 53 do_check_eq(b2h(authKeyInfo), "6964656e746974792e6d6f7a696c6c612e636f6d2f7069636c2f76312f617574685057");
michael@0 54
michael@0 55 // derive auth password
michael@0 56 let hkdfSalt = h2b("00");
michael@0 57 let hkdfLen = 32;
michael@0 58 let authPW = hkdf(quickStretchedPW, hkdfSalt, authKeyInfo, hkdfLen);
michael@0 59
michael@0 60 do_check_eq(b2h(authPW), "4b8dec7f48e7852658163601ff766124c312f9392af6c3d4e1a247eb439be342");
michael@0 61
michael@0 62 // derive unwrap key
michael@0 63 let unwrapKeyInfo = Credentials.keyWord('unwrapBkey');
michael@0 64 let unwrapKey = hkdf(quickStretchedPW, hkdfSalt, unwrapKeyInfo, hkdfLen);
michael@0 65
michael@0 66 do_check_eq(b2h(unwrapKey), "8ff58975be391338e4ec5d7138b5ed7b65c7d1bfd1f3a4f93e05aa47d5b72be9");
michael@0 67 });
michael@0 68
michael@0 69 add_task(function test_client_stretch_kdf() {
michael@0 70 let pbkdf2 = CryptoUtils.pbkdf2Generate;
michael@0 71 let hkdf = CryptoUtils.hkdf;
michael@0 72 let expected = vectors["client stretch-KDF"];
michael@0 73
michael@0 74 let emailUTF8 = h2s(expected.email);
michael@0 75 let passwordUTF8 = h2s(expected.password);
michael@0 76
michael@0 77 // Intermediate value from sjcl implementation in fxa-js-client
michael@0 78 // The key thing is the c3a9 sequence in "andré"
michael@0 79 let salt = Credentials.keyWordExtended("quickStretch", emailUTF8);
michael@0 80 do_check_eq(b2h(salt), "6964656e746974792e6d6f7a696c6c612e636f6d2f7069636c2f76312f717569636b537472657463683a616e6472c3a9406578616d706c652e6f7267");
michael@0 81
michael@0 82 let options = {
michael@0 83 stretchedPassLength: 32,
michael@0 84 pbkdf2Rounds: 1000,
michael@0 85 hmacAlgorithm: Ci.nsICryptoHMAC.SHA256,
michael@0 86 hmacLength: 32,
michael@0 87 hkdfSalt: h2b("00"),
michael@0 88 hkdfLength: 32,
michael@0 89 };
michael@0 90
michael@0 91 let results = yield Credentials.setup(emailUTF8, passwordUTF8, options);
michael@0 92
michael@0 93 do_check_eq(emailUTF8, results.emailUTF8,
michael@0 94 "emailUTF8 is wrong");
michael@0 95
michael@0 96 do_check_eq(passwordUTF8, results.passwordUTF8,
michael@0 97 "passwordUTF8 is wrong");
michael@0 98
michael@0 99 do_check_eq(expected.quickStretchedPW, b2h(results.quickStretchedPW),
michael@0 100 "quickStretchedPW is wrong");
michael@0 101
michael@0 102 do_check_eq(expected.authPW, b2h(results.authPW),
michael@0 103 "authPW is wrong");
michael@0 104 });
michael@0 105
michael@0 106 // End of tests
michael@0 107 // Utility functions follow
michael@0 108
michael@0 109 function run_test() {
michael@0 110 run_next_test();
michael@0 111 }
michael@0 112
michael@0 113 // turn formatted test vectors into normal hex strings
michael@0 114 function h(hexStr) {
michael@0 115 return hexStr.replace(/\s+/g, "");
michael@0 116 }

mercurial