diff options
| -rw-r--r-- | ext/node/polyfills/crypto.ts | 2 | ||||
| -rw-r--r-- | ext/node/polyfills/internal/crypto/cipher.ts | 41 | ||||
| -rw-r--r-- | ext/node/polyfills/internal/crypto/util.ts | 84 | ||||
| -rw-r--r-- | tests/unit_node/crypto/crypto_cipher_test.ts | 22 |
4 files changed, 107 insertions, 42 deletions
diff --git a/ext/node/polyfills/crypto.ts b/ext/node/polyfills/crypto.ts index b3afff5a1..7ea8800a7 100644 --- a/ext/node/polyfills/crypto.ts +++ b/ext/node/polyfills/crypto.ts @@ -86,7 +86,6 @@ import { import { Cipheriv, Decipheriv, - getCipherInfo, privateDecrypt, privateEncrypt, publicDecrypt, @@ -149,6 +148,7 @@ import type { X509CheckOptions, } from "ext:deno_node/internal/crypto/x509.ts"; import { + getCipherInfo, getCiphers, getCurves, secureHeapUsed, diff --git a/ext/node/polyfills/internal/crypto/cipher.ts b/ext/node/polyfills/internal/crypto/cipher.ts index 20971a8c7..f8a46896d 100644 --- a/ext/node/polyfills/internal/crypto/cipher.ts +++ b/ext/node/polyfills/internal/crypto/cipher.ts @@ -22,11 +22,6 @@ import { op_node_public_encrypt, } from "ext:core/ops"; -import { ERR_INVALID_ARG_TYPE } from "ext:deno_node/internal/errors.ts"; -import { - validateInt32, - validateObject, -} from "ext:deno_node/internal/validators.mjs"; import { Buffer } from "node:buffer"; import { notImplemented } from "ext:deno_node/_utils.ts"; import type { TransformOptions } from "ext:deno_node/_stream.d.ts"; @@ -405,41 +400,6 @@ export class Decipheriv extends Transform implements Cipher { } } -export function getCipherInfo( - nameOrNid: string | number, - options?: { keyLength?: number; ivLength?: number }, -) { - if (typeof nameOrNid !== "string" && typeof nameOrNid !== "number") { - throw new ERR_INVALID_ARG_TYPE( - "nameOrNid", - ["string", "number"], - nameOrNid, - ); - } - - if (typeof nameOrNid === "number") { - validateInt32(nameOrNid, "nameOrNid"); - } - - let keyLength, ivLength; - - if (options !== undefined) { - validateObject(options, "options"); - - ({ keyLength, ivLength } = options); - - if (keyLength !== undefined) { - validateInt32(keyLength, "options.keyLength"); - } - - if (ivLength !== undefined) { - validateInt32(ivLength, "options.ivLength"); - } - } - - notImplemented("crypto.getCipherInfo"); -} - export function privateEncrypt( privateKey: ArrayBufferView | string | KeyObject, buffer: ArrayBufferView | string | KeyObject, @@ -503,5 +463,4 @@ export default { Cipheriv, Decipheriv, prepareKey, - getCipherInfo, }; diff --git a/ext/node/polyfills/internal/crypto/util.ts b/ext/node/polyfills/internal/crypto/util.ts index 91e2c92a2..a68ac3682 100644 --- a/ext/node/polyfills/internal/crypto/util.ts +++ b/ext/node/polyfills/internal/crypto/util.ts @@ -83,6 +83,89 @@ export function getCiphers(): string[] { return supportedCiphers; } +export function getCipherInfo( + nameOrNid: string | number, + options?: { keyLength?: number; ivLength?: number }, +) { + if (typeof nameOrNid !== "string" && typeof nameOrNid !== "number") { + throw new ERR_INVALID_ARG_TYPE( + "nameOrNid", + ["string", "number"], + nameOrNid, + ); + } + + if (typeof nameOrNid === "number") { + validateInt32(nameOrNid, "nameOrNid"); + } + + let keyLength, ivLength; + + if (options !== undefined) { + validateObject(options, "options"); + + ({ keyLength, ivLength } = options); + + if (keyLength !== undefined) { + validateInt32(keyLength, "options.keyLength"); + } + + if (ivLength !== undefined) { + validateInt32(ivLength, "options.ivLength"); + } + } + + // This API is heavily based on OpenSSL's EVP_get_cipherbyname(3) and + // EVP_get_cipherbynid(3) functions. + // + // TODO(@littledivy): write proper cipher info utility in Rust + // in future refactors + const cipher = supportedCiphers.find((c) => c === nameOrNid); + if (cipher === undefined) { + return undefined; + } + + const match = cipher.match(/^(aes)-(\d+)-(\w+)$/); + if (match) { + const [, name, keyLength, mode] = match; + return { + name: `${name}-${keyLength}-${mode}`, + keyLength: parseInt(keyLength) / 8, + mode, + ivLength: 16, + }; + } + + if (cipher === "aes128") { + return { + name: "aes-128-cbc", + keyLength: 16, + mode: "cbc", + ivLength: 16, + }; + } + + if (cipher === "aes192") { + return { + name: "aes-192-cbc", + keyLength: 24, + mode: "cbc", + ivLength: 16, + }; + } + + if (cipher === "aes256") { + return { + name: "aes-256-cbc", + keyLength: 32, + mode: "cbc", + ivLength: 16, + }; + } + + return undefined; +} + let defaultEncoding = "buffer"; export function setDefaultEncoding(val: string) { @@ -150,6 +233,7 @@ export default { getDefaultEncoding, setDefaultEncoding, getCiphers, + getCipherInfo, getCurves, secureHeapUsed, setEngine, diff --git a/tests/unit_node/crypto/crypto_cipher_test.ts b/tests/unit_node/crypto/crypto_cipher_test.ts index d22028624..ab8bb4d37 100644 --- a/tests/unit_node/crypto/crypto_cipher_test.ts +++ b/tests/unit_node/crypto/crypto_cipher_test.ts @@ -256,3 +256,25 @@ Deno.test({ ); }, }); + +Deno.test({ + name: "getCiphers", + fn() { + assertEquals(crypto.getCiphers().includes("aes-128-cbc"), true); + }, +}); + +Deno.test({ + name: "getCipherInfo", + fn() { + const info = crypto.getCipherInfo("aes-128-cbc")!; + assertEquals(info.name, "aes-128-cbc"); + assertEquals(info.keyLength, 16); + assertEquals(info.ivLength, 16); + + const info2 = crypto.getCipherInfo("aes128")!; + assertEquals(info2.name, "aes-128-cbc"); + assertEquals(info2.keyLength, 16); + assertEquals(info2.ivLength, 16); + }, +}); |
