| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="../../../resources/js-test.js"></script> |
| <script src="../resources/common.js"></script> |
| </head> |
| <body> |
| <p id="description"></p> |
| <div id="console"></div> |
| |
| <script> |
| description("Tests wrapping and unwrapping of AES-CBC keys using AES-KW and raw format"); |
| |
| jsTestIsAsync = true; |
| |
| var kWrappingTestCases = [ |
| // AES-KW test vectors from http://www.ietf.org/rfc/rfc3394.txt |
| // 4.1 Wrap 128 bits of Key Data with a 128-bit KEK |
| { |
| "wrappingKey": "000102030405060708090A0B0C0D0E0F", |
| "key": "00112233445566778899AABBCCDDEEFF", |
| "ciphertext": "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5" |
| }, |
| // 4.3 Wrap 128 bits of Key Data with a 256-bit KEK |
| { |
| "wrappingKey": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", |
| "key": "00112233445566778899AABBCCDDEEFF", |
| "ciphertext": "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7" |
| }, |
| // 4.5 Wrap 192 bits of Key Data with a 256-bit KEK |
| { |
| "wrappingKey": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", |
| "key": "00112233445566778899AABBCCDDEEFF0001020304050607", |
| "ciphertext": "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1" |
| }, |
| // 4.6 Wrap 256 bits of Key Data with a 256-bit KEK |
| { |
| "wrappingKey": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", |
| "key": "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F", |
| "ciphertext": "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21" |
| } |
| ] |
| |
| function runTestCase(testCase) |
| { |
| var wrappingKey = null; |
| var key = null; |
| |
| return Promise.resolve(null).then(function(result) { |
| // Import the wrapping key |
| var importAlgorithm = {name: 'aes-kw'}; |
| var keyData = hexStringToUint8Array(testCase.wrappingKey); |
| var usages = ['wrapKey', 'unwrapKey']; |
| var extractable = false; |
| |
| return crypto.subtle.importKey('raw', keyData, importAlgorithm, extractable, usages); |
| }).then(function(result) { |
| wrappingKey = result; |
| |
| // Import the key to be wrapped. |
| var importAlgorithm = {name: 'HMAC', hash: {name: 'sha-1'}}; |
| var keyData = hexStringToUint8Array(testCase.key); |
| var usages = ['sign', 'verify']; |
| var extractable = true; |
| |
| return crypto.subtle.importKey('raw', keyData, importAlgorithm, extractable, usages); |
| }).then(function(result) { |
| key = result; |
| |
| // Wrap the key. |
| var wrapAlgorithm = {name: 'aes-kw'}; |
| return crypto.subtle.wrapKey('raw', key, wrappingKey, wrapAlgorithm); |
| }).then(function(result) { |
| bytesShouldMatchHexString("Wrapped key data", testCase.ciphertext, result); |
| |
| // Unwrap the key. |
| var wrappedKeyData = hexStringToUint8Array(testCase.ciphertext); |
| var unwrapAlgorithm = {name: 'aes-kw'}; |
| var unwrappedKeyAlgorithm = {name: 'HMAC', hash: {name: 'sha-1'}}; |
| var extractable = true; |
| var usages = ['sign']; |
| return crypto.subtle.unwrapKey('raw', wrappedKeyData, wrappingKey, unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, usages); |
| }).then(function(result) { |
| unwrappedKey = result; |
| |
| shouldEvaluateAs("unwrappedKey.algorithm.name", "HMAC"); |
| shouldEvaluateAs("unwrappedKey.algorithm.hash.name", "SHA-1"); |
| shouldEvaluateAs("unwrappedKey.algorithm.length", testCase.key.length * 4); |
| shouldEvaluateAs("unwrappedKey.extractable", true); |
| shouldEvaluateAs("unwrappedKey.usages.join(',')", "sign"); |
| |
| return crypto.subtle.exportKey('raw', unwrappedKey); |
| }).then(function(result) { |
| bytesShouldMatchHexString("Unwrapped key data", testCase.key, result); |
| }); |
| } |
| |
| var lastPromise = Promise.resolve(null); |
| |
| kWrappingTestCases.forEach(function(test) { |
| lastPromise = lastPromise.then(runTestCase.bind(null, test)); |
| }); |
| |
| lastPromise.then(finishJSTest, failAndFinishJSTest); |
| |
| </script> |
| |
| </body> |
| </html> |