Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 | // XXX until bug 937114 is fixed |
michael@0 | 5 | Cu.importGlobalProperties(['btoa']); |
michael@0 | 6 | Cu.import("resource://services-crypto/utils.js"); |
michael@0 | 7 | Cu.import("resource://services-common/utils.js"); |
michael@0 | 8 | |
michael@0 | 9 | let {bytesAsHex: b2h} = CommonUtils; |
michael@0 | 10 | |
michael@0 | 11 | function run_test() { |
michael@0 | 12 | run_next_test(); |
michael@0 | 13 | } |
michael@0 | 14 | |
michael@0 | 15 | add_task(function test_pbkdf2() { |
michael@0 | 16 | let symmKey16 = CryptoUtils.pbkdf2Generate("secret phrase", "DNXPzPpiwn", 4096, 16); |
michael@0 | 17 | do_check_eq(symmKey16.length, 16); |
michael@0 | 18 | do_check_eq(btoa(symmKey16), "d2zG0d2cBfXnRwMUGyMwyg=="); |
michael@0 | 19 | do_check_eq(CommonUtils.encodeBase32(symmKey16), "O5WMNUO5TQC7LZ2HAMKBWIZQZI======"); |
michael@0 | 20 | let symmKey32 = CryptoUtils.pbkdf2Generate("passphrase", "salt", 4096, 32); |
michael@0 | 21 | do_check_eq(symmKey32.length, 32); |
michael@0 | 22 | }); |
michael@0 | 23 | |
michael@0 | 24 | // http://tools.ietf.org/html/rfc6070 |
michael@0 | 25 | // PBKDF2 HMAC-SHA1 Test Vectors |
michael@0 | 26 | add_task(function test_pbkdf2_hmac_sha1() { |
michael@0 | 27 | let pbkdf2 = CryptoUtils.pbkdf2Generate; |
michael@0 | 28 | let vectors = [ |
michael@0 | 29 | {P: "password", // (8 octets) |
michael@0 | 30 | S: "salt", // (4 octets) |
michael@0 | 31 | c: 1, |
michael@0 | 32 | dkLen: 20, |
michael@0 | 33 | DK: h("0c 60 c8 0f 96 1f 0e 71"+ |
michael@0 | 34 | "f3 a9 b5 24 af 60 12 06"+ |
michael@0 | 35 | "2f e0 37 a6"), // (20 octets) |
michael@0 | 36 | }, |
michael@0 | 37 | |
michael@0 | 38 | {P: "password", // (8 octets) |
michael@0 | 39 | S: "salt", // (4 octets) |
michael@0 | 40 | c: 2, |
michael@0 | 41 | dkLen: 20, |
michael@0 | 42 | DK: h("ea 6c 01 4d c7 2d 6f 8c"+ |
michael@0 | 43 | "cd 1e d9 2a ce 1d 41 f0"+ |
michael@0 | 44 | "d8 de 89 57"), // (20 octets) |
michael@0 | 45 | }, |
michael@0 | 46 | |
michael@0 | 47 | {P: "password", // (8 octets) |
michael@0 | 48 | S: "salt", // (4 octets) |
michael@0 | 49 | c: 4096, |
michael@0 | 50 | dkLen: 20, |
michael@0 | 51 | DK: h("4b 00 79 01 b7 65 48 9a"+ |
michael@0 | 52 | "be ad 49 d9 26 f7 21 d0"+ |
michael@0 | 53 | "65 a4 29 c1"), // (20 octets) |
michael@0 | 54 | }, |
michael@0 | 55 | |
michael@0 | 56 | // XXX Uncomment the following test after Bug 968567 lands |
michael@0 | 57 | // |
michael@0 | 58 | // XXX As it stands, I estimate that the CryptoUtils implementation will |
michael@0 | 59 | // take approximately 16 hours in my 2.3GHz MacBook to perform this many |
michael@0 | 60 | // rounds. |
michael@0 | 61 | // |
michael@0 | 62 | // {P: "password", // (8 octets) |
michael@0 | 63 | // S: "salt" // (4 octets) |
michael@0 | 64 | // c: 16777216, |
michael@0 | 65 | // dkLen = 20, |
michael@0 | 66 | // DK: h("ee fe 3d 61 cd 4d a4 e4"+ |
michael@0 | 67 | // "e9 94 5b 3d 6b a2 15 8c"+ |
michael@0 | 68 | // "26 34 e9 84"), // (20 octets) |
michael@0 | 69 | // }, |
michael@0 | 70 | |
michael@0 | 71 | {P: "passwordPASSWORDpassword", // (24 octets) |
michael@0 | 72 | S: "saltSALTsaltSALTsaltSALTsaltSALTsalt", // (36 octets) |
michael@0 | 73 | c: 4096, |
michael@0 | 74 | dkLen: 25, |
michael@0 | 75 | DK: h("3d 2e ec 4f e4 1c 84 9b"+ |
michael@0 | 76 | "80 c8 d8 36 62 c0 e4 4a"+ |
michael@0 | 77 | "8b 29 1a 96 4c f2 f0 70"+ |
michael@0 | 78 | "38"), // (25 octets) |
michael@0 | 79 | |
michael@0 | 80 | }, |
michael@0 | 81 | |
michael@0 | 82 | {P: "pass\0word", // (9 octets) |
michael@0 | 83 | S: "sa\0lt", // (5 octets) |
michael@0 | 84 | c: 4096, |
michael@0 | 85 | dkLen: 16, |
michael@0 | 86 | DK: h("56 fa 6a a7 55 48 09 9d"+ |
michael@0 | 87 | "cc 37 d7 f0 34 25 e0 c3"), // (16 octets) |
michael@0 | 88 | }, |
michael@0 | 89 | ]; |
michael@0 | 90 | |
michael@0 | 91 | for (let v of vectors) { |
michael@0 | 92 | do_check_eq(v.DK, b2h(pbkdf2(v.P, v.S, v.c, v.dkLen))); |
michael@0 | 93 | } |
michael@0 | 94 | }); |
michael@0 | 95 | |
michael@0 | 96 | // I can't find any normative ietf test vectors for pbkdf2 hmac-sha256. |
michael@0 | 97 | // The following vectors are derived with the same inputs as above (the sha1 |
michael@0 | 98 | // test). Results verified by users here: |
michael@0 | 99 | // https://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors |
michael@0 | 100 | add_task(function test_pbkdf2_hmac_sha256() { |
michael@0 | 101 | let pbkdf2 = CryptoUtils.pbkdf2Generate; |
michael@0 | 102 | let vectors = [ |
michael@0 | 103 | {P: "password", // (8 octets) |
michael@0 | 104 | S: "salt", // (4 octets) |
michael@0 | 105 | c: 1, |
michael@0 | 106 | dkLen: 32, |
michael@0 | 107 | DK: h("12 0f b6 cf fc f8 b3 2c"+ |
michael@0 | 108 | "43 e7 22 52 56 c4 f8 37"+ |
michael@0 | 109 | "a8 65 48 c9 2c cc 35 48"+ |
michael@0 | 110 | "08 05 98 7c b7 0b e1 7b"), // (32 octets) |
michael@0 | 111 | }, |
michael@0 | 112 | |
michael@0 | 113 | {P: "password", // (8 octets) |
michael@0 | 114 | S: "salt", // (4 octets) |
michael@0 | 115 | c: 2, |
michael@0 | 116 | dkLen: 32, |
michael@0 | 117 | DK: h("ae 4d 0c 95 af 6b 46 d3"+ |
michael@0 | 118 | "2d 0a df f9 28 f0 6d d0"+ |
michael@0 | 119 | "2a 30 3f 8e f3 c2 51 df"+ |
michael@0 | 120 | "d6 e2 d8 5a 95 47 4c 43"), // (32 octets) |
michael@0 | 121 | }, |
michael@0 | 122 | |
michael@0 | 123 | {P: "password", // (8 octets) |
michael@0 | 124 | S: "salt", // (4 octets) |
michael@0 | 125 | c: 4096, |
michael@0 | 126 | dkLen: 32, |
michael@0 | 127 | DK: h("c5 e4 78 d5 92 88 c8 41"+ |
michael@0 | 128 | "aa 53 0d b6 84 5c 4c 8d"+ |
michael@0 | 129 | "96 28 93 a0 01 ce 4e 11"+ |
michael@0 | 130 | "a4 96 38 73 aa 98 13 4a"), // (32 octets) |
michael@0 | 131 | }, |
michael@0 | 132 | |
michael@0 | 133 | {P: "passwordPASSWORDpassword", // (24 octets) |
michael@0 | 134 | S: "saltSALTsaltSALTsaltSALTsaltSALTsalt", // (36 octets) |
michael@0 | 135 | c: 4096, |
michael@0 | 136 | dkLen: 40, |
michael@0 | 137 | DK: h("34 8c 89 db cb d3 2b 2f"+ |
michael@0 | 138 | "32 d8 14 b8 11 6e 84 cf"+ |
michael@0 | 139 | "2b 17 34 7e bc 18 00 18"+ |
michael@0 | 140 | "1c 4e 2a 1f b8 dd 53 e1"+ |
michael@0 | 141 | "c6 35 51 8c 7d ac 47 e9"), // (40 octets) |
michael@0 | 142 | }, |
michael@0 | 143 | |
michael@0 | 144 | {P: "pass\0word", // (9 octets) |
michael@0 | 145 | S: "sa\0lt", // (5 octets) |
michael@0 | 146 | c: 4096, |
michael@0 | 147 | dkLen: 16, |
michael@0 | 148 | DK: h("89 b6 9d 05 16 f8 29 89"+ |
michael@0 | 149 | "3c 69 62 26 65 0a 86 87"), // (16 octets) |
michael@0 | 150 | }, |
michael@0 | 151 | ]; |
michael@0 | 152 | |
michael@0 | 153 | for (let v of vectors) { |
michael@0 | 154 | do_check_eq(v.DK, |
michael@0 | 155 | b2h(pbkdf2(v.P, v.S, v.c, v.dkLen, Ci.nsICryptoHMAC.SHA256, 32))); |
michael@0 | 156 | } |
michael@0 | 157 | }); |
michael@0 | 158 | |
michael@0 | 159 | // turn formatted test vectors into normal hex strings |
michael@0 | 160 | function h(hexStr) { |
michael@0 | 161 | return hexStr.replace(/\s+/g, ""); |
michael@0 | 162 | } |