diff options
author | Sean Michael Wykes <8363933+SeanWykes@users.noreply.github.com> | 2022-01-19 00:38:35 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-19 09:08:35 +0530 |
commit | 77e58fe7f9fc20dabf77424efbd25ce332f8f59c (patch) | |
tree | e8cdf3b06661b209ea685b5d762f670e662923b7 /ext/crypto/00_crypto.js | |
parent | b3545dd447dcbab6629827dbe8d127ef82f8da69 (diff) |
feat(ext/crypto): implement pkcs8/spki/jwk exportKey for ECDSA and ECDH (#13104)
Diffstat (limited to 'ext/crypto/00_crypto.js')
-rw-r--r-- | ext/crypto/00_crypto.js | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index 81c475ad7..2596bb052 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -975,6 +975,10 @@ case "RSA-OAEP": { return exportKeyRSA(format, key, innerKey); } + case "ECDH": + case "ECDSA": { + return exportKeyEC(format, key, innerKey); + } case "AES-CTR": case "AES-CBC": case "AES-GCM": @@ -3377,6 +3381,128 @@ } } + function exportKeyEC(format, key, innerKey) { + switch (format) { + case "pkcs8": { + // 1. + if (key[_type] !== "private") { + throw new DOMException( + "Key is not a private key", + "InvalidAccessError", + ); + } + + // 2. + const data = core.opSync("op_crypto_export_key", { + algorithm: key[_algorithm].name, + namedCurve: key[_algorithm].namedCurve, + format: "pkcs8", + }, innerKey); + + return data.buffer; + } + case "spki": { + // 1. + if (key[_type] !== "public") { + throw new DOMException( + "Key is not a public key", + "InvalidAccessError", + ); + } + + // 2. + const data = core.opSync("op_crypto_export_key", { + algorithm: key[_algorithm].name, + namedCurve: key[_algorithm].namedCurve, + format: "spki", + }, innerKey); + + return data.buffer; + } + case "jwk": { + if (key[_algorithm].name == "ECDSA") { + // 1-2. + const jwk = { + kty: "EC", + }; + + // 3.1 + jwk.crv = key[_algorithm].namedCurve; + + // Missing from spec + let algNamedCurve; + + switch (key[_algorithm].namedCurve) { + case "P-256": { + algNamedCurve = "ES256"; + break; + } + case "P-384": { + algNamedCurve = "ES384"; + break; + } + case "P-521": { + algNamedCurve = "ES512"; + break; + } + default: + throw new DOMException( + "Curve algorithm not supported", + "DataError", + ); + } + + jwk.alg = algNamedCurve; + + // 3.2 - 3.4. + const data = core.opSync("op_crypto_export_key", { + format: key[_type] === "private" ? "jwkprivate" : "jwkpublic", + algorithm: key[_algorithm].name, + namedCurve: key[_algorithm].namedCurve, + }, innerKey); + ObjectAssign(jwk, data); + + // 4. + jwk.key_ops = key.usages; + + // 5. + jwk.ext = key[_extractable]; + + return jwk; + } else { // ECDH + // 1-2. + const jwk = { + kty: "EC", + }; + + // missing step from spec + jwk.alg = "ECDH"; + + // 3.1 + jwk.crv = key[_algorithm].namedCurve; + + // 3.2 - 3.4 + const data = core.opSync("op_crypto_export_key", { + format: key[_type] === "private" ? "jwkprivate" : "jwkpublic", + algorithm: key[_algorithm].name, + namedCurve: key[_algorithm].namedCurve, + }, innerKey); + ObjectAssign(jwk, data); + + // 4. + jwk.key_ops = key.usages; + + // 5. + jwk.ext = key[_extractable]; + + return jwk; + } + } + default: + throw new DOMException("Not implemented", "NotSupportedError"); + } + } + async function generateKeyAES(normalizedAlgorithm, extractable, usages) { const algorithmName = normalizedAlgorithm.name; |