OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <html> | 2 <html> |
3 <head> | 3 <head> |
4 <script src="../resources/js-test.js"></script> | 4 <script src="../resources/js-test.js"></script> |
5 <script src="resources/common.js"></script> | 5 <script src="resources/common.js"></script> |
6 </head> | 6 </head> |
7 <body> | 7 <body> |
8 <p id="description"></p> | 8 <p id="description"></p> |
9 <div id="console"></div> | 9 <div id="console"></div> |
10 | 10 |
11 <script> | 11 <script> |
12 description("Tests cypto.subtle.encrypt and crypto.subtle.decrypt"); | 12 description("Tests cypto.subtle.encrypt and crypto.subtle.decrypt"); |
13 | 13 |
14 jsTestIsAsync = true; | 14 jsTestIsAsync = true; |
15 | 15 |
16 // A list of Promises for every test to run. | 16 // A list of Promises for every test to run. |
17 var allTests = []; | 17 var allTests = []; |
18 | 18 |
19 // ------------------------------------------------- | 19 // ------------------------------------------------- |
20 // Successful encryption/decryption | 20 // Successful encryption/decryption |
21 // ------------------------------------------------- | 21 // ------------------------------------------------- |
22 | 22 |
23 // Test vectors marked with [1] were copied from: | 23 // Test vectors marked with [1] were copied from: |
24 // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf | 24 // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf |
25 // | 25 // |
26 // The NIST tests do not have a padding block. To match the WebCrypto | 26 // The NIST tests do not have a padding block. To match the WebCrypto |
27 // expectations, a PKCS#5 padding block has been added. | 27 // expectations, a PKCS#5 padding block has been added. |
28 | 28 |
29 var kSuccessTestVectors = [ | 29 var kAesCbcSuccessVectors = [ |
30 // 128-bit key with plaintext that is an exact multiple of block size. | 30 // 128-bit key with plaintext that is an exact multiple of block size. |
31 // Derived from [1] F.2.1 (CBC-AES128.Encrypt), by adding padding block. | 31 // Derived from [1] F.2.1 (CBC-AES128.Encrypt), by adding padding block. |
32 { | 32 { |
33 key: "2b7e151628aed2a6abf7158809cf4f3c", | 33 key: "2b7e151628aed2a6abf7158809cf4f3c", |
34 iv: "000102030405060708090a0b0c0d0e0f", | 34 iv: "000102030405060708090a0b0c0d0e0f", |
35 plainText: "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51
30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", | 35 plainText: "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51
30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", |
36 cipherText: "7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b
273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120eca307586e1a7" + | 36 cipherText: "7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b
273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120eca307586e1a7" + |
37 // Padding block. | 37 // Padding block. |
38 "8cb82807230e1321d3fae00d18cc2012" | 38 "8cb82807230e1321d3fae00d18cc2012" |
39 }, | 39 }, |
(...skipping 23 matching lines...) Expand all Loading... |
63 // 128-bit key, with empty plaintext. | 63 // 128-bit key, with empty plaintext. |
64 // Derived from Chromium's EncryptorTest.EmptyEncrypt() (encryptor_unittest.cc
) | 64 // Derived from Chromium's EncryptorTest.EmptyEncrypt() (encryptor_unittest.cc
) |
65 { | 65 { |
66 key: "3132383d5369787465656e4279746573", | 66 key: "3132383d5369787465656e4279746573", |
67 iv: "5377656574205369787465656e204956", | 67 iv: "5377656574205369787465656e204956", |
68 plainText: "", | 68 plainText: "", |
69 cipherText: "8518b8878d34e7185e300d0fcc426396" | 69 cipherText: "8518b8878d34e7185e300d0fcc426396" |
70 }, | 70 }, |
71 ]; | 71 ]; |
72 | 72 |
73 function runSuccessTestCase(testCase) | 73 // These tests come from the NIST GCM test vectors: |
| 74 // http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip |
| 75 // |
| 76 // Both encryption and decryption are expected to work. |
| 77 var kAesGcmSuccessVectors = |
| 78 [ |
| 79 // [Keylen = 128] |
| 80 // [IVlen = 96] |
| 81 // [PTlen = 0] |
| 82 // [AADlen = 0] |
| 83 // [Taglen = 128] |
| 84 { |
| 85 "key": "cf063a34d4a9a76c2c86787d3f96db71", |
| 86 "iv": "113b9785971864c83b01c787", |
| 87 "plainText": "", |
| 88 "cipherText": "", |
| 89 "additionalData": "", |
| 90 "authenticationTag": "72ac8493e3a5228b5d130a69d2510e42" |
| 91 }, |
| 92 |
| 93 // [Keylen = 128] |
| 94 // [IVlen = 96] |
| 95 // [PTlen = 0] |
| 96 // [AADlen = 128] |
| 97 // [Taglen = 120] |
| 98 { |
| 99 "key": "6dfa1a07c14f978020ace450ad663d18", |
| 100 "iv": "34edfa462a14c6969a680ec1", |
| 101 "plainText": "", |
| 102 "cipherText": "", |
| 103 "additionalData": "2a35c7f5f8578e919a581c60500c04f6", |
| 104 "authenticationTag": "751f3098d59cf4ea1d2fb0853bde1c" |
| 105 }, |
| 106 |
| 107 // [Keylen = 128] |
| 108 // [IVlen = 96] |
| 109 // [PTlen = 128] |
| 110 // [AADlen = 128] |
| 111 // [Taglen = 112] |
| 112 { |
| 113 "key": "ed6cd876ceba555706674445c229c12d", |
| 114 "iv": "92ecbf74b765bc486383ca2e", |
| 115 "plainText": "bfaaaea3880d72d4378561e2597a9b35", |
| 116 "cipherText": "bdd2ed6c66fa087dce617d7fd1ff6d93", |
| 117 "additionalData": "95bd10d77dbe0e87fb34217f1a2e5efe", |
| 118 "authenticationTag": "ba82e49c55a22ed02ca67da4ec6f" |
| 119 }, |
| 120 |
| 121 // [Keylen = 192] |
| 122 // [IVlen = 96] |
| 123 // [PTlen = 128] |
| 124 // [AADlen = 384] |
| 125 // [Taglen = 112] |
| 126 { |
| 127 "key": "ae7972c025d7f2ca3dd37dcc3d41c506671765087c6b61b8", |
| 128 "iv": "984c1379e6ba961c828d792d", |
| 129 "plainText": "d30b02c343487105219d6fa080acc743", |
| 130 "cipherText": "c4489fa64a6edf80e7e6a3b8855bc37c", |
| 131 "additionalData": "edd8f630f9bbc31b0acf122998f15589d6e6e3e1a3ec89e0c6a6ece75
1610ebbf57fdfb9d82028ff1d9faebe37a268c1", |
| 132 "authenticationTag": "772ee7de0f91a981c36c93a35c88" |
| 133 } |
| 134 ]; |
| 135 |
| 136 function runAesCbcSuccessTestCase(testCase) |
74 { | 137 { |
75 var algorithm = {name: 'aes-cbc', iv: hexStringToUint8Array(testCase.iv)}; | 138 var algorithm = {name: 'aes-cbc', iv: hexStringToUint8Array(testCase.iv)}; |
76 | 139 |
77 var key = null; | 140 var key = null; |
78 var keyData = hexStringToUint8Array(testCase.key); | 141 var keyData = hexStringToUint8Array(testCase.key); |
79 var usages = ['encrypt', 'decrypt']; | 142 var usages = ['encrypt', 'decrypt']; |
80 var extractable = false; | 143 var extractable = false; |
81 | 144 |
82 // (1) Import the key | 145 // (1) Import the key |
83 return crypto.subtle.importKey('raw', keyData, algorithm, extractable, usage
s).then(function(result) { | 146 return crypto.subtle.importKey('raw', keyData, algorithm, extractable, usage
s).then(function(result) { |
(...skipping 11 matching lines...) Expand all Loading... |
95 }).then(function(result) { | 158 }).then(function(result) { |
96 bytesShouldMatchHexString("Encryption", testCase.cipherText, result); | 159 bytesShouldMatchHexString("Encryption", testCase.cipherText, result); |
97 | 160 |
98 // (3) Decrypt | 161 // (3) Decrypt |
99 return crypto.subtle.decrypt(algorithm, key, hexStringToUint8Array(testC
ase.cipherText)); | 162 return crypto.subtle.decrypt(algorithm, key, hexStringToUint8Array(testC
ase.cipherText)); |
100 }).then(function(result) { | 163 }).then(function(result) { |
101 bytesShouldMatchHexString("Decryption", testCase.plainText, result); | 164 bytesShouldMatchHexString("Decryption", testCase.plainText, result); |
102 }); | 165 }); |
103 } | 166 } |
104 | 167 |
| 168 function runAesGcmSuccessTestCase(testCase) |
| 169 { |
| 170 var key = null; |
| 171 var keyData = hexStringToUint8Array(testCase.key); |
| 172 var iv = hexStringToUint8Array(testCase.iv); |
| 173 var additionalData = hexStringToUint8Array(testCase.additionalData); |
| 174 var tag = hexStringToUint8Array(testCase.authenticationTag); |
| 175 var usages = ['encrypt', 'decrypt']; |
| 176 var extractable = false; |
| 177 |
| 178 var tagLengthBits = tag.byteLength * 8; |
| 179 |
| 180 var algorithm = {name: 'aes-gcm', iv: iv, additionalData: additionalData, ta
gLength: tagLengthBits}; |
| 181 |
| 182 // (1) Import the key |
| 183 return crypto.subtle.importKey('raw', keyData, algorithm, extractable, usage
s).then(function(result) { |
| 184 key = result; |
| 185 |
| 186 // shouldBe() can only resolve variables in global context. |
| 187 tmpKey = key; |
| 188 shouldBe("tmpKey.type", "'secret'"); |
| 189 shouldBe("tmpKey.extractable", "false"); |
| 190 shouldBe("tmpKey.algorithm.name", "'AES-GCM'"); |
| 191 shouldBe("tmpKey.usages.join(',')", "'decrypt,encrypt'"); |
| 192 |
| 193 // (2) Encrypt. |
| 194 return crypto.subtle.encrypt(algorithm, key, hexStringToUint8Array(testC
ase.plainText)); |
| 195 }).then(function(result) { |
| 196 bytesShouldMatchHexString("Encryption", testCase.cipherText + testCase.a
uthenticationTag, result); |
| 197 |
| 198 // (3) Decrypt |
| 199 return crypto.subtle.decrypt(algorithm, key, hexStringToUint8Array(testC
ase.cipherText + testCase.authenticationTag)); |
| 200 }).then(function(result) { |
| 201 bytesShouldMatchHexString("Decryption", testCase.plainText, result); |
| 202 }); |
| 203 } |
| 204 |
105 // Add all of the tests defined above. | 205 // Add all of the tests defined above. |
106 for (var i = 0; i < kSuccessTestVectors.length; ++i) { | 206 for (var i = 0; i < kAesCbcSuccessVectors.length; ++i) { |
107 addTask(runSuccessTestCase(kSuccessTestVectors[i])); | 207 addTask(runAesCbcSuccessTestCase(kAesCbcSuccessVectors[i])); |
| 208 } |
| 209 |
| 210 // Add all of the tests defined above. |
| 211 for (var i = 0; i < kAesGcmSuccessVectors.length; ++i) { |
| 212 addTask(runAesGcmSuccessTestCase(kAesGcmSuccessVectors[i])); |
108 } | 213 } |
109 | 214 |
110 // ------------------------------------------------- | 215 // ------------------------------------------------- |
111 // Failed key import. | 216 // Failed key import. |
112 // ------------------------------------------------- | 217 // ------------------------------------------------- |
113 | 218 |
114 // Supported key lengths are 16 (128-bit), 32 (256-bit), 24 (192-bit), | 219 // Supported key lengths are 16 (128-bit), 32 (256-bit), 24 (192-bit), |
115 // Try key lengths that are off by 1 from the supported ones. | 220 // Try key lengths that are off by 1 from the supported ones. |
116 var kUnsupportedKeyLengths = [ | 221 var kUnsupportedKeyLengths = [ |
117 0, 1, 15, 17, 31, 33, 23, 25, 64 | 222 0, 1, 15, 17, 31, 33, 23, 25, 64 |
(...skipping 15 matching lines...) Expand all Loading... |
133 } | 238 } |
134 | 239 |
135 for (var i = 0; i < kUnsupportedKeyLengths.length; ++i) { | 240 for (var i = 0; i < kUnsupportedKeyLengths.length; ++i) { |
136 addTask(testInvalidKeyImport(kUnsupportedKeyLengths[i])); | 241 addTask(testInvalidKeyImport(kUnsupportedKeyLengths[i])); |
137 } | 242 } |
138 | 243 |
139 // ------------------------------------------------- | 244 // ------------------------------------------------- |
140 // Invalid cipher texts | 245 // Invalid cipher texts |
141 // ------------------------------------------------- | 246 // ------------------------------------------------- |
142 | 247 |
143 function testInvalidDecryptions() | 248 function testInvalidAesCbcDecryptions() |
144 { | 249 { |
145 // 128-bit key with plaintext that is an exact multiple of block size. | 250 // 128-bit key with plaintext that is an exact multiple of block size. |
146 // Derived from [1] F.2.1 (CBC-AES128.Encrypt), by adding padding block. | 251 // Derived from [1] F.2.1 (CBC-AES128.Encrypt), by adding padding block. |
147 var iv = hexStringToUint8Array("000102030405060708090a0b0c0d0e0f"); | 252 var iv = hexStringToUint8Array("000102030405060708090a0b0c0d0e0f"); |
148 var keyData = hexStringToUint8Array("2b7e151628aed2a6abf7158809cf4f3c"); | 253 var keyData = hexStringToUint8Array("2b7e151628aed2a6abf7158809cf4f3c"); |
149 var cipherText = hexStringToUint8Array("7649abac8119b246cee98e9b12e9197d5086
cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120e
ca307586e1a78cb82807230e1321d3fae00d18cc2012"); | 254 var cipherText = hexStringToUint8Array("7649abac8119b246cee98e9b12e9197d5086
cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120e
ca307586e1a78cb82807230e1321d3fae00d18cc2012"); |
150 | 255 |
151 var key = null; | 256 var key = null; |
152 var usages = ['encrypt', 'decrypt']; | 257 var usages = ['encrypt', 'decrypt']; |
153 var extractable = false; | 258 var extractable = false; |
(...skipping 28 matching lines...) Expand all Loading... |
182 // padding error. | 287 // padding error. |
183 verifyDecryptionFails(cipherText.byteLength - 16), | 288 verifyDecryptionFails(cipherText.byteLength - 16), |
184 verifyDecryptionFails(1), | 289 verifyDecryptionFails(1), |
185 verifyDecryptionFails(15), | 290 verifyDecryptionFails(15), |
186 verifyDecryptionFails(16), | 291 verifyDecryptionFails(16), |
187 verifyDecryptionFails(17), | 292 verifyDecryptionFails(17), |
188 ]); | 293 ]); |
189 }); | 294 }); |
190 } | 295 } |
191 | 296 |
192 addTask(testInvalidDecryptions()); | 297 addTask(testInvalidAesCbcDecryptions()); |
193 | 298 |
194 function testNormalizationFailures(importedKeys) | 299 function testNormalizationFailures(importedKeys) |
195 { | 300 { |
196 keys = importedKeys; | 301 keys = importedKeys; |
197 | 302 |
198 data = asciiToUint8Array("hello"); | 303 data = asciiToUint8Array("hello"); |
199 | 304 |
200 // --------------------------------------------------- | 305 // --------------------------------------------------- |
201 // AES-CBC normalization failures (AesCbcParams) | 306 // AES-CBC normalization failures (AesCbcParams) |
202 // --------------------------------------------------- | 307 // --------------------------------------------------- |
203 | 308 |
204 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CBC', iv: nul
l}, keys.aesCbc, data)"); | 309 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CBC', iv: nul
l}, keys.aesCbc, data)"); |
205 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CBC'}, keys.a
esCbc, data)"); | 310 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CBC'}, keys.a
esCbc, data)"); |
206 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CBC', iv: 3},
keys.aesCbc, data)"); | 311 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CBC', iv: 3},
keys.aesCbc, data)"); |
207 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CBC', iv: new
Uint8Array(0)}, keys.aesCbc, data)"); | 312 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CBC', iv: new
Uint8Array(0)}, keys.aesCbc, data)"); |
208 | 313 |
209 // --------------------------------------------------- | 314 // --------------------------------------------------- |
210 // AES-CTR normalization failures (AesCtrParams) | 315 // AES-CTR normalization failures (AesCtrParams) |
211 // --------------------------------------------------- | 316 // --------------------------------------------------- |
212 | 317 |
213 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: null}, keys.aesCtr, data)"); | 318 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: null}, keys.aesCtr, data)"); |
214 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR'}, keys.a
esCtr, data)"); | 319 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR'}, keys.a
esCtr, data)"); |
215 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(0)}, keys.aesCtr, data)"); | 320 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(0)}, keys.aesCtr, data)"); |
216 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: 0}, keys.aesCtr, data)"); | 321 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: 0}, keys.aesCtr, data)"); |
217 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: 18}, keys.aesCtr, data)"); | 322 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: 18}, keys.aesCtr, data)"); |
218 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: 256}, keys.aesCtr, data)"); | 323 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: 256}, keys.aesCtr, data)"); |
219 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: -3}, keys.aesCtr, data)"); | 324 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: -3}, keys.aesCtr, data)"); |
220 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: Infinity}, keys.aesCtr, data)"); | 325 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-CTR', counter
: new Uint8Array(16), length: Infinity}, keys.aesCtr, data)"); |
221 | 326 |
| 327 // --------------------------------------------------- |
| 328 // AES-CBC normalization failures (AesGcmParams) |
| 329 // --------------------------------------------------- |
| 330 |
| 331 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-gcm'}, keys.a
esGcm, data)"); |
| 332 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-gcm', iv: 3},
keys.aesGcm, data)"); |
| 333 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-gcm', iv: 'fo
o'}, keys.aesGcm, data)"); |
| 334 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-gcm', iv: new
Uint8Array(16), additionalData: '5'}, keys.aesGcm, data)"); |
| 335 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-gcm', iv: new
Uint8Array(16), additionalData: new Uint8Array(1), tagLength: 'foo'}, keys.aesG
cm, data)"); |
| 336 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-gcm', iv: new
Uint8Array(16), additionalData: new Uint8Array(1), tagLength: -1}, keys.aesGcm,
data)"); |
| 337 shouldRejectPromiseWithNull("crypto.subtle.encrypt({name: 'AES-gcm', iv: new
Uint8Array(16), additionalData: new Uint8Array(1), tagLength: 8000}, keys.aesGc
m, data)"); |
| 338 |
222 // Try calling with the wrong key type. | 339 // Try calling with the wrong key type. |
223 aesCbc = {name: 'AES-CBC', iv: new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15])}; | 340 aesCbc = {name: 'AES-CBC', iv: new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15])}; |
224 shouldRejectPromiseWithNull("crypto.subtle.encrypt(aesCbc, keys.hmacSha1, da
ta)"); | 341 shouldRejectPromiseWithNull("crypto.subtle.encrypt(aesCbc, keys.hmacSha1, da
ta)"); |
225 | 342 |
226 // Key doesn't support encrypt. | 343 // Key doesn't support encrypt. |
227 shouldRejectPromiseWithNull("crypto.subtle.encrypt(aesCbc, keys.aesCbcJustDe
crypt, data)"); | 344 shouldRejectPromiseWithNull("crypto.subtle.encrypt(aesCbc, keys.aesCbcJustDe
crypt, data)"); |
228 | 345 |
229 // If no key was specified AND the algorithm was bogus, should complain | 346 // If no key was specified AND the algorithm was bogus, should complain |
230 // about the missing key first. | 347 // about the missing key first. |
231 shouldThrow("crypto.subtle.encrypt({name: 'bogus'}, null, data)"); | 348 shouldThrow("crypto.subtle.encrypt({name: 'bogus'}, null, data)"); |
232 } | 349 } |
233 | 350 |
234 addTask(importTestKeys().then(testNormalizationFailures)); | 351 addTask(importTestKeys().then(testNormalizationFailures)); |
235 | 352 |
236 completeTestWhenAllTasksDone(); | 353 completeTestWhenAllTasksDone(); |
237 | 354 |
238 </script> | 355 </script> |
239 | 356 |
240 </body> | 357 </body> |
OLD | NEW |