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:
parent
cad79af785
commit
cf3c6f9b08
4 changed files with 107 additions and 42 deletions
|
@ -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,
|
||||||
|
|
|
@ -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,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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