Commit e6074e79 authored by ap@apple.com's avatar ap@apple.com

Update WebCrypto JWK mapping to newer proposal

https://bugs.webkit.org/show_bug.cgi?id=124218

Reviewed by Anders Carlsson.

Source/WebCore: 

Tests: crypto/subtle/jwk-export-use-values.html
       crypto/subtle/jwk-import-use-values.html

1. "extractable" renamed to "ext" in JWK.
2. New values for "use" mapping, which can now be combined into comma separated lists,
and cover all possible WebCrypto usages.

* bindings/js/JSCryptoKeySerializationJWK.cpp:
(WebCore::JSCryptoKeySerializationJWK::reconcileUsages):
(WebCore::JSCryptoKeySerializationJWK::reconcileExtractable):
(WebCore::JSCryptoKeySerializationJWK::addJWKAlgorithmToJSON):
(WebCore::processUseValue):
(WebCore::JSCryptoKeySerializationJWK::addJWKUseToJSON):
(WebCore::JSCryptoKeySerializationJWK::serialize):

LayoutTests: 

* crypto/subtle/jwk-export-use-values-expected.txt: Added.
* crypto/subtle/jwk-export-use-values.html: Added.
* crypto/subtle/jwk-import-use-values-expected.txt: Added.
* crypto/subtle/jwk-import-use-values.html: Added.
New tests for "use" mapping.

* crypto/subtle/aes-cbc-import-jwk.html:
* crypto/subtle/aes-cbc-unwrap-rsa.html:
* crypto/subtle/aes-cbc-wrap-rsa-non-extractable.html:
* crypto/subtle/aes-cbc-wrap-rsa.html:
* crypto/subtle/aes-export-key-expected.txt:
* crypto/subtle/aes-export-key.html:
* crypto/subtle/hmac-export-key-expected.txt:
* crypto/subtle/hmac-export-key.html:
* crypto/subtle/hmac-import-jwk.html:
* crypto/subtle/import-jwk-expected.txt:
* crypto/subtle/import-jwk.html:
* crypto/subtle/rsa-export-key-expected.txt:
* crypto/subtle/rsa-export-key.html:
* crypto/subtle/rsa-export-private-key-expected.txt:
* crypto/subtle/rsa-export-private-key.html:
* crypto/subtle/rsa-oaep-key-manipulation-expected.txt:
* crypto/subtle/rsa-oaep-key-manipulation.html:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@160061 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 0a661907
2013-12-03 Alexey Proskuryakov <ap@apple.com>
Update WebCrypto JWK mapping to newer proposal
https://bugs.webkit.org/show_bug.cgi?id=124218
Reviewed by Anders Carlsson.
* crypto/subtle/jwk-export-use-values-expected.txt: Added.
* crypto/subtle/jwk-export-use-values.html: Added.
* crypto/subtle/jwk-import-use-values-expected.txt: Added.
* crypto/subtle/jwk-import-use-values.html: Added.
New tests for "use" mapping.
* crypto/subtle/aes-cbc-import-jwk.html:
* crypto/subtle/aes-cbc-unwrap-rsa.html:
* crypto/subtle/aes-cbc-wrap-rsa-non-extractable.html:
* crypto/subtle/aes-cbc-wrap-rsa.html:
* crypto/subtle/aes-export-key-expected.txt:
* crypto/subtle/aes-export-key.html:
* crypto/subtle/hmac-export-key-expected.txt:
* crypto/subtle/hmac-export-key.html:
* crypto/subtle/hmac-import-jwk.html:
* crypto/subtle/import-jwk-expected.txt:
* crypto/subtle/import-jwk.html:
* crypto/subtle/rsa-export-key-expected.txt:
* crypto/subtle/rsa-export-key.html:
* crypto/subtle/rsa-export-private-key-expected.txt:
* crypto/subtle/rsa-export-private-key.html:
* crypto/subtle/rsa-oaep-key-manipulation-expected.txt:
* crypto/subtle/rsa-oaep-key-manipulation.html:
2013-12-03 Alexey Proskuryakov <ap@apple.com>
Layout Test platform/mac/accessibility/search-predicate-element-count.html is flaky
......
......@@ -22,7 +22,7 @@ var jwkKey = {
"kty": "oct",
"alg": "A192CBC",
"use": "enc",
"extractable": true,
"ext": true,
"k": "jnOw99oOZFLIEPMrgJB55WL46tJSLGt7"
};
......
......@@ -21,12 +21,12 @@ var publicKeyJSON = {
alg: "RS256",
n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
e: "AQAB",
extractable: false,
ext: false,
use: "sig"
};
var unwrappingKeyOctets = hexStringToUint8Array("2a00e0e776e94e4dc89bf947cebdebe1");
var wrappedKey = hexStringToUint8Array("3511f6028db04ea97e7cfad3c4cc60837bceff25cb6c88292fbcb4547570afdc32e4003fe4d65f1e7df60dc1fdb3df36c3f58ab228e33aa31005852d46d0c2ad1318435a071bbb5bbb05650ea63d551698b0c040dd95ed0d379b5e2eccb545ae5620acb8051174cd2ad647328ad99dcd462fec40748724eb1e68f209f779faa2c35b4d4d1b6604a74e62a1846249ea6192954a5af10c71ebfea79948142441ed307e9f52e797a51a8007a6f87b57c51f9e7eef54b7e4a1f818ba6ac25ee5935c23b3253d6d9d222262c79ccdb7147d9c07527c22fe7a4ab91af20479edf5930b3c053c0a0b27092cfb53203633d01dcf6e333b5be7c1933c321c953f962b934ebefd9df8cca6c0a25fcd5fb96105435c42d9902406f82bc8daa8ec12fa85d9afa65adbfe3f60828ef64adaf43ad8e3b0af104cbfafd994323732bba08f84d5cac1d157b276233dffecafe47942b83c85ead6d5886c6badf534d4a32d3f545e8032dd5e419d7bff3acde2c37a96fc34fda8747d89500bf9f7ef45873c6b3b274197c184fe91badeeddf5045f982ecc66b61e0c4d75fd496c61ffcbb36e079faf20aa0c05cd12742aefdf1f6a39c4a9c5a");
var wrappedKey = hexStringToUint8Array("3511f6028db04ea97e7cfad3c4cc60837bceff25cb6c88292fbcb4547570afdc32e4003fe4d65f1e7df60dc1fdb3df36c3f58ab228e33aa31005852d46d0c2ad1318435a071bbb5bbb05650ea63d551698b0c040dd95ed0d379b5e2eccb545ae5620acb8051174cd2ad647328ad99dcd462fec40748724eb1e68f209f779faa2c35b4d4d1b6604a74e62a1846249ea6192954a5af10c71ebfea79948142441ed307e9f52e797a51a8007a6f87b57c51f9e7eef54b7e4a1f818ba6ac25ee5935c23b3253d6d9d222262c79ccdb7147d9c07527c22fe7a4ab91af20479edf5930b3c053c0a0b27092cfb53203633d01dcf6e333b5be7c1933c321c953f962b934ebefd9df8cca6c0a25fcd5fb96105435c42d9902406f82bc8daa8ec12fa85d9afa65adbfe3f60828ef64adaf43ad8e3b0af104cbfafd994323732bba08f84d5cac1d157b276233dffecafe47942b83c85ead6d5886c6badf534d4a32d3f545e8032dd5e419d7bff3acde2c37a96fc34fda8747d89500bf9f7ef45873c6b3b2741aaf74ff96a2f950028f38eb62f1be936fe0a994ebfa928021c0c96172d84584e");
debug("Importing an unwrapping key...");
crypto.subtle.importKey("raw", unwrappingKeyOctets, "AES-CBC", nonExtractable, ["unwrapKey"]).then(function(result) {
......
......@@ -21,7 +21,7 @@ var publicKeyJSON = {
alg: "RS256",
n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
e: "AQAB",
extractable: false,
ext: false,
use: "sig"
};
......
......@@ -21,7 +21,7 @@ var publicKeyJSON = {
alg: "RS256",
n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
e: "AQAB",
extractable: true,
ext: true,
use: "sig"
};
......
......@@ -22,7 +22,7 @@ Exporting the key as JWK...
PASS exportedJWK.kty is 'oct'
PASS exportedJWK.k is 'jnOw99oOZFLIEPMrgJB55WL46tJSLGt7'
PASS exportedJWK.alg is 'A192CBC'
PASS exportedJWK.extractable is true
PASS exportedJWK.ext is true
PASS exportedJWK.use is 'enc'
Importing a key that's not extractable...
......@@ -31,9 +31,6 @@ Trying to export as raw...
PASS Rejected, as expected
Trying to export as jwk...
PASS Rejected, as expected
Importing a key with only encrypt+decrypt usage (this doesn't map to anything in JWK, as 'enc' also allows wrap/unwrap)...
PASS crypto.subtle.exportKey("jwk", key) threw exception TypeError: Key usages cannot be represented in JWK. Only two variants are supported: sign+verify and encrypt+decrypt+wrapKey+unwrapKey.
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -52,7 +52,7 @@ crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, "AES-CBC", extractable, ['en
shouldBe("exportedJWK.kty", "'oct'");
shouldBe("exportedJWK.k", "'jnOw99oOZFLIEPMrgJB55WL46tJSLGt7'");
shouldBe("exportedJWK.alg", "'A192CBC'");
shouldBe("exportedJWK.extractable", "true");
shouldBe("exportedJWK.ext", "true");
shouldBe("exportedJWK.use", "'enc'");
debug("\nImporting a key that's not extractable...");
......@@ -76,16 +76,6 @@ crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, "AES-CBC", extractable, ['en
}, function() {
testPassed("Rejected, as expected");
// If this test starts to fail because a way to encode encrypt+decrypt is added to JWK, change to something that's not there.
// If all WebCrypto modes are added to JWK, then this test will be obsolete.
debug("\nImporting a key with only encrypt+decrypt usage (this doesn't map to anything in JWK, as 'enc' also allows wrap/unwrap)...");
return crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, "AES-CBC", extractable, ['encrypt', 'decrypt'])
}).then(function(result) {
key = result;
// Maybe this should be a rejected promise, not an exception. We'll need to find a way to provide meaningful error messages with such failures.
shouldThrow('crypto.subtle.exportKey("jwk", key)');
finishJSTest();
});
</script>
......
......@@ -15,7 +15,7 @@ Exporting the key as JWK...
PASS exportedJWK.kty is 'oct'
PASS exportedJWK.k is 'ahjkn-_387fgnsibf23qsvahjkn-_387fgnsibf23qs'
PASS exportedJWK.alg is 'HS256'
PASS exportedJWK.extractable is true
PASS exportedJWK.ext is true
PASS exportedJWK.use is 'sig'
Importing a key that's not extractable...
......@@ -24,9 +24,6 @@ Trying to export as raw...
PASS Rejected, as expected
Trying to export as jwk...
PASS Rejected, as expected
Importing a key with only sign usage (this doesn't map to anything in JWK, as 'sig' allows both sign and verify)...
PASS crypto.subtle.exportKey("jwk", key) threw exception TypeError: Key usages cannot be represented in JWK. Only two variants are supported: sign+verify and encrypt+decrypt+wrapKey+unwrapKey.
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -46,7 +46,7 @@ crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, { name: "HMAC", hash: "SHA-2
shouldBe("exportedJWK.kty", "'oct'");
shouldBe("exportedJWK.k", "'ahjkn-_387fgnsibf23qsvahjkn-_387fgnsibf23qs'");
shouldBe("exportedJWK.alg", "'HS256'");
shouldBe("exportedJWK.extractable", "true");
shouldBe("exportedJWK.ext", "true");
shouldBe("exportedJWK.use", "'sig'");
debug("\nImporting a key that's not extractable...");
......@@ -70,16 +70,6 @@ crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, { name: "HMAC", hash: "SHA-2
}, function() {
testPassed("Rejected, as expected");
// If this test starts to fail because a way to encode encrypt+decrypt is added to JWK, change to something that's not there.
// If all WebCrypto modes are added to JWK, then this test will be obsolete.
debug("\nImporting a key with only sign usage (this doesn't map to anything in JWK, as 'sig' allows both sign and verify)...");
return crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, { name: "HMAC", hash: "SHA-256" }, extractable, ['sign'])
}).then(function(result) {
key = result;
// Maybe this should be a rejected promise, not an exception. We'll need to find a way to provide meaningful error messages with such failures.
shouldThrow('crypto.subtle.exportKey("jwk", key)');
finishJSTest();
});
</script>
......
......@@ -19,7 +19,7 @@ var hmacKey = {
"kty": "oct",
"alg": "HS256",
"use": "sig",
"extractable": false,
"ext": false,
"k": "ahjkn-_387fgnsibf23qsvahjkn-_387fgnsibf23qs"
};
......
......@@ -11,19 +11,19 @@ PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{}'), null) threw excepti
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{}'), "aes-cbc") threw exception TypeError: Required JWK "kty" member is missing.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "foobar", "alg": "HS256", "use": "sig", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Unsupported JWK key type foobar.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "foobar", "use": "sig", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Unsupported JWK algorithm foobar.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), "aes-cbc") threw exception TypeError: Algorithm specified in key is not compatible with one passed to importKey as argument.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), { name: "hmac", hash: "sha-1" }) threw exception TypeError: Algorithm specified in key is not compatible with one passed to importKey as argument.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), "aes-cbc") threw exception TypeError: Algorithm specified in key is not compatible with one passed to importKey as argument.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), { name: "hmac", hash: "sha-1" }) threw exception TypeError: Algorithm specified in key is not compatible with one passed to importKey as argument.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256" }'), null) threw exception TypeError: Secret key data is not present is JWK.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "A128CBC" }'), null) threw exception TypeError: Secret key data is not present is JWK.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": "1234" }'), null) threw exception TypeError: Key size is not valid for HS256.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "A128CBC", "use": "sig", "extractable": false, "k": "1234" }'), null) threw exception TypeError: Key size is not valid for A128CBC.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "A128CBC", "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Key size is not valid for A128CBC.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": "ahjkn23387f+nsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Cannot decode base64url key data in JWK.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": 1, "alg": "HS256", "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Expected a string value for "kty" JSON key.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": 1, "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Expected a string value for "alg" JSON key.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": 1, "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Expected a string value for "use" JSON key.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": "false", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Expected a boolean value for "extractable" JSON key.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": 1 }'), null) threw exception TypeError: Expected a string value for "k" JSON key.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "1234" }'), null) threw exception TypeError: Key size is not valid for HS256.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "A128CBC", "use": "sig", "ext": false, "k": "1234" }'), null) threw exception TypeError: Key size is not valid for A128CBC.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "A128CBC", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Key size is not valid for A128CBC.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387f+nsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Cannot decode base64url key data in JWK.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": 1, "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Expected a string value for "kty" JSON key.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": 1, "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Expected a string value for "alg" JSON key.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": 1, "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Expected a string value for "use" JSON key.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": "false", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }'), null) threw exception TypeError: Expected a boolean value for "ext" JSON key.
PASS crypto.subtle.importKey("jwk", asciiToUint8Array('{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": 1 }'), null) threw exception TypeError: Expected a string value for "k" JSON key.
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -23,27 +23,27 @@ shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "foobar
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "foobar", "use": "sig", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
// Algorithm mismatch.
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), "aes-cbc")')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), { name: "hmac", hash: "sha-1" })')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), "aes-cbc")')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), { name: "hmac", hash: "sha-1" })')
// No key data.
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "A128CBC" }\'), null)')
// Key data length is incorrect, not allowed in JWK.
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": "1234" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "A128CBC", "use": "sig", "extractable": false, "k": "1234" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "A128CBC", "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "1234" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "A128CBC", "use": "sig", "ext": false, "k": "1234" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "A128CBC", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
// Key data is not valid base64url.
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": "ahjkn23387f+nsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387f+nsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
// Incorrect data types.
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": 1, "alg": "HS256", "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": 1, "use": "sig", "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": 1, "extractable": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": "false", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "extractable": false, "k": 1 }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": 1, "alg": "HS256", "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": 1, "use": "sig", "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": 1, "ext": false, "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": "false", "k": "ahjkn23387fgnsibf23qsvahjkn37387fgnsibf23qs" }\'), null)')
shouldThrow('crypto.subtle.importKey("jwk", asciiToUint8Array(\'{ "kty": "oct", "alg": "HS256", "use": "sig", "ext": false, "k": 1 }\'), null)')
</script>
<script src="../../resources/js-test-post.js"></script>
......
Test exporting keys with various usages to JWK.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
encrypt:
PASS jwk.use is 'enconly'
decrypt:
PASS jwk.use is 'deconly'
encrypt,decrypt:
PASS jwk.use is 'enconly,deconly'
wrapKey:
PASS jwk.use is 'wrap'
unwrapKey:
PASS jwk.use is 'unwrap'
wrapKey,unwrapKey:
PASS jwk.use is 'wrap,unwrap'
encrypt,decrypt,wrapKey:
PASS jwk.use is 'enconly,deconly,wrap'
encrypt,decrypt,wrapKey,unwrapKey:
PASS jwk.use is 'enc'
sign:
PASS jwk.use is 'sigonly'
verify:
PASS jwk.use is 'vfyonly'
sign,verify:
PASS jwk.use is 'sig'
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<script src="resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>
description("Test exporting keys with various usages to JWK.");
jsTestIsAsync = true;
var extractable = true;
var aesKeyAsArrayBuffer = Base64URL.parse("jnOw99oOZFLIEPMrgJB55WL46tJSLGt7");
var hmacKeyAsArrayBuffer = Base64URL.parse("ahjkn-_387fgnsibf23qsvahjkn-_387fgnsibf23qs");
function testWithAESCBC(usages, expectedUse)
{
return crypto.subtle.importKey("raw", aesKeyAsArrayBuffer, "AES-CBC", extractable, usages).then(function(result) {
return crypto.subtle.exportKey("jwk", result);
}).then(function(result) {
jwk = JSON.parse(bytesToASCIIString(result));
debug(usages + ":");
shouldBe("jwk.use", "'" + expectedUse + "'");
debug("");
});
}
function testWithHMAC(usages, expectedUse)
{
return crypto.subtle.importKey("raw", hmacKeyAsArrayBuffer, {name: 'hmac', hash: {name: 'sha-256'}}, extractable, usages).then(function(result) {
return crypto.subtle.exportKey("jwk", result);
}).then(function(result) {
jwk = JSON.parse(bytesToASCIIString(result));
debug(usages + ":");
shouldBe("jwk.use", "'" + expectedUse + "'");
debug("");
});
}
Promise.all([
testWithAESCBC(["encrypt"], "enconly"),
testWithAESCBC(["decrypt"], "deconly"),
testWithAESCBC(["encrypt", "decrypt"], "enconly,deconly"),
testWithAESCBC(["wrapKey"], "wrap"),
testWithAESCBC(["unwrapKey"], "unwrap"),
testWithAESCBC(["wrapKey", "unwrapKey"], "wrap,unwrap"),
testWithAESCBC(["encrypt", "decrypt", "wrapKey"], "enconly,deconly,wrap"),
testWithAESCBC(["encrypt", "decrypt", "wrapKey", "unwrapKey"], "enc"),
testWithHMAC(["sign"], "sigonly"),
testWithHMAC(["verify"], "vfyonly"),
testWithHMAC(["sign", "verify"], "sig"),
]).then(function() { finishJSTest(); } );
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
Test importing keys with various uses from JWK.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
enconly:
PASS key.usages is ["encrypt"]
deconly:
PASS key.usages is ["decrypt"]
enconly,deconly:
PASS key.usages is ["encrypt","decrypt"]
wrap:
PASS key.usages is ["wrapKey"]
unwrap:
PASS key.usages is ["unwrapKey"]
wrap,unwrap:
PASS key.usages is ["wrapKey","unwrapKey"]
enconly,deconly,wrap:
PASS key.usages is ["encrypt","decrypt","wrapKey"]
enc:
PASS key.usages is ["encrypt","decrypt","wrapKey","unwrapKey"]
sigonly:
PASS key.usages is ["sign"]
vfyonly:
PASS key.usages is ["verify"]
sig:
PASS key.usages is ["sign","verify"]
'enconly':
PASS key.usages is []
enconly :
PASS key.usages is []
EncOnly:
PASS key.usages is []
enconly, deconly:
PASS key.usages is ["encrypt"]
enconly,,deconly:
PASS key.usages is ["encrypt","decrypt"]
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<script src="resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>
description("Test importing keys with various uses from JWK.");
jsTestIsAsync = true;
var extractable = true;
var aesKeyAsJSON = {
"alg": "A192CBC",
"ext": true,
"kty": "oct",
"k": "jnOw99oOZFLIEPMrgJB55WL46tJSLGt7"
};
var hmacKeyAsJSON = {
"alg": "HS256",
"ext": true,
"kty": "oct",
"k": "ahjkn-_387fgnsibf23qsvahjkn-_387fgnsibf23qs"
};
function testWithAESCBC(expectedUsages, use)
{
aesKeyAsJSON.use = use;
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(aesKeyAsJSON)), "AES-CBC", extractable, ["encrypt", "decrypt", "wrapKey", "unwrapKey"]).then(function(result) {
key = result;
debug(use + ":");
shouldBe("key.usages", JSON.stringify(expectedUsages));
debug("");
});
}
function testWithHMAC(expectedUsages, use)
{
hmacKeyAsJSON.use = use;
return crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(hmacKeyAsJSON)), {name: 'hmac', hash: {name: 'sha-256'}}, extractable, ["sign", "verify"]).then(function(result) {
key = result;
debug(use + ":");
shouldBe("key.usages", JSON.stringify(expectedUsages));
debug("");
});
}
Promise.all([
testWithAESCBC(["encrypt"], "enconly"),
testWithAESCBC(["decrypt"], "deconly"),
testWithAESCBC(["encrypt", "decrypt"], "enconly,deconly"),
testWithAESCBC(["wrapKey"], "wrap"),
testWithAESCBC(["unwrapKey"], "unwrap"),
testWithAESCBC(["wrapKey", "unwrapKey"], "wrap,unwrap"),
testWithAESCBC(["encrypt", "decrypt", "wrapKey"], "enconly,deconly,wrap"),
testWithAESCBC(["encrypt", "decrypt", "wrapKey", "unwrapKey"], "enc"),
testWithHMAC(["sign"], "sigonly"),
testWithHMAC(["verify"], "vfyonly"),
testWithHMAC(["sign", "verify"], "sig"),
// Incorrect use strings. There is currently no spec for what to do, but ignoring unknown uses seems right.
testWithAESCBC([], "'enconly'"),
testWithAESCBC([], "enconly "),
testWithAESCBC([], "EncOnly"),
testWithAESCBC(["encrypt"], "enconly, deconly"),
testWithAESCBC(["encrypt", "decrypt"], "enconly,,deconly"),
]).then(function() { finishJSTest(); } );
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
......@@ -16,7 +16,7 @@ PASS exportedJWK.kty is 'RSA'
PASS exportedJWK.n is publicKeyJSON.n
PASS exportedJWK.e is publicKeyJSON.e
PASS exportedJWK.alg is 'RS256'
PASS exportedJWK.extractable is true
PASS exportedJWK.ext is true
PASS exportedJWK.use is 'sig'
PASS successfullyParsed is true
......
......@@ -44,7 +44,7 @@ crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, "RSASSA-PKCS1-v1_5", extract
shouldBe("exportedJWK.n", "publicKeyJSON.n");
shouldBe("exportedJWK.e", "publicKeyJSON.e");
shouldBe("exportedJWK.alg", "'RS256'");
shouldBe("exportedJWK.extractable", "true");
shouldBe("exportedJWK.ext", "true");
shouldBe("exportedJWK.use", "'sig'");
finishJSTest();
......
......@@ -18,7 +18,7 @@ PASS exportedJWK.dq is privateKeyJSON.dq
PASS exportedJWK.qi is privateKeyJSON.qi
PASS exportedJWK.oth is privateKeyJSON.oth
PASS exportedJWK.alg is privateKeyJSON.alg
PASS exportedJWK.extractable is true
PASS exportedJWK.ext is true
PASS exportedJWK.use is 'sig'
PASS successfullyParsed is true
......
......@@ -52,7 +52,7 @@ crypto.subtle.importKey("jwk", jwkKeyAsArrayBuffer, "RSASSA-PKCS1-v1_5", extract
shouldBe("exportedJWK.qi", "privateKeyJSON.qi");
shouldBe("exportedJWK.oth", "privateKeyJSON.oth");
shouldBe("exportedJWK.alg", "privateKeyJSON.alg");
shouldBe("exportedJWK.extractable", "true");
shouldBe("exportedJWK.ext", "true");
shouldBe("exportedJWK.use", "'sig'");
finishJSTest();
......
......@@ -26,7 +26,7 @@ PASS Promise rejected for exporting private key
Exporting public key to JWK...
PASS jwkPublicKey.alg is 'RSA-OAEP'
PASS jwkPublicKey.extractable is true
PASS jwkPublicKey.ext is true
PASS jwkPublicKey.use is 'enc'
PASS jwkPublicKey.kty is 'RSA'
PASS bytesToHexString(Base64URL.parse(jwkPublicKey.e)) is '010001'
......
......@@ -55,7 +55,7 @@ crypto.subtle.generateKey(algorithmKeyGen, extractable, ["encrypt", "decrypt", "
jwkPublicKeyArray = result;
jwkPublicKey = JSON.parse(bytesToASCIIString(jwkPublicKeyArray));
shouldBe("jwkPublicKey.alg", "'RSA-OAEP'");
shouldBe("jwkPublicKey.extractable", "true");
shouldBe("jwkPublicKey.ext", "true");
shouldBe("jwkPublicKey.use", "'enc'");
shouldBe("jwkPublicKey.kty", "'RSA'");
shouldBe("bytesToHexString(Base64URL.parse(jwkPublicKey.e))", "'010001'");
......
2013-12-03 Alexey Proskuryakov <ap@apple.com>
Update WebCrypto JWK mapping to newer proposal
https://bugs.webkit.org/show_bug.cgi?id=124218
Reviewed by Anders Carlsson.
Tests: crypto/subtle/jwk-export-use-values.html
crypto/subtle/jwk-import-use-values.html
1. "extractable" renamed to "ext" in JWK.
2. New values for "use" mapping, which can now be combined into comma separated lists,
and cover all possible WebCrypto usages.
* bindings/js/JSCryptoKeySerializationJWK.cpp:
(WebCore::JSCryptoKeySerializationJWK::reconcileUsages):
(WebCore::JSCryptoKeySerializationJWK::reconcileExtractable):
(WebCore::JSCryptoKeySerializationJWK::addJWKAlgorithmToJSON):
(WebCore::processUseValue):
(WebCore::JSCryptoKeySerializationJWK::addJWKUseToJSON):
(WebCore::JSCryptoKeySerializationJWK::serialize):
2013-12-03 Simon Fraser <simon.fraser@apple.com>
Remove some iOS-related documentScale code
......@@ -245,7 +245,7 @@ bool JSCryptoKeySerializationJWK::reconcileAlgorithm(std::unique_ptr<CryptoAlgor
return true;
}
void JSCryptoKeySerializationJWK::reconcileUsages(CryptoKeyUsage& suggestedUsage) const
void JSCryptoKeySerializationJWK::reconcileUsages(CryptoKeyUsage& suggestedUsages) const
{
String jwkUseString;
if (!getStringFromJSON(m_exec, m_json.get(), "use", jwkUseString)) {
......@@ -253,23 +253,42 @@ void JSCryptoKeySerializationJWK::reconcileUsages(CryptoKeyUsage& suggestedUsage
return;
}
// FIXME: CryptoKeyUsageDeriveKey, CryptoKeyUsageDeriveBits - should these be implicitly allowed by any JWK use value?
// FIXME: "use" mapping is in flux, see <https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796>.
if (jwkUseString == "sig")
suggestedUsage = suggestedUsage & (CryptoKeyUsageSign | CryptoKeyUsageVerify);
else if (jwkUseString == "enc")
suggestedUsage = suggestedUsage & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey);
else if (jwkUseString == "wrap")
suggestedUsage = suggestedUsage & (CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey);
else
suggestedUsage = 0; // Unknown usage, better be safe.
// Implemented according to a proposal in <https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796>.
Vector<String> jwkUsageValues;
jwkUseString.split(',', jwkUsageValues);
CryptoKeyUsage jwkUsages = 0;
for (size_t i = 0, size = jwkUsageValues.size(); i < size; ++i) {
String jwkUse = jwkUsageValues[i];
if (jwkUse == "sig")
jwkUsages |= (CryptoKeyUsageSign | CryptoKeyUsageVerify);