| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="../fast/js/resources/js-test-pre.js"></script> |
| <script src="resources/common.js"></script> |
| </head> |
| <body> |
| <p id="description"></p> |
| <div id="console"></div> |
| |
| <script> |
| description("Tests algorithm normalization."); |
| |
| jsTestIsAsync = true; |
| |
| // FIXME: Rename this to crypto-operation.html, since it tests the basic |
| // construction of CryptoOperations. |
| |
| // ------------------------------- |
| // Helpers to return a normalized algorithm identifier. |
| // ------------------------------- |
| |
| aesCbcKey = null; |
| hmacSha1Key = null; |
| rsaSsaKey = null; |
| |
| function normalizeDigest(algorithmIdentifier) |
| { |
| return crypto.subtle.digest(algorithmIdentifier).algorithm; |
| } |
| |
| function normalizeEncrypt(algorithmIdentifier, key) |
| { |
| return crypto.subtle.encrypt(algorithmIdentifier, key).algorithm; |
| } |
| |
| function normalizeSign(algorithmIdentifier, key) |
| { |
| return crypto.subtle.sign(algorithmIdentifier, key).algorithm; |
| } |
| |
| function runTests() |
| { |
| // ------------------------------- |
| // Case insensitivity of "name" |
| // ------------------------------- |
| algorithm = normalizeDigest({name: "SHA-1"}); |
| shouldBe("algorithm.name", "'SHA-1'"); |
| algorithm = normalizeDigest({name: "sHa-256"}); |
| shouldBe("algorithm.name", "'SHA-256'"); |
| |
| // ------------------------------- |
| // Failures if "name" is invalid |
| // ------------------------------- |
| shouldThrow("normalizeDigest({})"); |
| shouldThrow("normalizeDigest({name: null})"); |
| shouldThrow("normalizeDigest({name: -1})"); |
| shouldThrow("normalizeDigest({name: ''})"); |
| shouldThrow("normalizeDigest({name: 'nosuchalgorithm'})"); |
| shouldThrow("normalizeDigest({name: '\\u0189'})"); |
| |
| // ------------------------------- |
| // Failures if the algorithm identifier is not an object |
| // ------------------------------- |
| shouldThrow("normalizeDigest(null)"); |
| shouldThrow("normalizeDigest(0)"); |
| shouldThrow("normalizeDigest(undefined)"); |
| shouldThrow("normalizeDigest('')"); |
| |
| // ------------------------------- |
| // Skip unrecognized parameters. |
| // ------------------------------- |
| algorithm = normalizeDigest({name: "sHa-1", noSuchParam: 3}); |
| shouldBeUndefined("algorithm.noSuchParam"); |
| |
| // ------------------------------- |
| // Normalized algorithm COPIES all data |
| // ------------------------------- |
| originalIv = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); |
| algorithm = normalizeEncrypt({ name: "aes-cbc", iv: originalIv }, aesCbcKey); |
| |
| // Make sure it constructed the normalized result. |
| shouldBe("algorithm.name", "'AES-CBC'"); |
| shouldBe("algorithm.iv.length", "16"); |
| shouldBe("algorithm.iv[3]", "3"); |
| |
| // Mutate the original (un-normalized) algorithm. Verify that this doesn't affect the normalized output. |
| originalIv[3] = 0; |
| shouldBe("algorithm.iv[3]", "3"); |
| |
| // ------------------------------- |
| // AES-CBC normalization failures |
| // ------------------------------- |
| |
| // The "iv" MUST be 16 bytes long. |
| rawAlgorithm = { |
| name: "AES-CBC", |
| iv: new Uint8Array([1, 2, 3]) |
| }; |
| shouldThrow("normalizeEncrypt(rawAlgorithm, aesCbcKey)"); |
| |
| // ------------------------------- |
| // Normalize a normalized algorithm (SHA-384) |
| // ------------------------------- |
| algorithm = normalizeDigest({name: "sHa-384"}); |
| shouldBe("algorithm.name", "'SHA-384'"); |
| algorithm = normalizeDigest(algorithm); |
| shouldBe("algorithm.name", "'SHA-384'"); |
| |
| // ------------------------------- |
| // Normalize a normalized algorithm (AES-CBC, encrypt) |
| // ------------------------------- |
| algorithm = normalizeEncrypt({ name: "aEs-cbc", iv: originalIv }, aesCbcKey); |
| // Make sure it constructed the normalized result. |
| shouldBe("algorithm.name", "'AES-CBC'"); |
| shouldBe("algorithm.iv.length", "16"); |
| shouldBe("algorithm.iv[1]", "1"); |
| algorithm = normalizeEncrypt(algorithm, aesCbcKey); |
| shouldBe("algorithm.name", "'AES-CBC'"); |
| shouldBe("algorithm.iv.length", "16"); |
| shouldBe("algorithm.iv[1]", "1"); |
| |
| // ------------------------------- |
| // Unsupported operation on algorithm |
| // ------------------------------- |
| shouldThrow("normalizeEncrypt({ name: 'SHA-1' }, aesCbcKey)"); |
| shouldThrow("normalizeDigest({ name: 'AES-CBC', iv: originalIv })"); |
| |
| // ------------------------------- |
| // Normalize HMAC |
| // ------------------------------- |
| shouldThrow("normalizeSign({name: 'hmac'}, hmacSha1Key)"); // Missing "hash" |
| shouldThrow("normalizeSign({name: 'hmac', hash: 'foo'}, hmacSha1Key)"); // Not a valid "hash" |
| shouldThrow("normalizeSign({name: 'hmac', hash: { name: 'AES-CBC', iv: originalIv }}, hmacSha1Key)"); // Not a valid "hash" |
| |
| validHmacSha1 = {name: 'hmac', hash: {name: 'Sha-1'}}; |
| algorithm = normalizeSign(validHmacSha1, hmacSha1Key); |
| shouldBe("algorithm.name", "'HMAC'"); |
| shouldBe("algorithm.hash.name", "'SHA-1'"); |
| |
| shouldThrow("normalizeEncrypt(validHmacSha1, hmacSha1Key)"); // Not defined for encrypt() |
| |
| // ------------------------------- |
| // Normalize RSASSA-PKCS1-v1_5 |
| // ------------------------------- |
| shouldThrow("normalizeSign({name: 'RSASSA-PKCS1-v1_5'}, rsaSsaKey)"); // Missing "hash" |
| shouldThrow("normalizeSign({name: 'RSASSA-PKCS1-v1_5', hash: 'foo'}, rsaSsaKey)"); // Not a valid "hash" |
| shouldThrow("normalizeSign({name: 'RSASSA-PKCS1-v1_5', hash: { name: 'AES-CBC', iv: originalIv }}, rsaSsaKey)"); // Not a valid "hash" |
| |
| validRsaSsa = {name: 'RsaSsa-PKCS1-v1_5', hash: {name: 'Sha-256'}}; |
| algorithm = normalizeSign(validRsaSsa, rsaSsaKey); |
| shouldBe("algorithm.name", "'RSASSA-PKCS1-v1_5'"); |
| shouldBe("algorithm.hash.name", "'SHA-256'"); |
| |
| shouldThrow("normalizeEncrypt(validRsaSsa, rsaSsaKey)"); // Not defined for encrypt() |
| |
| // FIXME: Test the normalization of RsaSsaKeyGen parameters. |
| |
| // ------------------------------- |
| // Try using a key for an unsupported operation. |
| // ------------------------------- |
| algorithmIdentifier = { name: "aes-cbc", iv: originalIv }; |
| shouldThrow("crypto.subtle.encrypt(algorithmIdentifier, aesCbcKeyNoEncrypt)"); |
| |
| // ------------------------------- |
| // Try using an HMAC-SHA1 key for encrypting AES-CBC |
| // ------------------------------- |
| algorithmIdentifier = { name: "aes-cbc", iv: originalIv }; |
| shouldThrow("crypto.subtle.encrypt(algorithmIdentifier, hmacSha1Key)"); |
| |
| // ------------------------------- |
| // Try using an HMAC-SHA1 key for signing HMAC-SHA256 |
| // ------------------------------- |
| algorithmIdentifier = {name: 'hmac', hash: {name: 'sha-256'}}; |
| shouldThrow("crypto.subtle.sign(algorithmIdentifier, hmacSha1Key)"); |
| } |
| |
| function importAesCbcKey(keyUsages) |
| { |
| var keyFormat = "spki"; |
| var data = new Uint8Array([]); |
| var algorithm = {name: "aes-cbc"}; |
| var extractable = false; |
| |
| return crypto.subtle.importKey(keyFormat, data, algorithm, extractable, keyUsages); |
| } |
| |
| function importRsaSsaKey() |
| { |
| var keyFormat = "spki"; |
| var data = new Uint8Array([]); |
| var algorithm = {name: "RSASSA-PKCS1-v1_5"}; |
| var extractable = false; |
| var keyUsages = ["encrypt", "decrypt", "verify", "sign"]; |
| |
| return crypto.subtle.importKey(keyFormat, data, algorithm, extractable, keyUsages); |
| } |
| |
| function failedKeyImport(value) |
| { |
| debug("Failed importing key: " + value); |
| finishJSTest(); |
| } |
| |
| // Import two keys before starting the tests: one for AES-CBC, and one for |
| // HMAC SHA1. |
| Promise.every(importAesCbcKey(['encrypt', 'decrypt', 'sign', 'verify']), importAesCbcKey(['decrypt', 'sign', 'verify']), importHmacSha1Key(), importRsaSsaKey()).then(function(keys) |
| { |
| aesCbcKey = keys[0]; |
| aesCbcKeyNoEncrypt = keys[1]; |
| hmacSha1Key = keys[2]; |
| rsaSsaKey = keys[3]; |
| |
| runTests(); |
| finishJSTest(); |
| |
| }, failedKeyImport); |
| |
| </script> |
| |
| <script src="../fast/js/resources/js-test-post.js"></script> |
| </body> |
| </html> |