mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -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:
parent
cad79af785
commit
cf3c6f9b08
4 changed files with 107 additions and 42 deletions
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue