From b220a58d1a678ffd46a42567909d0b0d59731d99 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Tue, 14 Dec 2021 17:02:14 +0100 Subject: [PATCH] feat(ext/crypto): support exporting RSA JWKs (#13081) This commit adds support for exporting RSA JWKs in the Web Crypto API. It also does some minor fixes for RSA JWK imports. Co-authored-by: Sean Michael Wykes --- cli/tests/unit/webcrypto_test.ts | 255 +++++++++++++++++++++++++++++++ ext/crypto/00_crypto.js | 206 ++++++++++++++++++++----- ext/crypto/export_key.rs | 61 +++++++- ext/crypto/lib.deno_crypto.d.ts | 6 +- tools/wpt/expectation.json | 246 +---------------------------- 5 files changed, 492 insertions(+), 282 deletions(-) diff --git a/cli/tests/unit/webcrypto_test.ts b/cli/tests/unit/webcrypto_test.ts index 9e22b0a49c..dab46465ae 100644 --- a/cli/tests/unit/webcrypto_test.ts +++ b/cli/tests/unit/webcrypto_test.ts @@ -772,3 +772,258 @@ Deno.test(async function testDecryptWithInvalidIntializationVector() { ); }, DOMException); }); + +const jwtRSAKeys = { + "1024": { + size: 1024, + publicJWK: { + kty: "RSA", + n: "zZn4sRGfjQos56yL_Qy1R9NI-THMnFynn94g5RxA6wGrJh4BJT3x6I9x0IbpS3q-d4ORA6R2vuDMh8dDFRr9RDH6XY-gUScc9U5Jz3UA2KmVfsCbnUPvcAmMV_ENA7_TF0ivVjuIFodyDTx7EKHNVTrHHSlrbt7spbmcivs23Zc", + e: "AQAB", + }, + privateJWK: { + kty: "RSA", + n: "zZn4sRGfjQos56yL_Qy1R9NI-THMnFynn94g5RxA6wGrJh4BJT3x6I9x0IbpS3q-d4ORA6R2vuDMh8dDFRr9RDH6XY-gUScc9U5Jz3UA2KmVfsCbnUPvcAmMV_ENA7_TF0ivVjuIFodyDTx7EKHNVTrHHSlrbt7spbmcivs23Zc", + e: "AQAB", + d: "YqIK_GdH85F-GWZdgfgmv15NE78gOaL5h2g4v7DeM9-JC7A5PHSLKNYn87HFGcC4vv0PBIBRtyCA_mJJfEaGWORVCOXSBpWNepMYpio52n3w5uj5UZEsBnbtZc0EtWhVF2Auqa7VbiKrWcQUEgEI8V0gE5D4tyBg8GXv9975dQE", + p: "9BrAg5L1zfqGPuWJDuDCBX-TmtZdrOI3Ys4ZaN-yMPlTjwWSEPO0qnfjEZcw2VgXHgJJmbVco6TxckJCmEYqeQ", + q: "157jDJ1Ya5nmQvTPbhKAPAeMWogxCyaQTkBrp30pEKd6mGSB385hqr4BIk8s3f7MdXpM-USpaZgUoT4o_2VEjw", + dp: + "qdd_QUzcaB-6jkKo1Ug-1xKIAgDLFsIjJUUfWt_iHL8ti2Kl2dOnTcCypgebPm5TT1bqHN-agGYAdK5zpX2UiQ", + dq: + "hNRfwOSplNfhLvxLUN7a2qA3yYm-1MSz_1DWQP7srlLORlUcYPht2FZmsnEeDcAqynBGPQUcbG2Av_hgHz2OZw", + qi: + "zbpJQAhinrxSbVKxBQ2EZGFUD2e3WCXbAJRYpk8HVQ5AA52OhKTicOye2hEHnrgpFKzC8iznTsCG3FMkvwcj4Q", + }, + }, + + "2048": { + size: 2048, + publicJWK: { + kty: "RSA", + // unpadded base64 for rawKey. + n: "09eVwAhT9SPBxdEN-74BBeEANGaVGwqH-YglIc4VV7jfhR2by5ivzVq8NCeQ1_ACDIlTDY8CTMQ5E1c1SEXmo_T7q84XUGXf8U9mx6uRg46sV7fF-hkwJR80BFVsvWxp4ahPlVJYj__94ft7rIVvchb5tyalOjrYFCJoFnSgq-i3ZjU06csI9XnO5klINucD_Qq0vUhO23_Add2HSYoRjab8YiJJR_Eths7Pq6HHd2RSXmwYp5foRnwe0_U75XmesHWDJlJUHYbwCZo0kP9G8g4QbucwU-MSNBkZOO2x2ZtZNexpHd0ThkATbnNlpVG_z2AGNORp_Ve3rlXwrGIXXw", + e: "AQAB", + }, + privateJWK: { + kty: "RSA", + // unpadded base64 for rawKey. + n: "09eVwAhT9SPBxdEN-74BBeEANGaVGwqH-YglIc4VV7jfhR2by5ivzVq8NCeQ1_ACDIlTDY8CTMQ5E1c1SEXmo_T7q84XUGXf8U9mx6uRg46sV7fF-hkwJR80BFVsvWxp4ahPlVJYj__94ft7rIVvchb5tyalOjrYFCJoFnSgq-i3ZjU06csI9XnO5klINucD_Qq0vUhO23_Add2HSYoRjab8YiJJR_Eths7Pq6HHd2RSXmwYp5foRnwe0_U75XmesHWDJlJUHYbwCZo0kP9G8g4QbucwU-MSNBkZOO2x2ZtZNexpHd0ThkATbnNlpVG_z2AGNORp_Ve3rlXwrGIXXw", + e: "AQAB", + d: "H4xboN2co0VP9kXL71G8lUOM5EDis8Q9u8uqu_4U75t4rjpamVeD1vFMVfgOehokM_m_hKVnkkcmuNqj9L90ObaiRFPM5QxG7YkFpXbHlPAKeoXD1hsqMF0VQg_2wb8DhberInHA_rEA_kaVhHvavQLu7Xez45gf1d_J4I4931vjlCB6cupbLL0H5hHsxbMsX_5nnmAJdL_U3gD-U7ZdQheUPhDBJR2KeGzvnTm3KVKpOnwn-1Cd45MU4-KDdP0FcBVEuBsSrsQHliTaciBgkbyj__BangPj3edDxTkb-fKkEvhkXRjAoJs1ixt8nfSGDce9cM_GqAX9XGb4s2QkAQ", + dp: + "mM82RBwzGzi9LAqjGbi-badLtHRRBoH9sfMrJuOtzxRnmwBFccg_lwy-qAhUTqnN9kvD0H1FzXWzoFPFJbyi-AOmumYGpWm_PvzQGldne5CPJ02pYaeg-t1BePsT3OpIq0Am8E2Kjf9polpRJwIjO7Kx8UJKkhg5bISnsy0V8wE", + dq: + "ZlM4AvrWIpXwqsH_5Q-6BsLJdbnN_GypFCXoT9VXniXncSBZIWCkgDndBdWkSzyzIN65NiMRBfZaf9yduTFj4kvOPwb3ch3J0OxGJk0Ary4OGSlS1zNwMl93ALGal1FzpWUuiia9L9RraGqXAUr13L7TIIMRobRjpAV-z7M-ruM", + p: "7VwGt_tJcAFQHrmDw5dM1EBru6fidM45NDv6VVOEbxKuD5Sh2EfAHfm5c6oouA1gZqwvKH0sn_XpB1NsyYyHEQd3sBVdK0zRjTo-E9mRP-1s-LMd5YDXVq6HE339nxpXsmO25slQEF6zBrj1bSNNXBFc7fgDnlq-HIeleMvsY_E", + q: "5HqMHLzb4IgXhUl4pLz7E4kjY8PH2YGzaQfK805zJMbOXzmlZK0hizKo34Qqd2nB9xos7QgzOYQrNfSWheARwVsSQzAE0vGvw3zHIPP_lTtChBlCTPctQcURjw4dXcnK1oQ-IT321FNOW3EO-YTsyGcypJqJujlZrLbxYjOjQE8", + qi: + "OQXzi9gypDnpdHatIi0FaUGP8LSzfVH0AUugURJXs4BTJpvA9y4hcpBQLrcl7H_vq6kbGmvC49V-9I5HNVX_AuxGIXKuLZr5WOxPq8gLTqHV7X5ZJDtWIP_nq2NNgCQQyNNRrxebiWlwGK9GnX_unewT6jopI_oFhwp0Q13rBR0", + }, + }, + "4096": { + size: 4096, + publicJWK: { + kty: "RSA", + n: "2qr2TL2c2JmbsN0OLIRnaAB_ZKb1-Gh9H0qb4lrBuDaqkW_eFPwT-JIsvnNJvDT7BLJ57tTMIj56ZMtv6efSSTWSk9MOoW2J1K_iEretZ2cegB_aRX7qQVjnoFsz9U02BKfAIUT0o_K7b9G08d1rrAUohi_SVQhwObodg7BddMbKUmz70QNIS487LN44WUVnn9OgE9atTYUARNukT0DuQb3J-K20ksTuVujXbSelohDmLobqlGoi5sY_548Qs9BtFmQ2nGuEHNB2zdlZ5EvEqbUFVZ2QboG6jXdoos6qcwdgUvAhj1Hz10Ngic_RFqL7bNDoIOzNp66hdA35uxbwuaygZ16ikxoPj7eTYud1hrkyQCgeGw2YhCiKIE6eos_U5dL7WHRD5aSkkzsgXtnF8pVmStsuf0QcdAoC-eeCex0tSTgRw9AtGTz8Yr1tGQD9l_580zAXnE6jmrwRRQ68EEA7vohGov3tnG8pGyg_zcxeADLtPlfTc1tEwmh3SGrioDClioYCipm1JvkweEgP9eMPpEC8SgRU1VNDSVe1SF4uNsH8vA7PHFKfg6juqJEc5ht-l10FYER-Qq6bZXsU2oNcfE5SLDeLTWmxiHmxK00M8ABMFIV5gUkPoMiWcl87O6XwzA2chsIERp7Vb-Vn2O-EELiXzv7lPhc6fTGQ0Nc", + e: "AQAB", + }, + privateJWK: { + kty: "RSA", + n: "2qr2TL2c2JmbsN0OLIRnaAB_ZKb1-Gh9H0qb4lrBuDaqkW_eFPwT-JIsvnNJvDT7BLJ57tTMIj56ZMtv6efSSTWSk9MOoW2J1K_iEretZ2cegB_aRX7qQVjnoFsz9U02BKfAIUT0o_K7b9G08d1rrAUohi_SVQhwObodg7BddMbKUmz70QNIS487LN44WUVnn9OgE9atTYUARNukT0DuQb3J-K20ksTuVujXbSelohDmLobqlGoi5sY_548Qs9BtFmQ2nGuEHNB2zdlZ5EvEqbUFVZ2QboG6jXdoos6qcwdgUvAhj1Hz10Ngic_RFqL7bNDoIOzNp66hdA35uxbwuaygZ16ikxoPj7eTYud1hrkyQCgeGw2YhCiKIE6eos_U5dL7WHRD5aSkkzsgXtnF8pVmStsuf0QcdAoC-eeCex0tSTgRw9AtGTz8Yr1tGQD9l_580zAXnE6jmrwRRQ68EEA7vohGov3tnG8pGyg_zcxeADLtPlfTc1tEwmh3SGrioDClioYCipm1JvkweEgP9eMPpEC8SgRU1VNDSVe1SF4uNsH8vA7PHFKfg6juqJEc5ht-l10FYER-Qq6bZXsU2oNcfE5SLDeLTWmxiHmxK00M8ABMFIV5gUkPoMiWcl87O6XwzA2chsIERp7Vb-Vn2O-EELiXzv7lPhc6fTGQ0Nc", + e: "AQAB", + d: "uXPRXBhcE5-DWabBRKQuhxgU8ype5gTISWefeYP7U96ZHqu_sBByZ5ihdgyU9pgAZGVx4Ep9rnVKnH2lNr2zrP9Qhyqy99nM0aMxmypIWLAuP__DwLj4t99M4sU29c48CAq1egHfccSFjzpNuetOTCA71EJuokt70pm0OmGzgTyvjuR7VTLxd5PMXitBowSn8_cphmnFpT8tkTiuy8CH0R3DU7MOuINomDD1s8-yPBcVAVTPUnwJiauNuzestLQKMLlhT5wn-cAbYk36XRKdgkjSc2AkhHRl4WDqT1nzWYdh_DVIYSLiKSktkPO9ovMrRYiPtozfhl0m9SR9Ll0wXtcnnDlWXc_MSGpw18vmUBSJ4PIhkiFsvLn-db3wUkA8uve-iqqfk0sxlGWughWx03kGmZDmprWbXugCBHfsI4X93w4exznXH_tapxPnmjbhVUQR6p41MvO2lcHWPLwGJgLIoejBHpnn3TmMN0UjFZki7q9B_dJ3fXh0mX9DzAlC0sil1NgCPhMPq02393_giinQquMknrBvgKxGSfGUrDKuflCx611ZZlRM3R7YMX2OIy1g4DyhPzBVjxRMtm8PnIs3m3Hi-O-C_PHF93w9J8Wqd0yIw7SpavDqZXLPC6Cqi8K7MBZyVECXHtRj1bBqT-h_xZmFCDjSU0NqfOdgApE", + p: "9NrXwq4kY9kBBOwLoFZVQc4kJI_NbKa_W9FLdQdRIbMsZZHXJ3XDUR9vJAcaaR75WwIC7X6N55nVtWTq28Bys9flJ9RrCTfciOntHEphBhYaL5ZTUl-6khYmsOf_psff2VaOOCvHGff5ejuOmBQxkw2E-cv7knRgWFHoLWpku2NJIMuGHt9ks7OAUfIZVYl9YJnw4FYUzhgaxemknjLeZ8XTkGW2zckzF-d95YI9i8zD80Umubsw-YxriSfqFQ0rGHBsbQ8ZOTd_KJju42BWnXIjNDYmjFUqdzVjI4XQ8EGrCEf_8_iwphGyXD7LOJ4fqd97B3bYpoRTPnCgY_SEHQ", + q: "5J758_NeKr1XPZiLxXohYQQnh0Lb4QtGZ1xzCgjhBQLcIBeTOG_tYjCues9tmLt93LpJfypSJ-SjDLwkR2s069_IByYGpxyeGtV-ulqYhSw1nD2CXKMDGyO5jXDs9tJrS_UhfobXKQH03CRdFugyPkSNmXY-AafFynG7xLr7oYBC05FnhUXPm3VBTPt9K-BpqwYd_h9vkAWeprSPo83UlwcLMupSJY9LaHxhRdz2yi0ZKNwXXHRwcszGjDBvvzUcCYbqWqjzbEvFY6KtH8Jh4LhM46rHaoEOTernJsDF6a6W8Df88RthqTExcwnaQf0O_dlbjSxEIPfbxx8t1EQugw", + dp: + "4Y7Hu5tYAnLhMXuQqj9dgqU3PkcKYdCp7xc6f7Ah2P2JJHfYz4z4RD7Ez1eLyNKzulZ8A_PVHUjlSZiRkaYTBAEaJDrV70P6cFWuC6WpA0ZREQ1V7EgrQnANbGILa8QsPbYyhSQu4YlB1IwQq5_OmzyVBtgWA7AZIMMzMsMT0FuB_if-gWohBjmRN-vh0p45VUf6UW568-_YmgDFmMYbg1UFs7s_TwrNenPR0h7MO4CB8hP9vJLoZrooRczzIjljPbwy5bRG9CJfjTJ0vhj9MUT3kR1hHV1HJVGU5iBbfTfBKnvJGSI6-IDM4ZUm-B0R5hbs6s9cfOjhFmACIJIbMQ", + dq: + "gT4iPbfyHyVEwWyQb4X4grjvg7bXSKSwG1SXMDAOzV9tg7LwJjKYNy8gJAtJgNNVdsfVLs-E_Epzpoph1AIWO9YZZXkov6Yc9zyEVONMX9S7ReU74hTBd8E9b2lMfMg9ogYk9jtSPTt-6kigW4fOh4cHqZ6_tP3cgfLD3JZ8FDPHE4WaySvLDq49yUBO5dQKyIU_xV6OGhQjOUjP_yEoMmzn9tOittsIHTxbXTxqQ6c1FvU9O6YTv8Jl5_Cl66khfX1I1RG38xvurcHULyUbYgeuZ_Iuo9XreT73h9_owo9RguGT29XH4vcNZmRGf5GIvRb4e5lvtleIZkwJA3u78w", + qi: + "JHmVKb1zwW5iRR6RCeexYnh2fmY-3DrPSdM8Dxhr0F8dayi-tlRqEdnG0hvp45n8gLUskWWcB9EXlUJObZGKDfGuxgMa3g_xeLA2vmFQ12MxPsyH4iCNZvsgmGxx7TuOHrnDh5EBVnM4_de63crEJON2sYI8Ozi-xp2OEmAr2seWKq4sxkFni6exLhqb-NE4m9HMKlng1EtQh2rLBFG1VYD3SYYpMLc5fxzqGvSxn3Fa-Xgg-IZPY3ubrcm52KYgmLUGmnYStfVqGSWSdhDXHlNgI5pdAA0FzpyBk3ZX-JsxhwcnneKrYBBweq06kRMGWgvdbdAQ-7wSeGqqj5VPwA", + }, + }, +}; + +Deno.test(async function testImportRsaJwk() { + const subtle = window.crypto.subtle; + assert(subtle); + + for (const [_key, jwkData] of Object.entries(jwtRSAKeys)) { + const { size, publicJWK, privateJWK } = jwkData; + if (size < 2048) { + continue; + } + + // 1. Test import PSS + for (const hash of ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]) { + const hashMapPSS: Record = { + "SHA-1": "PS1", + "SHA-256": "PS256", + "SHA-384": "PS384", + "SHA-512": "PS512", + }; + + if (size == 1024 && hash == "SHA-512") { + continue; + } + + const privateKeyPSS = await crypto.subtle.importKey( + "jwk", + { + alg: hashMapPSS[hash], + ...privateJWK, + ext: true, + "key_ops": ["sign"], + }, + { name: "RSA-PSS", hash }, + true, + ["sign"], + ); + + const publicKeyPSS = await crypto.subtle.importKey( + "jwk", + { + alg: hashMapPSS[hash], + ...publicJWK, + ext: true, + "key_ops": ["verify"], + }, + { name: "RSA-PSS", hash }, + true, + ["verify"], + ); + + const signaturePSS = await crypto.subtle.sign( + { name: "RSA-PSS", saltLength: 32 }, + privateKeyPSS, + new Uint8Array([1, 2, 3, 4]), + ); + + const verifyPSS = await crypto.subtle.verify( + { name: "RSA-PSS", saltLength: 32 }, + publicKeyPSS, + signaturePSS, + new Uint8Array([1, 2, 3, 4]), + ); + assert(verifyPSS); + } + + // 2. Test import PKCS1 + for (const hash of ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]) { + const hashMapPKCS1: Record = { + "SHA-1": "RS1", + "SHA-256": "RS256", + "SHA-384": "RS384", + "SHA-512": "RS512", + }; + + if (size == 1024 && hash == "SHA-512") { + continue; + } + + const privateKeyPKCS1 = await crypto.subtle.importKey( + "jwk", + { + alg: hashMapPKCS1[hash], + ...privateJWK, + ext: true, + "key_ops": ["sign"], + }, + { name: "RSASSA-PKCS1-v1_5", hash }, + true, + ["sign"], + ); + + const publicKeyPKCS1 = await crypto.subtle.importKey( + "jwk", + { + alg: hashMapPKCS1[hash], + ...publicJWK, + ext: true, + "key_ops": ["verify"], + }, + { name: "RSASSA-PKCS1-v1_5", hash }, + true, + ["verify"], + ); + + const signaturePKCS1 = await crypto.subtle.sign( + { name: "RSASSA-PKCS1-v1_5", saltLength: 32 }, + privateKeyPKCS1, + new Uint8Array([1, 2, 3, 4]), + ); + + const verifyPKCS1 = await crypto.subtle.verify( + { name: "RSASSA-PKCS1-v1_5", saltLength: 32 }, + publicKeyPKCS1, + signaturePKCS1, + new Uint8Array([1, 2, 3, 4]), + ); + assert(verifyPKCS1); + } + + // 3. Test import OAEP + for ( + const { hash, plainText } of hashPlainTextVector + ) { + const hashMapOAEP: Record = { + "SHA-1": "RSA-OAEP", + "SHA-256": "RSA-OAEP-256", + "SHA-384": "RSA-OAEP-384", + "SHA-512": "RSA-OAEP-512", + }; + + if (size == 1024 && hash == "SHA-512") { + continue; + } + + const encryptAlgorithm = { name: "RSA-OAEP" }; + + const privateKeyOAEP = await crypto.subtle.importKey( + "jwk", + { + alg: hashMapOAEP[hash], + ...privateJWK, + ext: true, + "key_ops": ["decrypt"], + }, + { ...encryptAlgorithm, hash }, + true, + ["decrypt"], + ); + + const publicKeyOAEP = await crypto.subtle.importKey( + "jwk", + { + alg: hashMapOAEP[hash], + ...publicJWK, + ext: true, + "key_ops": ["encrypt"], + }, + { ...encryptAlgorithm, hash }, + true, + ["encrypt"], + ); + const cipherText = await subtle.encrypt( + encryptAlgorithm, + publicKeyOAEP, + plainText, + ); + + assert(cipherText); + assert(cipherText.byteLength > 0); + assertEquals(cipherText.byteLength * 8, size); + assert(cipherText instanceof ArrayBuffer); + + const decrypted = await subtle.decrypt( + encryptAlgorithm, + privateKeyOAEP, + cipherText, + ); + assert(decrypted); + assert(decrypted instanceof ArrayBuffer); + assertEquals(new Uint8Array(decrypted), plainText); + } + } +}); diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index 99efde2d4f..0e09197a84 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -15,31 +15,32 @@ const { btoa } = window.__bootstrap.base64; const { - ArrayPrototypeFind, - ArrayPrototypeEvery, - ArrayPrototypeIncludes, ArrayBuffer, ArrayBufferIsView, + ArrayPrototypeEvery, + ArrayPrototypeFind, + ArrayPrototypeIncludes, BigInt64Array, + Int16Array, + Int32Array, + Int8Array, + ObjectAssign, + StringFromCharCode, + StringPrototypeReplace, StringPrototypeToLowerCase, StringPrototypeToUpperCase, - StringPrototypeReplace, - StringFromCharCode, Symbol, SymbolFor, SyntaxError, + TypedArrayPrototypeSlice, + TypeError, + Uint16Array, + Uint32Array, + Uint8Array, + Uint8ClampedArray, WeakMap, WeakMapPrototypeGet, WeakMapPrototypeSet, - Int8Array, - Uint8Array, - TypedArrayPrototypeSlice, - Int16Array, - Uint16Array, - Int32Array, - Uint32Array, - Uint8ClampedArray, - TypeError, } = window.__bootstrap.primordials; // P-521 is not yet supported. @@ -2464,27 +2465,75 @@ let hash; // 8. - switch (jwk.alg) { - case undefined: - hash = undefined; - break; - case "RS1": - hash = "SHA-1"; - break; - case "RS256": - hash = "SHA-256"; - break; - case "RS384": - hash = "SHA-384"; - break; - case "RS512": - hash = "SHA-512"; - break; - default: - throw new DOMException( - `'alg' property of JsonWebKey must be one of 'RS1', 'RS256', 'RS384', 'RS512'`, - "DataError", - ); + if (normalizedAlgorithm.name === "RSASSA-PKCS1-v1_5") { + switch (jwk.alg) { + case undefined: + hash = undefined; + break; + case "RS1": + hash = "SHA-1"; + break; + case "RS256": + hash = "SHA-256"; + break; + case "RS384": + hash = "SHA-384"; + break; + case "RS512": + hash = "SHA-512"; + break; + default: + throw new DOMException( + `'alg' property of JsonWebKey must be one of 'RS1', 'RS256', 'RS384', 'RS512'`, + "DataError", + ); + } + } else if (normalizedAlgorithm.name === "RSA-PSS") { + switch (jwk.alg) { + case undefined: + hash = undefined; + break; + case "PS1": + hash = "SHA-1"; + break; + case "PS256": + hash = "SHA-256"; + break; + case "PS384": + hash = "SHA-384"; + break; + case "PS512": + hash = "SHA-512"; + break; + default: + throw new DOMException( + `'alg' property of JsonWebKey must be one of 'PS1', 'PS256', 'PS384', 'PS512'`, + "DataError", + ); + } + } else { + switch (jwk.alg) { + case undefined: + hash = undefined; + break; + case "RSA-OAEP": + hash = "SHA-1"; + break; + case "RSA-OAEP-256": + hash = "SHA-256"; + break; + case "RSA-OAEP-384": + hash = "SHA-384"; + break; + case "RSA-OAEP-512": + hash = "SHA-512"; + break; + default: + throw new DOMException( + `'alg' property of JsonWebKey must be one of 'RSA-OAEP', 'RSA-OAEP-256', 'RSA-OAEP-384', or 'RSA-OAEP-512'`, + "DataError", + ); + } } // 9. @@ -2822,6 +2871,93 @@ // 3. return data.buffer; } + case "jwk": { + // 1-2. + const jwk = { + kty: "RSA", + }; + + // 3. + const hash = key[_algorithm].hash.name; + + // 4. + if (key[_algorithm].name === "RSASSA-PKCS1-v1_5") { + switch (hash) { + case "SHA-1": + jwk.alg = "RS1"; + break; + case "SHA-256": + jwk.alg = "RS256"; + break; + case "SHA-384": + jwk.alg = "RS384"; + break; + case "SHA-512": + jwk.alg = "RS512"; + break; + default: + throw new DOMException( + "Hash algorithm not supported", + "NotSupportedError", + ); + } + } else if (key[_algorithm].name === "RSA-PSS") { + switch (hash) { + case "SHA-1": + jwk.alg = "PS1"; + break; + case "SHA-256": + jwk.alg = "PS256"; + break; + case "SHA-384": + jwk.alg = "PS384"; + break; + case "SHA-512": + jwk.alg = "PS512"; + break; + default: + throw new DOMException( + "Hash algorithm not supported", + "NotSupportedError", + ); + } + } else { + switch (hash) { + case "SHA-1": + jwk.alg = "RSA-OAEP"; + break; + case "SHA-256": + jwk.alg = "RSA-OAEP-256"; + break; + case "SHA-384": + jwk.alg = "RSA-OAEP-384"; + break; + case "SHA-512": + jwk.alg = "RSA-OAEP-512"; + break; + default: + throw new DOMException( + "Hash algorithm not supported", + "NotSupportedError", + ); + } + } + + // 5-6. + const data = core.opSync("op_crypto_export_key", { + format: key[_type] === "private" ? "jwkprivate" : "jwkpublic", + algorithm: key[_algorithm].name, + }, innerKey); + ObjectAssign(jwk, data); + + // 7. + jwk.key_ops = key.usages; + + // 8. + jwk.ext = key[_extractable]; + + return jwk; + } default: throw new DOMException("Not implemented", "NotSupportedError"); } diff --git a/ext/crypto/export_key.rs b/ext/crypto/export_key.rs index 22a4b55ca2..2e74d61f22 100644 --- a/ext/crypto/export_key.rs +++ b/ext/crypto/export_key.rs @@ -1,9 +1,12 @@ +use deno_core::error::custom_error; use deno_core::error::AnyError; use deno_core::OpState; use deno_core::ZeroCopyBuf; +use rsa::pkcs1::UIntBytes; use serde::Deserialize; use serde::Serialize; use spki::der::asn1; +use spki::der::Decodable; use spki::der::Encodable; use crate::shared::*; @@ -21,7 +24,8 @@ pub struct ExportKeyOptions { pub enum ExportKeyFormat { Pkcs8, Spki, - Jwk, + JwkPublic, + JwkPrivate, } #[derive(Deserialize)] @@ -40,6 +44,20 @@ pub enum ExportKeyAlgorithm { pub enum ExportKeyResult { Pkcs8(ZeroCopyBuf), Spki(ZeroCopyBuf), + JwkPublicRsa { + n: String, + e: String, + }, + JwkPrivateRsa { + n: String, + e: String, + d: String, + p: String, + q: String, + dp: String, + dq: String, + qi: String, + }, } pub fn op_crypto_export_key( @@ -54,6 +72,10 @@ pub fn op_crypto_export_key( } } +fn uint_to_b64(bytes: UIntBytes) -> String { + base64::encode_config(bytes.as_bytes(), base64::URL_SAFE_NO_PAD) +} + fn export_key_rsa( format: ExportKeyFormat, key_data: RawKeyData, @@ -108,6 +130,41 @@ fn export_key_rsa( Ok(ExportKeyResult::Pkcs8(pkcs8_der.into())) } - _ => Err(unsupported_format()), + ExportKeyFormat::JwkPublic => { + let public_key = key_data.as_rsa_public_key()?; + let public_key = rsa::pkcs1::RsaPublicKey::from_der(&public_key) + .map_err(|_| { + custom_error( + "DOMExceptionOperationError", + "failed to decode public key", + ) + })?; + + Ok(ExportKeyResult::JwkPublicRsa { + n: uint_to_b64(public_key.modulus), + e: uint_to_b64(public_key.public_exponent), + }) + } + ExportKeyFormat::JwkPrivate => { + let private_key = key_data.as_rsa_private_key()?; + let private_key = rsa::pkcs1::RsaPrivateKey::from_der(private_key) + .map_err(|_| { + custom_error( + "DOMExceptionOperationError", + "failed to decode private key", + ) + })?; + + Ok(ExportKeyResult::JwkPrivateRsa { + n: uint_to_b64(private_key.modulus), + e: uint_to_b64(private_key.public_exponent), + d: uint_to_b64(private_key.private_exponent), + p: uint_to_b64(private_key.prime1), + q: uint_to_b64(private_key.prime2), + dp: uint_to_b64(private_key.exponent1), + dq: uint_to_b64(private_key.exponent2), + qi: uint_to_b64(private_key.coefficient), + }) + } } } diff --git a/ext/crypto/lib.deno_crypto.d.ts b/ext/crypto/lib.deno_crypto.d.ts index 0338448af4..7681a56abe 100644 --- a/ext/crypto/lib.deno_crypto.d.ts +++ b/ext/crypto/lib.deno_crypto.d.ts @@ -101,6 +101,10 @@ interface HmacImportParams extends Algorithm { length?: number; } +interface RsaHashedImportParams extends Algorithm { + hash: HashAlgorithmIdentifier; +} + interface EcKeyAlgorithm extends KeyAlgorithm { namedCurve: NamedCurve; } @@ -191,7 +195,7 @@ interface SubtleCrypto { importKey( format: "jwk", keyData: JsonWebKey, - algorithm: AlgorithmIdentifier | HmacImportParams, + algorithm: AlgorithmIdentifier | HmacImportParams | RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[], ): Promise; diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json index 76b6bc4462..0d9c0a5e29 100644 --- a/tools/wpt/expectation.json +++ b/tools/wpt/expectation.json @@ -3941,250 +3941,8 @@ "import_export": { "ec_importKey.https.any.html": false, "ec_importKey.https.any.worker.html": false, - "rsa_importKey.https.any.html": [ - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-PSS}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-PSS}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-PSS}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-PSS}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-PSS}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-PSS}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-PSS}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-PSS}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-PSS}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-PSS}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-PSS}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-PSS}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-PSS}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-PSS}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-PSS}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-PSS}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-PSS}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-PSS}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-PSS}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-PSS}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-PSS}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-PSS}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-PSS}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-PSS}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [sign])" - ], - "rsa_importKey.https.any.worker.html": [ - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey, encrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-OAEP}, true, [wrapKey])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey, decrypt])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-OAEP}, true, [unwrapKey])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-PSS}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-PSS}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-PSS}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-PSS}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-PSS}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-PSS}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-PSS}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-PSS}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-PSS}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-PSS}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-PSS}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-PSS}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-PSS}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-PSS}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-PSS}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-PSS}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSA-PSS}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSA-PSS}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSA-PSS}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSA-PSS}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSA-PSS}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSA-PSS}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSA-PSS}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSA-PSS}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 1024 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 1024 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 2048 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 2048 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-1, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-256, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-384, name: RSASSA-PKCS1-v1_5}, true, [sign])", - "Good parameters: 4096 bits (jwk, object(kty, n, e), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [verify])", - "Good parameters: 4096 bits (jwk, object(kty, n, e, d, p, q, dp, dq, qi), {hash: SHA-512, name: RSASSA-PKCS1-v1_5}, true, [sign])" - ], + "rsa_importKey.https.any.html": true, + "rsa_importKey.https.any.worker.html": true, "symmetric_importKey.https.any.html": true, "symmetric_importKey.https.any.worker.html": true },