From df1d36324ffd4f687c406e412f9255bf7a9d8a61 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 19 Nov 2024 01:39:40 +0100 Subject: [PATCH] fix(node/crypto): support promisify on generateKeyPair (#26913) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling `promisify(generateKeyPair)` didn't work as expected. It requires a custom promisify implementation. This was easy to fix thanks to the excellent debugging investigation in https://github.com/denoland/deno/issues/26910 Fixes https://github.com/denoland/deno/issues/26910 Co-authored-by: Bartek IwaƄczuk --- ext/node/polyfills/internal/crypto/keygen.ts | 20 +++++++++++++---- tests/unit_node/crypto/crypto_key_test.ts | 23 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/ext/node/polyfills/internal/crypto/keygen.ts b/ext/node/polyfills/internal/crypto/keygen.ts index 44bfd83277..b023ab1060 100644 --- a/ext/node/polyfills/internal/crypto/keygen.ts +++ b/ext/node/polyfills/internal/crypto/keygen.ts @@ -30,6 +30,7 @@ import { import { Buffer } from "node:buffer"; import { KeyFormat, KeyType } from "ext:deno_node/internal/crypto/types.ts"; import process from "node:process"; +import { promisify } from "node:util"; import { op_node_generate_dh_group_key, @@ -570,7 +571,15 @@ export function generateKeyPair( privateKey: any, ) => void, ) { - createJob(kAsync, type, options).then((pair) => { + _generateKeyPair(type, options) + .then( + (res) => callback(null, res.publicKey, res.privateKey), + (err) => callback(err, null, null), + ); +} + +function _generateKeyPair(type: string, options: unknown) { + return 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); @@ -589,12 +598,15 @@ export function generateKeyPair( } } - callback(null, publicKey, privateKey); - }).catch((err) => { - callback(err, null, null); + return { publicKey, privateKey }; }); } +Object.defineProperty(generateKeyPair, promisify.custom, { + enumerable: false, + value: _generateKeyPair, +}); + export interface KeyPairKeyObjectResult { publicKey: KeyObject; privateKey: KeyObject; diff --git a/tests/unit_node/crypto/crypto_key_test.ts b/tests/unit_node/crypto/crypto_key_test.ts index 3c7ad44232..5d206acc72 100644 --- a/tests/unit_node/crypto/crypto_key_test.ts +++ b/tests/unit_node/crypto/crypto_key_test.ts @@ -677,3 +677,26 @@ Deno.test("generateKeyPair large pem", function () { }, }); }); + +Deno.test("generateKeyPair promisify", async () => { + const passphrase = "mypassphrase"; + const cipher = "aes-256-cbc"; + const modulusLength = 4096; + + const { privateKey, publicKey } = await promisify(generateKeyPair)("rsa", { + modulusLength, + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "pem", + cipher, + passphrase, + }, + }); + + assert(publicKey.startsWith("-----BEGIN PUBLIC KEY-----")); + assert(privateKey.startsWith("-----BEGIN PRIVATE KEY-----")); +});