Commit 0002e54a authored by eroman@chromium.org's avatar eroman@chromium.org

[webcrypto] Require importKey() for JWK to provide data as a Javascript object...

[webcrypto] Require importKey() for JWK to provide data as a Javascript object rather than a JSON arraybuffer.

BUG=373917,245025

Review URL: https://codereview.chromium.org/336173002

git-svn-id: svn://svn.chromium.org/blink/trunk@176238 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 2d34c638
......@@ -27,10 +27,8 @@ var jwkKey = {
"k": "YD3rEBXKcb4rc67whX13gR81LAc7YQjXLZgQowkU3_Q"
};
var jwkKeyAsArrayBuffer = asciiToUint8Array(JSON.stringify(jwkKey));
debug("Importing a key...\n");
crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, {name: 'AES-CBC'}, false, ["encrypt"]).then(function(result) {
crypto.subtle.importKey("jwk", jwkKey, {name: 'AES-CBC'}, false, ["encrypt"]).then(function(result) {
key = result;
shouldBe("key.type", "'secret'");
......
......@@ -25,13 +25,12 @@ var publicKeyJSON = {
use: "sig"
};
var jwkKeyAsArrayBuffer = asciiToUint8Array(JSON.stringify(publicKeyJSON));
var wrappingKeyOctets = hexStringToUint8Array("2a00e0e776e94e4dc89bf947cebdebe1");
debug("Importing a key to wrap...");
var importAlgorithm = {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'sha-256'} };
crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, importAlgorithm, nonExtractable, ["verify"]).then(function(result) {
crypto.subtle.importKey("jwk", publicKeyJSON, importAlgorithm, nonExtractable, ["verify"]).then(function(result) {
key = result;
shouldBe("key.algorithm.name", "'RSASSA-PKCS1-v1_5'");
debug("Importing a key encryption key...");
......
......@@ -25,12 +25,11 @@ var publicKeyJSON = {
use: "sig"
};
var jwkKeyAsArrayBuffer = asciiToUint8Array(JSON.stringify(publicKeyJSON));
var wrappingKeyOctets = hexStringToUint8Array("2a00e0e776e94e4dc89bf947cebdebe1");
debug("Importing a key to wrap...");
crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, { name: "RSASSA-PKCS1-v1_5", hash: {name: "Sha-256"} }, extractable, ["verify"]).then(function(result) {
crypto.subtle.importKey("jwk", publicKeyJSON, { name: "RSASSA-PKCS1-v1_5", hash: {name: "Sha-256"} }, extractable, ["verify"]).then(function(result) {
key = result;
shouldBe("key.algorithm.name", "'RSASSA-PKCS1-v1_5'");
debug("Importing a key encryption key...");
......
......@@ -21,8 +21,6 @@ var jwkKey = {
k: "jnOw99oOZFLIEPMrgJB55WL46tJSLGt7jnOw99oOZFI"
};
var jwkKeyAsArrayBuffer = asciiToUint8Array(JSON.stringify(jwkKey));
Promise.resolve(null).then(function(result) {
return crypto.subtle.exportKey("raw");
}).then(failAndFinishJSTest, function(result) {
......@@ -41,7 +39,7 @@ Promise.resolve(null).then(function(result) {
logError(result);
debug("\nImporting a JWK key...");
return crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, {name: "AES-CBC"}, extractable, ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']);
return crypto.subtle.importKey("jwk", jwkKey, {name: "AES-CBC"}, extractable, ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']);
}).then(function(result) {
key = result;
......@@ -79,7 +77,7 @@ Promise.resolve(null).then(function(result) {
shouldBe("exportedJWK.key_ops", "['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']");
debug("\nImporting a key that's not extractable...");
return crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, {name: "AES-CBC"}, nonExtractable, ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'])
return crypto.subtle.importKey("jwk", jwkKey, {name: "AES-CBC"}, nonExtractable, ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'])
}).then(function(result) {
key = result;
......
......@@ -21,10 +21,8 @@ var jwkKey = {
"k": "ahjkn-_387fgnsibf23qsvahjkn-_387fgnsibf23qs"
};
var jwkKeyAsArrayBuffer = asciiToUint8Array(JSON.stringify(jwkKey));
debug("Importing a JWK key...");
crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, { name: "HMAC", hash: {name: "SHA-256"} }, extractable, ["sign", "verify"]).then(function(result) {
crypto.subtle.importKey("jwk", jwkKey, { name: "HMAC", hash: {name: "SHA-256"} }, extractable, ["sign", "verify"]).then(function(result) {
key = result;
return crypto.subtle.exportKey(null, key);
......@@ -61,7 +59,7 @@ crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, { name: "HMAC", hash: {name:
shouldBe("exportedJWK.key_ops", "['sign', 'verify']");
debug("\nImporting a key that's not extractable...");
return crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, { name: "HMAC", hash: {name: "SHA-256"} }, nonExtractable, ["sign", "verify"]);
return crypto.subtle.importKey("jwk", jwkKey, { name: "HMAC", hash: {name: "SHA-256"} }, nonExtractable, ["sign", "verify"]);
}, failAndFinishJSTest).then(function(result) {
key = result;
......
......@@ -24,10 +24,8 @@ var hmacKey = {
"k": "ahjkn-_387fgnsibf23qsvahjkn-_387fgnsibf23qs"
};
var hmacKeyAsArrayBuffer = asciiToUint8Array(JSON.stringify(hmacKey));
debug("Importing a key...\n");
crypto.subtle.importKey("jwk", hmacKeyAsArrayBuffer, {name: "HMAC", hash: {name: "SHA-256"}}, nonExtractable, ["sign", "verify"]).then(function(result) {
crypto.subtle.importKey("jwk", hmacKey, {name: "HMAC", hash: {name: "SHA-256"}}, nonExtractable, ["sign", "verify"]).then(function(result) {
key = result;
shouldBe("key.type", "'secret'");
......
......@@ -3,10 +3,8 @@ Test error handling for JWK import.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
error is: DataError: No key data was provided
error is: DataError: JWK input could not be parsed to a JSON dictionary
error is: DataError: JWK input could not be parsed to a JSON dictionary
error is: DataError: JWK input could not be parsed to a JSON dictionary
error is: TypeError: Failed to execute 'importKey' on 'SubtleCrypto': No function was found that matched the signature provided.
error is: TypeError: Failed to execute 'importKey' on 'SubtleCrypto': No function was found that matched the signature provided.
error is: DataError: The required JWK property "kty" was missing
error is: DataError: The JWK "kty" property was unrecognized
error is: DataError: The JWK "alg" property was not recognized
......@@ -16,11 +14,11 @@ error is: DataError: The required JWK property "k" was missing
error is: DataError: The required JWK property "k" was missing
error is: DataError: The JWK "k" property did not include the right length of key data for the given algorithm.
error is: DataError: The JWK "k" property did not include the right length of key data for the given algorithm.
error is: DataError: The JWK property "kty" must be a string
error is: DataError: The JWK property "alg" must be a string
error is: DataError: The JWK property "use" must be a string
error is: DataError: The JWK property "ext" must be a boolean
error is: DataError: The JWK property "k" must be a string
error is: DataError: The JWK "kty" property was unrecognized
error is: DataError: The JWK "alg" property was not recognized
error is: DataError: The JWK "use" property could not be parsed
Boolean JWK property passed as a string and worked
String JWK property passed as a number and worked
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -19,49 +19,43 @@ var nonExtractable = false;
var hmac256 = {name: "HMAC", hash: {name: "sha-256"}};
Promise.resolve(null).then(function(result) {
return crypto.subtle.importKey("jwk", asciiToUint8Array(''), {name: "aes-cbc"}, extractable, []);
return crypto.subtle.importKey("jwk", null, {name: "aes-cbc"}, extractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{'), {name: "aes-cbc"}, extractable, []);
return crypto.subtle.importKey("jwk", undefined, {name: "aes-cbc"}, extractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('null'), {name: "aes-cbc"}, extractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('undefined'), {name: "aes-cbc"}, extractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{}'), {name: "aes-cbc"}, extractable, []);
return crypto.subtle.importKey("jwk", {}, {name: "aes-cbc"}, extractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
// Unknown/invalid JWK values.
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "foobar", "alg": "HS256", "use": "sig", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), hmac256, extractable, []);
return crypto.subtle.importKey("jwk", { "kty": "foobar", "alg": "HS256", "use": "sig", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }, hmac256, extractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "foobar", "use": "sig", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), {name: "aes-cbc"}, extractable, []);
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "foobar", "use": "sig", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }, {name: "aes-cbc"}, extractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
// Algorithm mismatch.
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), {name: "AES-cbc"}, nonExtractable, []);
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }, {name: "AES-cbc"}, nonExtractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), { name: "hmac", hash: {name: "sha-1"} }, nonExtractable, []);
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }, { name: "hmac", hash: {name: "sha-1"} }, nonExtractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
// No key data.
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256" }'), hmac256, extractable, []);
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "HS256" }, hmac256, extractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "A128CBC" }'), {name: "aes-cbc"}, extractable, []);
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "A128CBC" }, {name: "aes-cbc"}, extractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
// FIXME: http://crbug.com/378037
// Key data length is incorrect, not allowed in JWK.
// return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "1234" }'), hmac256, nonExtractable, []);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "A128CBC", "use": "sig", "ext": false, "k": "1234" }'), {name: "aes-cbc"}, nonExtractable, []);
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "A128CBC", "use": "sig", "ext": false, "k": "1234" }, {name: "aes-cbc"}, nonExtractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "A128CBC", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), {name: "aes-cbc"}, nonExtractable, []);
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "A128CBC", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }, {name: "aes-cbc"}, nonExtractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
// Key data is not valid base64url.
......@@ -69,21 +63,23 @@ Promise.resolve(null).then(function(result) {
// return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387f+nsibf23qsvahjkn37387fgnsibf23qs" }'), hmac256, nonExtractable, []);
// Incorrect data types.
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": 1, "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), hmac256, nonExtractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": 1, "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), {name: "aes-cbc"}, nonExtractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": 1, "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), hmac256, nonExtractable, []);
return crypto.subtle.importKey("jwk", { "kty": 1, "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }, hmac256, nonExtractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": "false", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), hmac256, nonExtractable, []);
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": 1, "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }, {name: "aes-cbc"}, nonExtractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
return crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": 1 }'), hmac256, nonExtractable, []);
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "HS256", "use": 1, "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }, hmac256, nonExtractable, []);
}).then(failAndFinishJSTest, function(result) {
logError(result);
// ext is recognized as a boolean even though it is a string.
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "HS256", "use": "sig", "ext": "false", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }, hmac256, nonExtractable, []);
}).then(function(result) {
debug("Boolean JWK property passed as a string and worked");
// k is recognized as a string even though it is a number.
return crypto.subtle.importKey("jwk", { "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": 1258 }, hmac256, nonExtractable, []);
}).then(function(result) {
debug("String JWK property passed as a number and worked");
}).then(finishJSTest, failAndFinishJSTest);
</script>
......
......@@ -3,7 +3,7 @@ Tests calling cypto.subtle.importKey with bad parameters
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
error is: TypeError: Failed to execute 'importKey' on 'SubtleCrypto': No function was found that matched the signature provided.
error is: DataError: Key data must be a buffer for non-JWK formats
error is: TypeError: Failed to execute 'importKey' on 'SubtleCrypto': No function was found that matched the signature provided.
error is: SyntaxError: Algorithm: Not an object
error is: SyntaxError: Invalid keyFormat argument
......
......@@ -39,7 +39,7 @@ function testWithAESCBC(expectedUsages, jwkUsages, importUsages)
aesKeyAsJSON.use = jwkUsages.use;
}
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(aesKeyAsJSON)), {name: "AES-CBC"}, extractable, importUsages).then(function(result) {
return crypto.subtle.importKey("jwk", aesKeyAsJSON, {name: "AES-CBC"}, extractable, importUsages).then(function(result) {
key = result;
debug(JSON.stringify(jwkUsages) + ":");
shouldBe("key.usages", JSON.stringify(expectedUsages));
......@@ -60,7 +60,7 @@ function testWithHMAC(expectedUsages, jwkUsages, importUsages)
hmacKeyAsJSON.use = jwkUsages.use;
}
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(hmacKeyAsJSON)), {name: 'hmac', hash: {name: 'sha-256'}}, extractable, importUsages).then(function(result) {
return crypto.subtle.importKey("jwk", hmacKeyAsJSON, {name: 'hmac', hash: {name: 'sha-256'}}, extractable, importUsages).then(function(result) {
key = result;
debug(JSON.stringify(jwkUsages) + ":");
shouldBe("key.usages", JSON.stringify(expectedUsages));
......
......@@ -23,10 +23,8 @@ var publicKeyJSON = {
e: "AQAB"
};
var jwkKeyAsArrayBuffer = asciiToUint8Array(JSON.stringify(publicKeyJSON));
debug("\nImporting a JWK key...");
crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, extractable, ['verify']).then(function(result) {
crypto.subtle.importKey("jwk", publicKeyJSON, {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, extractable, ['verify']).then(function(result) {
key = result;
return crypto.subtle.exportKey(null, key);
......
......@@ -30,10 +30,9 @@ var privateKeyJSON = {
"alg":"RS256",
"kid":"2011-04-29"
}
var jwkKeyAsArrayBuffer = asciiToUint8Array(JSON.stringify(privateKeyJSON));
debug("\nImporting a JWK key...");
crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, extractable, ['sign']).then(function(result) {
crypto.subtle.importKey("jwk", privateKeyJSON, {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, extractable, ['sign']).then(function(result) {
key = result;
debug("\nExporting the key as JWK...");
......
......@@ -24,7 +24,7 @@ var privateKeyJSON = {
qi: "YCX_pLwbMBA1ThVH0WcwmnytqNcrMCEwTm7ByA2eU6nWbQrULvf7m9_kzfLUcjsnpAVlBQG5JMXMy0Sq4ptwbywsa5-G8KAOOOR2L3v4hC-Eys9ftgFM_3i0o40eeQH4b3haPbntrIeMg8IzlOuVYKf9-2QuKDoWeRdd7NsdxTk"
};
crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(privateKeyJSON)), {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, true, ["sign"]).then(function(key) {
crypto.subtle.importKey("jwk", privateKeyJSON, {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, true, ["sign"]).then(function(key) {
var openRequest = indexedDB.open("crypto_subtle");
openRequest.onupgradeneeded = function(event) {
var objectStore = event.target.result.createObjectStore("rsa-indexeddb");
......
......@@ -71,7 +71,7 @@ crypto.subtle.generateKey(algorithmKeyGen, extractable, ["encrypt", "decrypt", "
shouldBe("bytesToHexString(Base64URL.parse(jwkPublicKey.e))", "'010001'");
debug("\nImporting it back...");
return crypto.subtle.importKey("jwk", jwkPublicKeyArray, { name: "RSA-OAEP", hash: {name: "sha-1"} }, extractable, ["encrypt", "wrapKey"]);
return crypto.subtle.importKey("jwk", jwkPublicKey, { name: "RSA-OAEP", hash: {name: "sha-1"} }, extractable, ["encrypt", "wrapKey"]);
}).then(function(result) {
exportedPublicKey = result;
shouldBe("exportedPublicKey.type", "'public'");
......
......@@ -37,9 +37,9 @@ var extractable = true;
var nonExtractable = false;
debug("Importing RSA keys...");
crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(publicKeyJSON)), {name:"rsa-oaep", hash:{name: "sha-1"}}, extractable, ["encrypt"]).then(function(result) {
crypto.subtle.importKey("jwk", publicKeyJSON, {name:"rsa-oaep", hash:{name: "sha-1"}}, extractable, ["encrypt"]).then(function(result) {
publicKey = result;
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(privateKeyJSON)), {name:"rsa-oaep", hash:{name: "sha-1"}}, extractable, ["decrypt"]);
return crypto.subtle.importKey("jwk", privateKeyJSON, {name:"rsa-oaep", hash:{name: "sha-1"}}, extractable, ["decrypt"]);
}, failAndFinishJSTest).then(function(result) {
privateKey = result;
......
......@@ -39,9 +39,9 @@ var nonExtractable = false;
var importAlgorithm = {name: "rsa-oaep", hash: {name:"sha-1"}};
debug("Importing RSA keys...");
crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(publicKeyJSON)), importAlgorithm, extractable, ["wrapKey"]).then(function(result) {
crypto.subtle.importKey("jwk", publicKeyJSON, importAlgorithm, extractable, ["wrapKey"]).then(function(result) {
publicKey = result;
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(privateKeyJSON)), importAlgorithm, extractable, ["unwrapKey"]);
return crypto.subtle.importKey("jwk", privateKeyJSON, importAlgorithm, extractable, ["unwrapKey"]);
}).then(function(result) {
privateKey = result;
......
......@@ -39,11 +39,11 @@ var privateKeyJSON = {
};
Promise.resolve(null).then(function(result) {
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(publicKeyJSON)), {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'sha-256'}}, extractable, ["verify"]);
return crypto.subtle.importKey("jwk", publicKeyJSON, {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'sha-256'}}, extractable, ["verify"]);
}).then(function(result) {
key = result;
shouldEvaluateAs("key.algorithm.modulusLength", 1024);
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(privateKeyJSON)), {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'sha-512'}}, extractable, ["sign"]);
return crypto.subtle.importKey("jwk", privateKeyJSON, {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'sha-512'}}, extractable, ["sign"]);
}).then(function(result) {
key = result;
shouldEvaluateAs("key.algorithm.modulusLength", 1024);
......
......@@ -36,7 +36,7 @@ var privateKeyJSON = {
};
debug("Importing a public key...");
crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(publicKeyJSON)), {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, extractable, ["verify"]).then(function(result) {
crypto.subtle.importKey("jwk", publicKeyJSON, {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, extractable, ["verify"]).then(function(result) {
publicKey = result;
shouldBe("publicKey.toString()", "'[object Key]'");
shouldBe("publicKey.type", "'public'");
......@@ -46,7 +46,7 @@ crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(publicKeyJSON)),
shouldBe("bytesToHexString(publicKey.algorithm.publicExponent)", "'010001'");
shouldBe("publicKey.algorithm.hash.name", "'SHA-256'");
debug("\nImporting a private key...");
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(privateKeyJSON)), {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, extractable, ["sign"]);
return crypto.subtle.importKey("jwk", privateKeyJSON, {name: "RSASSA-PKCS1-v1_5", hash: {name: "sha-256"}}, extractable, ["sign"]);
}).then(function(result) {
privateKey = result;
shouldBe("privateKey.toString()", "'[object Key]'");
......
......@@ -38,10 +38,10 @@ var privateKeyJSON = {
var data = asciiToUint8Array("Hello, world!");
debug("Importing a public key...");
crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(publicKeyJSON)), { name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256"} }, extractable, ["verify"]).then(function(result) {
crypto.subtle.importKey("jwk", publicKeyJSON, { name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256"} }, extractable, ["verify"]).then(function(result) {
publicKey = result;
debug("\nImporting a private key...");
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(privateKeyJSON)), { name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256"} }, extractable, ["sign"]);
return crypto.subtle.importKey("jwk", privateKeyJSON, { name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256"} }, extractable, ["sign"]);
}).then(function(result) {
privateKey = result;
debug("\nSigning some text...");
......
......@@ -36,6 +36,7 @@
#include "modules/crypto/CryptoResultImpl.h"
#include "modules/crypto/Key.h"
#include "modules/crypto/NormalizeAlgorithm.h"
#include "platform/JSONValues.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCrypto.h"
#include "public/platform/WebCryptoAlgorithm.h"
......@@ -65,7 +66,7 @@ static bool ensureNotNull(Key* key, const char* paramName, CryptoResult* result)
return true;
}
bool parseAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, CryptoResult* result)
static bool parseAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, CryptoResult* result)
{
AlgorithmError error;
bool success = normalizeAlgorithm(raw, op, algorithm, &error);
......@@ -136,6 +137,57 @@ static ScriptPromise startCryptoOperation(ScriptState* scriptState, const Dictio
return promise;
}
static bool copyStringProperty(const char* property, const Dictionary& source, JSONObject* destination)
{
String value;
if (!source.get(property, value))
return false;
destination->setString(property, value);
return true;
}
static bool copySequenceOfStringProperty(const char* property, const Dictionary& source, JSONObject* destination)
{
Vector<String> value;
if (!source.get(property, value))
return false;
RefPtr<JSONArray> jsonArray = JSONArray::create();
for (unsigned i = 0; i < value.size(); ++i)
jsonArray->pushString(value[i]);
destination->setArray(property, jsonArray.release());
return true;
}
// FIXME: At the time of writing this is not a part of the spec. It is based an
// an unpublished editor's draft for:
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=24963
// See http://crbug.com/373917.
static bool copyJwkDictionaryToJson(const Dictionary& dict, CString& jsonUtf8, CryptoResult* result)
{
RefPtr<JSONObject> jsonObject = JSONObject::create();
if (!copyStringProperty("kty", dict, jsonObject.get())) {
result->completeWithError(blink::WebCryptoErrorTypeData, "The required JWK property \"kty\" was missing");
return false;
}
copyStringProperty("use", dict, jsonObject.get());
copySequenceOfStringProperty("key_ops", dict, jsonObject.get());
copyStringProperty("alg", dict, jsonObject.get());
bool ext;
if (dict.get("ext", ext))
jsonObject->setBoolean("ext", ext);
const char* const propertyNames[] = { "d", "n", "e", "p", "q", "dp", "dq", "qi", "k" };
for (unsigned i = 0; i < WTF_ARRAY_LENGTH(propertyNames); ++i)
copyStringProperty(propertyNames[i], dict, jsonObject.get());
String json = jsonObject->toJSONString();
jsonUtf8 = json.utf8();
return true;
}
SubtleCrypto::SubtleCrypto()
{
ScriptWrappable::init(this);
......@@ -201,6 +253,11 @@ ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& ra
if (!Key::parseFormat(rawFormat, format, result.get()))
return promise;
if (format == blink::WebCryptoKeyFormatJwk) {
result->completeWithError(blink::WebCryptoErrorTypeData, "Key data must be an object for JWK import");
return promise;
}
blink::WebCryptoKeyUsageMask keyUsages;
if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get()))
return promise;
......@@ -213,6 +270,39 @@ ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& ra
return promise;
}
ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& rawFormat, const Dictionary& keyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages)
{
RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState);
ScriptPromise promise = result->promise();
if (!canAccessWebCrypto(scriptState, result.get()))
return promise;
blink::WebCryptoKeyFormat format;
if (!Key::parseFormat(rawFormat, format, result.get()))
return promise;
blink::WebCryptoKeyUsageMask keyUsages;
if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get()))
return promise;
if (format != blink::WebCryptoKeyFormatJwk) {
result->completeWithError(blink::WebCryptoErrorTypeData, "Key data must be a buffer for non-JWK formats");
return promise;
}
blink::WebCryptoAlgorithm algorithm;
if (!parseAlgorithm(rawAlgorithm, blink::WebCryptoOperationImportKey, algorithm, result.get()))
return promise;
CString jsonUtf8;
if (!copyJwkDictionaryToJson(keyData, jsonUtf8, result.get()))
return promise;
blink::Platform::current()->crypto()->importKey(format, reinterpret_cast<const unsigned char*>(jsonUtf8.data()), jsonUtf8.length(), algorithm, extractable, keyUsages, result->result());
return promise;
}
ScriptPromise SubtleCrypto::exportKey(ScriptState* scriptState, const String& rawFormat, Key* key)
{
RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState);
......
......@@ -59,6 +59,7 @@ public:
ScriptPromise generateKey(ScriptState*, const Dictionary&, bool extractable, const Vector<String>& keyUsages);
ScriptPromise importKey(ScriptState*, const String&, const ArrayPiece&, const Dictionary&, bool extractable, const Vector<String>& keyUsages);
ScriptPromise importKey(ScriptState*, const String&, const Dictionary&, const Dictionary&, bool extractable, const Vector<String>& keyUsages);
ScriptPromise exportKey(ScriptState*, const String&, Key*);
ScriptPromise wrapKey(ScriptState*, const String&, Key*, Key*, const Dictionary&);
......
......@@ -59,6 +59,7 @@ typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData;
[CallWith=ScriptState] Promise importKey(KeyFormat format, ArrayBuffer keyData, Dictionary algorithm, boolean extractable, KeyUsage[] keyUsages);
[CallWith=ScriptState] Promise importKey(KeyFormat format, ArrayBufferView keyData, Dictionary algorithm, boolean extractable, KeyUsage[] keyUsages);
[CallWith=ScriptState] Promise importKey(KeyFormat format, Dictionary keyData, Dictionary algorithm, boolean extractable, KeyUsage[] keyUsages);
[CallWith=ScriptState] Promise exportKey(KeyFormat format, Key key);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment