1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-30 16:40:57 -05:00
denoland-deno/ext/node/polyfills/internal/crypto/keygen.ts
Luca Casonato 4fa8869f24
feat(ext/node): rewrite crypto keys (#24463)
This completely rewrites how we handle key material in ext/node. Changes
in this
PR:

- **Signing**
  - RSA
  - RSA-PSS 🆕
  - DSA 🆕
  - EC
  - ED25519 🆕
- **Verifying**
  - RSA
  - RSA-PSS 🆕
  - DSA 🆕
  - EC 🆕
  - ED25519 🆕
- **Private key import**
  - Passphrase encrypted private keys 🆕
  - RSA
    - PEM
    - DER (PKCS#1) 🆕
    - DER (PKCS#8) 🆕
  - RSA-PSS
    - PEM
    - DER (PKCS#1) 🆕
    - DER (PKCS#8) 🆕
  - DSA 🆕
  - EC
    - PEM
    - DER (SEC1) 🆕
    - DER (PKCS#8) 🆕
  - X25519 🆕
  - ED25519 🆕
  - DH
- **Public key import**
  - RSA
    - PEM
    - DER (PKCS#1) 🆕
    - DER (PKCS#8) 🆕
  - RSA-PSS 🆕
  - DSA 🆕
  - EC 🆕
  - X25519 🆕
  - ED25519 🆕
  - DH 🆕
- **Private key export**
  - RSA 🆕
  - DSA 🆕
  - EC 🆕
  - X25519 🆕
  - ED25519 🆕
  - DH 🆕
- **Public key export**
  - RSA
  - DSA 🆕
  - EC 🆕
  - X25519 🆕
  - ED25519 🆕
  - DH 🆕
- **Key pair generation**
  - Overhauled, but supported APIs unchanged

This PR adds a lot of new individual functionality. But most importantly
because
of the new key material representation, it is now trivial to add new
algorithms
(as shown by this PR).

Now, when adding a new algorithm, it is also widely supported - for
example
previously we supported ED25519 key pair generation, but we could not
import,
export, sign or verify with ED25519. We can now do all of those things.
2024-08-07 08:43:58 +02:00

1019 lines
28 KiB
TypeScript

// Copyright 2018-2024 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 {
PrivateKeyObject,
PublicKeyObject,
SecretKeyObject,
} 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";
import {
op_node_generate_dh_group_key,
op_node_generate_dh_group_key_async,
op_node_generate_dh_key,
op_node_generate_dh_key_async,
op_node_generate_dsa_key,
op_node_generate_dsa_key_async,
op_node_generate_ec_key,
op_node_generate_ec_key_async,
op_node_generate_ed25519_key,
op_node_generate_ed25519_key_async,
op_node_generate_rsa_key,
op_node_generate_rsa_key_async,
op_node_generate_rsa_pss_key,
op_node_generate_rsa_pss_key_async,
op_node_generate_secret_key,
op_node_generate_secret_key_async,
op_node_generate_x25519_key,
op_node_generate_x25519_key_async,
op_node_get_private_key_from_pair,
op_node_get_public_key_from_pair,
} from "ext:core/ops";
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 len = Math.floor(length / 8);
const handle = op_node_generate_secret_key(len);
return new SecretKeyObject(handle);
}
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;
const len = Math.floor(length / 8);
op_node_generate_secret_key_async(len).then((handle) => {
callback(null, new SecretKeyObject(handle));
});
}
export interface BasePrivateKeyEncodingOptions<T extends KeyFormat> {
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<PrivF> & {
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<PrivF> & {
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<PrivF> & {
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<PrivF> & {
type: "sec1" | "pkcs8";
};
}
export interface ED25519KeyPairOptions<
PubF extends KeyFormat,
PrivF extends KeyFormat,
> {
publicKeyEncoding: {
type: "spki";
format: PubF;
};
privateKeyEncoding: BasePrivateKeyEncodingOptions<PrivF> & {
type: "pkcs8";
};
}
export interface ED448KeyPairOptions<
PubF extends KeyFormat,
PrivF extends KeyFormat,
> {
publicKeyEncoding: {
type: "spki";
format: PubF;
};
privateKeyEncoding: BasePrivateKeyEncodingOptions<PrivF> & {
type: "pkcs8";
};
}
export interface X25519KeyPairOptions<
PubF extends KeyFormat,
PrivF extends KeyFormat,
> {
publicKeyEncoding: {
type: "spki";
format: PubF;
};
privateKeyEncoding: BasePrivateKeyEncodingOptions<PrivF> & {
type: "pkcs8";
};
}
export interface X448KeyPairOptions<
PubF extends KeyFormat,
PrivF extends KeyFormat,
> {
publicKeyEncoding: {
type: "spki";
format: PubF;
};
privateKeyEncoding: BasePrivateKeyEncodingOptions<PrivF> & {
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((pair) => {
const privateKeyHandle = op_node_get_private_key_from_pair(pair);
const publicKeyHandle = op_node_get_public_key_from_pair(pair);
const privateKey = new PrivateKeyObject(privateKeyHandle);
const publicKey = new PublicKeyObject(publicKeyHandle);
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<string, string>;
export function generateKeyPairSync(
type: "rsa",
options: RSAKeyPairOptions<"pem", "der">,
): KeyPairSyncResult<string, Buffer>;
export function generateKeyPairSync(
type: "rsa",
options: RSAKeyPairOptions<"der", "pem">,
): KeyPairSyncResult<Buffer, string>;
export function generateKeyPairSync(
type: "rsa",
options: RSAKeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "rsa",
options: RSAKeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export function generateKeyPairSync(
type: "rsa-pss",
options: RSAPSSKeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "rsa-pss",
options: RSAPSSKeyPairOptions<"pem", "der">,
): KeyPairSyncResult<string, Buffer>;
export function generateKeyPairSync(
type: "rsa-pss",
options: RSAPSSKeyPairOptions<"der", "pem">,
): KeyPairSyncResult<Buffer, string>;
export function generateKeyPairSync(
type: "rsa-pss",
options: RSAPSSKeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "rsa-pss",
options: RSAPSSKeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export function generateKeyPairSync(
type: "dsa",
options: DSAKeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "dsa",
options: DSAKeyPairOptions<"pem", "der">,
): KeyPairSyncResult<string, Buffer>;
export function generateKeyPairSync(
type: "dsa",
options: DSAKeyPairOptions<"der", "pem">,
): KeyPairSyncResult<Buffer, string>;
export function generateKeyPairSync(
type: "dsa",
options: DSAKeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "dsa",
options: DSAKeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export function generateKeyPairSync(
type: "ec",
options: ECKeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "ec",
options: ECKeyPairOptions<"pem", "der">,
): KeyPairSyncResult<string, Buffer>;
export function generateKeyPairSync(
type: "ec",
options: ECKeyPairOptions<"der", "pem">,
): KeyPairSyncResult<Buffer, string>;
export function generateKeyPairSync(
type: "ec",
options: ECKeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "ec",
options: ECKeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export function generateKeyPairSync(
type: "ed25519",
options: ED25519KeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "ed25519",
options: ED25519KeyPairOptions<"pem", "der">,
): KeyPairSyncResult<string, Buffer>;
export function generateKeyPairSync(
type: "ed25519",
options: ED25519KeyPairOptions<"der", "pem">,
): KeyPairSyncResult<Buffer, string>;
export function generateKeyPairSync(
type: "ed25519",
options: ED25519KeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "ed25519",
options?: ED25519KeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export function generateKeyPairSync(
type: "ed448",
options: ED448KeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "ed448",
options: ED448KeyPairOptions<"pem", "der">,
): KeyPairSyncResult<string, Buffer>;
export function generateKeyPairSync(
type: "ed448",
options: ED448KeyPairOptions<"der", "pem">,
): KeyPairSyncResult<Buffer, string>;
export function generateKeyPairSync(
type: "ed448",
options: ED448KeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "ed448",
options?: ED448KeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export function generateKeyPairSync(
type: "x25519",
options: X25519KeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "x25519",
options: X25519KeyPairOptions<"pem", "der">,
): KeyPairSyncResult<string, Buffer>;
export function generateKeyPairSync(
type: "x25519",
options: X25519KeyPairOptions<"der", "pem">,
): KeyPairSyncResult<Buffer, string>;
export function generateKeyPairSync(
type: "x25519",
options: X25519KeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "x25519",
options?: X25519KeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export function generateKeyPairSync(
type: "x448",
options: X448KeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "x448",
options: X448KeyPairOptions<"pem", "der">,
): KeyPairSyncResult<string, Buffer>;
export function generateKeyPairSync(
type: "x448",
options: X448KeyPairOptions<"der", "pem">,
): KeyPairSyncResult<Buffer, string>;
export function generateKeyPairSync(
type: "x448",
options: X448KeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "x448",
options?: X448KeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export function generateKeyPairSync(
type: KeyType,
options: unknown,
):
| KeyPairKeyObjectResult
| KeyPairSyncResult<string | Buffer, string | Buffer> {
const pair = createJob(kSync, type, options);
const privateKeyHandle = op_node_get_private_key_from_pair(pair);
const publicKeyHandle = op_node_get_public_key_from_pair(pair);
let privateKey = new PrivateKeyObject(privateKeyHandle);
let publicKey = new PublicKeyObject(publicKeyHandle);
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 op_node_generate_rsa_key(
modulusLength,
publicExponent,
);
} else {
return op_node_generate_rsa_key_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 op_node_generate_rsa_pss_key(
modulusLength,
publicExponent,
hashAlgorithm,
mgf1HashAlgorithm ?? mgf1Hash,
saltLength,
);
} else {
return op_node_generate_rsa_pss_key_async(
modulusLength,
publicExponent,
hashAlgorithm,
mgf1HashAlgorithm ?? mgf1Hash,
saltLength,
);
}
}
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 op_node_generate_dsa_key(modulusLength, divisorLength);
} else {
return op_node_generate_dsa_key_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 op_node_generate_ec_key(namedCurve);
} else {
return op_node_generate_ec_key_async(namedCurve);
}
}
case "ed25519": {
if (mode === kSync) {
return op_node_generate_ed25519_key();
}
return op_node_generate_ed25519_key_async();
}
case "x25519": {
if (mode === kSync) {
return op_node_generate_x25519_key();
}
return op_node_generate_x25519_key_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 op_node_generate_dh_group_key(group);
} else {
return op_node_generate_dh_group_key_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 op_node_generate_dh_key(prime, primeLength ?? 0, g);
} else {
return op_node_generate_dh_key_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,
};