// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. // Copyright Joyent, Inc. and Node.js contributors. All rights reserved. MIT license. // TODO(petamoriken): enable prefer-primordials for node polyfills // deno-lint-ignore-file no-explicit-any prefer-primordials import { KeyObject } from "ext:deno_node/internal/crypto/keys.ts"; import { kAesKeyLengths } from "ext:deno_node/internal/crypto/util.ts"; import { SecretKeyObject, setOwnedKey, } from "ext:deno_node/internal/crypto/keys.ts"; import { notImplemented } from "ext:deno_node/_utils.ts"; import { ERR_INCOMPATIBLE_OPTION_PAIR, ERR_INVALID_ARG_VALUE, ERR_MISSING_OPTION, } from "ext:deno_node/internal/errors.ts"; import { validateBuffer, validateFunction, validateInt32, validateInteger, validateObject, validateOneOf, validateString, validateUint32, } from "ext:deno_node/internal/validators.mjs"; import { Buffer } from "node:buffer"; import { KeyFormat, KeyType } from "ext:deno_node/internal/crypto/types.ts"; const { core } = globalThis.__bootstrap; const { ops } = core; function validateGenerateKey( type: "hmac" | "aes", options: { length: number }, ) { validateString(type, "type"); validateObject(options, "options"); const { length } = options; switch (type) { case "hmac": validateInteger(length, "options.length", 8, 2 ** 31 - 1); break; case "aes": validateOneOf(length, "options.length", kAesKeyLengths); break; default: throw new ERR_INVALID_ARG_VALUE( "type", type, "must be a supported key type", ); } } export function generateKeySync( type: "hmac" | "aes", options: { length: number; }, ): KeyObject { validateGenerateKey(type, options); const { length } = options; const key = new Uint8Array(Math.floor(length / 8)); ops.op_node_generate_secret(key); return new SecretKeyObject(setOwnedKey(key)); } export function generateKey( type: "hmac" | "aes", options: { length: number; }, callback: (err: Error | null, key: KeyObject) => void, ) { validateGenerateKey(type, options); validateFunction(callback, "callback"); const { length } = options; core.opAsync("op_node_generate_secret_async", Math.floor(length / 8)).then( (key) => { callback(null, new SecretKeyObject(setOwnedKey(key))); }, ); } export interface BasePrivateKeyEncodingOptions { format: T; cipher?: string | undefined; passphrase?: string | undefined; } export interface RSAKeyPairOptions< PubF extends KeyFormat, PrivF extends KeyFormat, > { /** * Key size in bits */ modulusLength: number; /** * Public exponent * @default 0x10001 */ publicExponent?: number | undefined; publicKeyEncoding: { type: "pkcs1" | "spki"; format: PubF; }; privateKeyEncoding: BasePrivateKeyEncodingOptions & { type: "pkcs1" | "pkcs8"; }; } export interface RSAPSSKeyPairOptions< PubF extends KeyFormat, PrivF extends KeyFormat, > { /** * Key size in bits */ modulusLength: number; /** * Public exponent * @default 0x10001 */ publicExponent?: number | undefined; /** * Name of the message digest */ hashAlgorithm?: string; /** * Name of the message digest used by MGF1 */ mgf1HashAlgorithm?: string; /** * Minimal salt length in bytes */ saltLength?: string; publicKeyEncoding: { type: "spki"; format: PubF; }; privateKeyEncoding: BasePrivateKeyEncodingOptions & { type: "pkcs8"; }; } export interface DSAKeyPairOptions< PubF extends KeyFormat, PrivF extends KeyFormat, > { /** * Key size in bits */ modulusLength: number; /** * Size of q in bits */ divisorLength: number; publicKeyEncoding: { type: "spki"; format: PubF; }; privateKeyEncoding: BasePrivateKeyEncodingOptions & { type: "pkcs8"; }; } export interface ECKeyPairOptions< PubF extends KeyFormat, PrivF extends KeyFormat, > { /** * Name of the curve to use. */ namedCurve: string; publicKeyEncoding: { type: "pkcs1" | "spki"; format: PubF; }; privateKeyEncoding: BasePrivateKeyEncodingOptions & { type: "sec1" | "pkcs8"; }; } export interface ED25519KeyPairOptions< PubF extends KeyFormat, PrivF extends KeyFormat, > { publicKeyEncoding: { type: "spki"; format: PubF; }; privateKeyEncoding: BasePrivateKeyEncodingOptions & { type: "pkcs8"; }; } export interface ED448KeyPairOptions< PubF extends KeyFormat, PrivF extends KeyFormat, > { publicKeyEncoding: { type: "spki"; format: PubF; }; privateKeyEncoding: BasePrivateKeyEncodingOptions & { type: "pkcs8"; }; } export interface X25519KeyPairOptions< PubF extends KeyFormat, PrivF extends KeyFormat, > { publicKeyEncoding: { type: "spki"; format: PubF; }; privateKeyEncoding: BasePrivateKeyEncodingOptions & { type: "pkcs8"; }; } export interface X448KeyPairOptions< PubF extends KeyFormat, PrivF extends KeyFormat, > { publicKeyEncoding: { type: "spki"; format: PubF; }; privateKeyEncoding: BasePrivateKeyEncodingOptions & { type: "pkcs8"; }; } export interface RSAKeyPairKeyObjectOptions { /** * Key size in bits */ modulusLength: number; /** * Public exponent * @default 0x10001 */ publicExponent?: number | undefined; } export interface RSAPSSKeyPairKeyObjectOptions { /** * Key size in bits */ modulusLength: number; /** * Public exponent * @default 0x10001 */ publicExponent?: number | undefined; /** * Name of the message digest */ hashAlgorithm?: string; /** * Name of the message digest used by MGF1 */ mgf1HashAlgorithm?: string; /** * Minimal salt length in bytes */ saltLength?: string; } export interface DSAKeyPairKeyObjectOptions { /** * Key size in bits */ modulusLength: number; /** * Size of q in bits */ divisorLength: number; } // deno-lint-ignore no-empty-interface export interface ED25519KeyPairKeyObjectOptions {} // deno-lint-ignore no-empty-interface export interface ED448KeyPairKeyObjectOptions {} // deno-lint-ignore no-empty-interface export interface X25519KeyPairKeyObjectOptions {} // deno-lint-ignore no-empty-interface export interface X448KeyPairKeyObjectOptions {} export interface ECKeyPairKeyObjectOptions { /** * Name of the curve to use */ namedCurve: string; } export function generateKeyPair( type: "rsa", options: RSAKeyPairOptions<"pem", "pem">, callback: (err: Error | null, publicKey: string, privateKey: string) => void, ): void; export function generateKeyPair( type: "rsa", options: RSAKeyPairOptions<"pem", "der">, callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "rsa", options: RSAKeyPairOptions<"der", "pem">, callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, ): void; export function generateKeyPair( type: "rsa", options: RSAKeyPairOptions<"der", "der">, callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "rsa", options: RSAKeyPairKeyObjectOptions, callback: ( err: Error | null, publicKey: KeyObject, privateKey: KeyObject, ) => void, ): void; export function generateKeyPair( type: "rsa-pss", options: RSAPSSKeyPairOptions<"pem", "pem">, callback: (err: Error | null, publicKey: string, privateKey: string) => void, ): void; export function generateKeyPair( type: "rsa-pss", options: RSAPSSKeyPairOptions<"pem", "der">, callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "pem">, callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, ): void; export function generateKeyPair( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "der">, callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "rsa-pss", options: RSAPSSKeyPairKeyObjectOptions, callback: ( err: Error | null, publicKey: KeyObject, privateKey: KeyObject, ) => void, ): void; export function generateKeyPair( type: "dsa", options: DSAKeyPairOptions<"pem", "pem">, callback: (err: Error | null, publicKey: string, privateKey: string) => void, ): void; export function generateKeyPair( type: "dsa", options: DSAKeyPairOptions<"pem", "der">, callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "dsa", options: DSAKeyPairOptions<"der", "pem">, callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, ): void; export function generateKeyPair( type: "dsa", options: DSAKeyPairOptions<"der", "der">, callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "dsa", options: DSAKeyPairKeyObjectOptions, callback: ( err: Error | null, publicKey: KeyObject, privateKey: KeyObject, ) => void, ): void; export function generateKeyPair( type: "ec", options: ECKeyPairOptions<"pem", "pem">, callback: (err: Error | null, publicKey: string, privateKey: string) => void, ): void; export function generateKeyPair( type: "ec", options: ECKeyPairOptions<"pem", "der">, callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "ec", options: ECKeyPairOptions<"der", "pem">, callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, ): void; export function generateKeyPair( type: "ec", options: ECKeyPairOptions<"der", "der">, callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "ec", options: ECKeyPairKeyObjectOptions, callback: ( err: Error | null, publicKey: KeyObject, privateKey: KeyObject, ) => void, ): void; export function generateKeyPair( type: "ed25519", options: ED25519KeyPairOptions<"pem", "pem">, callback: (err: Error | null, publicKey: string, privateKey: string) => void, ): void; export function generateKeyPair( type: "ed25519", options: ED25519KeyPairOptions<"pem", "der">, callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "ed25519", options: ED25519KeyPairOptions<"der", "pem">, callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, ): void; export function generateKeyPair( type: "ed25519", options: ED25519KeyPairOptions<"der", "der">, callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "ed25519", options: ED25519KeyPairKeyObjectOptions | undefined, callback: ( err: Error | null, publicKey: KeyObject, privateKey: KeyObject, ) => void, ): void; export function generateKeyPair( type: "ed448", options: ED448KeyPairOptions<"pem", "pem">, callback: (err: Error | null, publicKey: string, privateKey: string) => void, ): void; export function generateKeyPair( type: "ed448", options: ED448KeyPairOptions<"pem", "der">, callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "ed448", options: ED448KeyPairOptions<"der", "pem">, callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, ): void; export function generateKeyPair( type: "ed448", options: ED448KeyPairOptions<"der", "der">, callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "ed448", options: ED448KeyPairKeyObjectOptions | undefined, callback: ( err: Error | null, publicKey: KeyObject, privateKey: KeyObject, ) => void, ): void; export function generateKeyPair( type: "x25519", options: X25519KeyPairOptions<"pem", "pem">, callback: (err: Error | null, publicKey: string, privateKey: string) => void, ): void; export function generateKeyPair( type: "x25519", options: X25519KeyPairOptions<"pem", "der">, callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "x25519", options: X25519KeyPairOptions<"der", "pem">, callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, ): void; export function generateKeyPair( type: "x25519", options: X25519KeyPairOptions<"der", "der">, callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "x25519", options: X25519KeyPairKeyObjectOptions | undefined, callback: ( err: Error | null, publicKey: KeyObject, privateKey: KeyObject, ) => void, ): void; export function generateKeyPair( type: "x448", options: X448KeyPairOptions<"pem", "pem">, callback: (err: Error | null, publicKey: string, privateKey: string) => void, ): void; export function generateKeyPair( type: "x448", options: X448KeyPairOptions<"pem", "der">, callback: (err: Error | null, publicKey: string, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "x448", options: X448KeyPairOptions<"der", "pem">, callback: (err: Error | null, publicKey: Buffer, privateKey: string) => void, ): void; export function generateKeyPair( type: "x448", options: X448KeyPairOptions<"der", "der">, callback: (err: Error | null, publicKey: Buffer, privateKey: Buffer) => void, ): void; export function generateKeyPair( type: "x448", options: X448KeyPairKeyObjectOptions | undefined, callback: ( err: Error | null, publicKey: KeyObject, privateKey: KeyObject, ) => void, ): void; export function generateKeyPair( type: KeyType, options: unknown, callback: ( err: Error | null, publicKey: any, privateKey: any, ) => void, ) { createJob(kAsync, type, options).then(([privateKey, publicKey]) => { privateKey = new KeyObject("private", setOwnedKey(privateKey)); publicKey = new KeyObject("public", setOwnedKey(publicKey)); if (typeof options === "object" && options !== null) { const { publicKeyEncoding, privateKeyEncoding } = options as any; if (publicKeyEncoding) { publicKey = publicKey.export(publicKeyEncoding); } if (privateKeyEncoding) { privateKey = privateKey.export(privateKeyEncoding); } } callback(null, publicKey, privateKey); }).catch((err) => { callback(err, null, null); }); } export interface KeyPairKeyObjectResult { publicKey: KeyObject; privateKey: KeyObject; } export interface KeyPairSyncResult< T1 extends string | Buffer, T2 extends string | Buffer, > { publicKey: T1; privateKey: T2; } export function generateKeyPairSync( type: "rsa", options: RSAKeyPairOptions<"pem", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "rsa", options: RSAKeyPairOptions<"pem", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "rsa", options: RSAKeyPairOptions<"der", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "rsa", options: RSAKeyPairOptions<"der", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "rsa", options: RSAKeyPairKeyObjectOptions, ): KeyPairKeyObjectResult; export function generateKeyPairSync( type: "rsa-pss", options: RSAPSSKeyPairOptions<"pem", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "rsa-pss", options: RSAPSSKeyPairOptions<"pem", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "rsa-pss", options: RSAPSSKeyPairOptions<"der", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "rsa-pss", options: RSAPSSKeyPairKeyObjectOptions, ): KeyPairKeyObjectResult; export function generateKeyPairSync( type: "dsa", options: DSAKeyPairOptions<"pem", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "dsa", options: DSAKeyPairOptions<"pem", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "dsa", options: DSAKeyPairOptions<"der", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "dsa", options: DSAKeyPairOptions<"der", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "dsa", options: DSAKeyPairKeyObjectOptions, ): KeyPairKeyObjectResult; export function generateKeyPairSync( type: "ec", options: ECKeyPairOptions<"pem", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ec", options: ECKeyPairOptions<"pem", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ec", options: ECKeyPairOptions<"der", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ec", options: ECKeyPairOptions<"der", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ec", options: ECKeyPairKeyObjectOptions, ): KeyPairKeyObjectResult; export function generateKeyPairSync( type: "ed25519", options: ED25519KeyPairOptions<"pem", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ed25519", options: ED25519KeyPairOptions<"pem", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ed25519", options: ED25519KeyPairOptions<"der", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ed25519", options: ED25519KeyPairOptions<"der", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ed25519", options?: ED25519KeyPairKeyObjectOptions, ): KeyPairKeyObjectResult; export function generateKeyPairSync( type: "ed448", options: ED448KeyPairOptions<"pem", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ed448", options: ED448KeyPairOptions<"pem", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ed448", options: ED448KeyPairOptions<"der", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ed448", options: ED448KeyPairOptions<"der", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "ed448", options?: ED448KeyPairKeyObjectOptions, ): KeyPairKeyObjectResult; export function generateKeyPairSync( type: "x25519", options: X25519KeyPairOptions<"pem", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "x25519", options: X25519KeyPairOptions<"pem", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "x25519", options: X25519KeyPairOptions<"der", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "x25519", options: X25519KeyPairOptions<"der", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "x25519", options?: X25519KeyPairKeyObjectOptions, ): KeyPairKeyObjectResult; export function generateKeyPairSync( type: "x448", options: X448KeyPairOptions<"pem", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "x448", options: X448KeyPairOptions<"pem", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "x448", options: X448KeyPairOptions<"der", "pem">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "x448", options: X448KeyPairOptions<"der", "der">, ): KeyPairSyncResult; export function generateKeyPairSync( type: "x448", options?: X448KeyPairKeyObjectOptions, ): KeyPairKeyObjectResult; export function generateKeyPairSync( type: KeyType, options: unknown, ): | KeyPairKeyObjectResult | KeyPairSyncResult { let [privateKey, publicKey] = createJob(kSync, type, options); privateKey = new KeyObject("private", setOwnedKey(privateKey)); publicKey = new KeyObject("public", setOwnedKey(publicKey)); if (typeof options === "object" && options !== null) { const { publicKeyEncoding, privateKeyEncoding } = options as any; if (publicKeyEncoding) { publicKey = publicKey.export(publicKeyEncoding); } if (privateKeyEncoding) { privateKey = privateKey.export(privateKeyEncoding); } } return { publicKey, privateKey }; } const kSync = 0; const kAsync = 1; function createJob(mode, type, options) { validateString(type, "type"); if (options !== undefined) { validateObject(options, "options"); } switch (type) { case "rsa": case "rsa-pss": { validateObject(options, "options"); const { modulusLength } = options; validateUint32(modulusLength, "options.modulusLength"); let { publicExponent } = options; if (publicExponent == null) { publicExponent = 0x10001; } else { validateUint32(publicExponent, "options.publicExponent"); } if (type === "rsa") { if (mode === kSync) { return ops.op_node_generate_rsa( modulusLength, publicExponent, ); } else { return core.opAsync( "op_node_generate_rsa_async", modulusLength, publicExponent, ); } } const { hash, mgf1Hash, hashAlgorithm, mgf1HashAlgorithm, saltLength, } = options; if (saltLength !== undefined) { validateInt32(saltLength, "options.saltLength", 0); } if (hashAlgorithm !== undefined) { validateString(hashAlgorithm, "options.hashAlgorithm"); } if (mgf1HashAlgorithm !== undefined) { validateString(mgf1HashAlgorithm, "options.mgf1HashAlgorithm"); } if (hash !== undefined) { process.emitWarning( '"options.hash" is deprecated, ' + 'use "options.hashAlgorithm" instead.', "DeprecationWarning", "DEP0154", ); validateString(hash, "options.hash"); if (hashAlgorithm && hash !== hashAlgorithm) { throw new ERR_INVALID_ARG_VALUE("options.hash", hash); } } if (mgf1Hash !== undefined) { process.emitWarning( '"options.mgf1Hash" is deprecated, ' + 'use "options.mgf1HashAlgorithm" instead.', "DeprecationWarning", "DEP0154", ); validateString(mgf1Hash, "options.mgf1Hash"); if (mgf1HashAlgorithm && mgf1Hash !== mgf1HashAlgorithm) { throw new ERR_INVALID_ARG_VALUE("options.mgf1Hash", mgf1Hash); } } if (mode === kSync) { return ops.op_node_generate_rsa( modulusLength, publicExponent, ); } else { return core.opAsync( "op_node_generate_rsa_async", modulusLength, publicExponent, ); } } case "dsa": { validateObject(options, "options"); const { modulusLength } = options; validateUint32(modulusLength, "options.modulusLength"); let { divisorLength } = options; if (divisorLength == null) { divisorLength = 256; } else { validateInt32(divisorLength, "options.divisorLength", 0); } if (mode === kSync) { return ops.op_node_dsa_generate(modulusLength, divisorLength); } return core.opAsync( "op_node_dsa_generate_async", modulusLength, divisorLength, ); } case "ec": { validateObject(options, "options"); const { namedCurve } = options; validateString(namedCurve, "options.namedCurve"); const { paramEncoding } = options; if (paramEncoding == null || paramEncoding === "named") { // pass. } else if (paramEncoding === "explicit") { // TODO(@littledivy): Explicit param encoding is very rarely used, and not supported by the ring crate. throw new TypeError("Explicit encoding is not supported"); } else { throw new ERR_INVALID_ARG_VALUE("options.paramEncoding", paramEncoding); } if (mode === kSync) { return ops.op_node_ec_generate(namedCurve); } else { return core.opAsync("op_node_ec_generate_async", namedCurve); } } case "ed25519": { if (mode === kSync) { return ops.op_node_ed25519_generate(); } return core.opAsync("op_node_ed25519_generate_async"); } case "x25519": { if (mode === kSync) { return ops.op_node_x25519_generate(); } return core.opAsync("op_node_x25519_generate_async"); } case "ed448": case "x448": { notImplemented(type); break; } case "dh": { validateObject(options, "options"); const { group, primeLength, prime, generator } = options; if (group != null) { if (prime != null) { throw new ERR_INCOMPATIBLE_OPTION_PAIR("group", "prime"); } if (primeLength != null) { throw new ERR_INCOMPATIBLE_OPTION_PAIR("group", "primeLength"); } if (generator != null) { throw new ERR_INCOMPATIBLE_OPTION_PAIR("group", "generator"); } validateString(group, "options.group"); if (mode === kSync) { return ops.op_node_dh_generate_group(group); } else { return core.opAsync("op_node_dh_generate_group_async", group); } } if (prime != null) { if (primeLength != null) { throw new ERR_INCOMPATIBLE_OPTION_PAIR("prime", "primeLength"); } validateBuffer(prime, "options.prime"); } else if (primeLength != null) { validateInt32(primeLength, "options.primeLength", 0); } else { throw new ERR_MISSING_OPTION( "At least one of the group, prime, or primeLength options", ); } if (generator != null) { validateInt32(generator, "options.generator", 0); } const g = generator == null ? 2 : generator; if (mode === kSync) { return ops.op_node_dh_generate(prime, primeLength ?? 0, g); } else { return core.opAsync( "op_node_dh_generate_async", prime, primeLength ?? 0, g, ); } } default: // Fall through } throw new ERR_INVALID_ARG_VALUE("type", type, "must be a supported key type"); } export default { generateKey, generateKeySync, generateKeyPair, generateKeyPairSync, };