1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-28 16:20:57 -05:00

fix(ext/node): crypto.getCipherInfo() (#22916)

Stub implementation of getCipherInfo(). Good enough for most cases.

Note: We do not support all OpenSSL ciphers (likely never will)

Fixes https://github.com/denoland/deno/issues/21805
This commit is contained in:
Divy Srivastava 2024-03-14 06:30:29 -07:00 committed by GitHub
parent cad79af785
commit cf3c6f9b08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 107 additions and 42 deletions

View file

@ -86,7 +86,6 @@ import {
import { import {
Cipheriv, Cipheriv,
Decipheriv, Decipheriv,
getCipherInfo,
privateDecrypt, privateDecrypt,
privateEncrypt, privateEncrypt,
publicDecrypt, publicDecrypt,
@ -149,6 +148,7 @@ import type {
X509CheckOptions, X509CheckOptions,
} from "ext:deno_node/internal/crypto/x509.ts"; } from "ext:deno_node/internal/crypto/x509.ts";
import { import {
getCipherInfo,
getCiphers, getCiphers,
getCurves, getCurves,
secureHeapUsed, secureHeapUsed,

View file

@ -22,11 +22,6 @@ import {
op_node_public_encrypt, op_node_public_encrypt,
} from "ext:core/ops"; } 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 { Buffer } from "node:buffer";
import { notImplemented } from "ext:deno_node/_utils.ts"; import { notImplemented } from "ext:deno_node/_utils.ts";
import type { TransformOptions } from "ext:deno_node/_stream.d.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( export function privateEncrypt(
privateKey: ArrayBufferView | string | KeyObject, privateKey: ArrayBufferView | string | KeyObject,
buffer: ArrayBufferView | string | KeyObject, buffer: ArrayBufferView | string | KeyObject,
@ -503,5 +463,4 @@ export default {
Cipheriv, Cipheriv,
Decipheriv, Decipheriv,
prepareKey, prepareKey,
getCipherInfo,
}; };

View file

@ -83,6 +83,89 @@ export function getCiphers(): string[] {
return supportedCiphers; 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"; let defaultEncoding = "buffer";
export function setDefaultEncoding(val: string) { export function setDefaultEncoding(val: string) {
@ -150,6 +233,7 @@ export default {
getDefaultEncoding, getDefaultEncoding,
setDefaultEncoding, setDefaultEncoding,
getCiphers, getCiphers,
getCipherInfo,
getCurves, getCurves,
secureHeapUsed, secureHeapUsed,
setEngine, setEngine,

View file

@ -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);
},
});