diff options
author | 2023-10-14 12:58:30 -0700 | |
---|---|---|
committer | 2023-10-14 12:58:30 -0700 | |
commit | f9add8b6bea4df3cdbd56a21f17e4cab1a854e4e (patch) | |
tree | 8e5306104d81c67b771181337bba02cd9ec39453 /test/js/node | |
parent | 81a1a58d66c598ea35c42453d0ba4c6341a940fc (diff) | |
parent | 9b5e66453b0879ed77b71dcdbe50e4efa184261e (diff) | |
download | bun-sdl.tar.gz bun-sdl.tar.zst bun-sdl.zip |
Merge branch 'main' into sdlsdl
Diffstat (limited to 'test/js/node')
29 files changed, 2364 insertions, 0 deletions
diff --git a/test/js/node/crypto/crypto.hmac.test.ts b/test/js/node/crypto/crypto.hmac.test.ts new file mode 100644 index 000000000..6a54d1a82 --- /dev/null +++ b/test/js/node/crypto/crypto.hmac.test.ts @@ -0,0 +1,426 @@ +import { Hmac, createHmac, createSecretKey } from "crypto"; +import { test, expect, describe } from "bun:test"; + +function testHmac(algo, key, data, expected) { + if (!Array.isArray(data)) data = [data]; + // If the key is a Buffer, test Hmac with a key object as well. + const keyWrappers = [key => key, ...(typeof key === "string" ? [] : [createSecretKey])]; + const wrapperName = ["default", "KeyObject"]; + + for (const i in keyWrappers) { + const keyWrapper = keyWrappers[i]; + test(`Hmac ${algo} with ${wrapperName[i]} key`, async () => { + const hmac = createHmac(algo, keyWrapper(key)); + for (const chunk of data) hmac.update(chunk); + const actual = hmac.digest("hex"); + expect(actual).toEqual(expected); + }); + } +} + +describe("crypto.Hmac", () => { + test.todo("Hmac is expected to return a new instance", async () => { + const instance = Hmac("sha256", "Node"); + expect(instance instanceof Hmac).toBe(true); + }); + + test("createHmac should throw when using invalid options", async () => { + expect(() => createHmac(null)).toThrow("null is not an object"); + expect(() => createHmac("sha1", null)).toThrow("null is not an object"); + }); + + describe("test HMAC with multiple updates.", async () => { + testHmac("sha1", "Node", ["some data", "to hmac"], "19fd6e1ba73d9ed2224dd5094a71babe85d9a892"); + }); + + describe("test HMAC with Wikipidia test cases", async () => { + const wikipedia = [ + { + key: "key", + data: "The quick brown fox jumps over the lazy dog", + hmac: { + // HMACs lifted from Wikipedia. + md5: "80070713463e7749b90c2dc24911e275", + sha1: "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9", + sha256: "f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc" + "2d1a3cd8", + }, + }, + { + key: "key", + data: "", + hmac: { + // Intermediate test to help debugging. + md5: "63530468a04e386459855da0063b6596", + sha1: "f42bb0eeb018ebbd4597ae7213711ec60760843f", + sha256: "5d5d139563c95b5967b9bd9a8c9b233a9dedb45072794cd232dc1b74" + "832607d0", + }, + }, + { + key: "", + data: "The quick brown fox jumps over the lazy dog", + hmac: { + // Intermediate test to help debugging. + md5: "ad262969c53bc16032f160081c4a07a0", + sha1: "2ba7f707ad5f187c412de3106583c3111d668de8", + sha256: "fb011e6154a19b9a4c767373c305275a5a69e8b68b0b4c9200c383dc" + "ed19a416", + }, + }, + { + key: "", + data: "", + hmac: { + // HMACs lifted from Wikipedia. + md5: "74e6f7298a9c2d168935f58c001bad88", + sha1: "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d", + sha256: "b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c71214" + "4292c5ad", + }, + }, + ]; + + for (const { key, data, hmac } of wikipedia) { + for (const hash in hmac) testHmac(hash, key, data, hmac[hash]); + } + }); + + describe("HMAC-SHA-* (rfc 4231 Test Cases)", async () => { + const rfc4231 = [ + { + key: Buffer.from("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "hex"), + data: Buffer.from("4869205468657265", "hex"), // 'Hi There' + hmac: { + sha224: "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22", + sha256: "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c" + "2e32cff7", + sha384: + "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c" + "7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6", + sha512: + "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b305" + + "45e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f170" + + "2e696c203a126854", + }, + }, + { + key: Buffer.from("4a656665", "hex"), // 'Jefe' + data: Buffer.from("7768617420646f2079612077616e7420666f72206e6f74686" + "96e673f", "hex"), // 'what do ya want for nothing?' + hmac: { + sha224: "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44", + sha256: "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b9" + "64ec3843", + sha384: + "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec373" + "6322445e8e2240ca5e69e2c78b3239ecfab21649", + sha512: + "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7" + + "ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b" + + "636e070a38bce737", + }, + }, + { + key: Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex"), + data: Buffer.from( + "ddddddddddddddddddddddddddddddddddddddddddddddddd" + "ddddddddddddddddddddddddddddddddddddddddddddddddddd", + "hex", + ), + hmac: { + sha224: "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea", + sha256: "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514" + "ced565fe", + sha384: + "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e5" + "5966144b2a5ab39dc13814b94e3ab6e101a34f27", + sha512: + "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33" + + "b2279d39bf3e848279a722c806b485a47e67c807b946a337bee89426" + + "74278859e13292fb", + }, + }, + { + key: Buffer.from("0102030405060708090a0b0c0d0e0f10111213141516171819", "hex"), + data: Buffer.from( + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc" + "dcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", + "hex", + ), + hmac: { + sha224: "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a", + sha256: "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff4" + "6729665b", + sha384: + "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e" + "1f573b4e6801dd23c4a7d679ccf8a386c674cffb", + sha512: + "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050" + + "361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2d" + + "e2adebeb10a298dd", + }, + }, + + { + key: Buffer.from("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "hex"), + // 'Test With Truncation' + data: Buffer.from("546573742057697468205472756e636174696f6e", "hex"), + hmac: { + sha224: "0e2aea68a90c8d37c988bcdb9fca6fa8", + sha256: "a3b6167473100ee06e0c796c2955552b", + sha384: "3abf34c3503b2a23a46efc619baef897", + sha512: "415fad6271580a531d4179bc891d87a6", + }, + truncate: true, + }, + { + key: Buffer.from( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaa", + "hex", + ), + // 'Test Using Larger Than Block-Size Key - Hash Key First' + data: Buffer.from( + "54657374205573696e67204c6172676572205468616e20426" + + "c6f636b2d53697a65204b6579202d2048617368204b657920" + + "4669727374", + "hex", + ), + hmac: { + sha224: "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e", + sha256: "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f" + "0ee37f54", + sha384: + "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05" + "033ac4c60c2ef6ab4030fe8296248df163f44952", + sha512: + "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b0137" + + "83f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec" + + "8b915a985d786598", + }, + }, + { + key: Buffer.from( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaa", + "hex", + ), + // 'This is a test using a larger than block-size key and a larger ' + + // 'than block-size data. The key needs to be hashed before being ' + + // 'used by the HMAC algorithm.' + data: Buffer.from( + "5468697320697320612074657374207573696e672061206c6" + + "172676572207468616e20626c6f636b2d73697a65206b6579" + + "20616e642061206c6172676572207468616e20626c6f636b2" + + "d73697a6520646174612e20546865206b6579206e65656473" + + "20746f20626520686173686564206265666f7265206265696" + + "e6720757365642062792074686520484d414320616c676f72" + + "6974686d2e", + "hex", + ), + hmac: { + sha224: "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1", + sha256: "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f5153" + "5c3a35e2", + sha384: + "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82" + "461e99c5a678cc31e799176d3860e6110c46523e", + sha512: + "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d" + + "20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de04460" + + "65c97440fa8c6a58", + }, + }, + ]; + + for (let i = 0, l = rfc4231.length; i < l; i++) { + for (const hash in rfc4231[i].hmac) { + test(`Test HMAC-${hash} rfc 4231 case ${i + 1}`, async () => { + const str = createHmac(hash, rfc4231[i].key); + str.end(rfc4231[i].data); + let strRes = str.read().toString("hex"); + let actual = createHmac(hash, rfc4231[i].key).update(rfc4231[i].data).digest("hex"); + if (rfc4231[i].truncate) { + actual = actual.substr(0, 32); // first 128 bits == 32 hex chars + strRes = strRes.substr(0, 32); + } + const expected = rfc4231[i].hmac[hash]; + // `Test HMAC-${hash} rfc 4231 case ${i + 1}: ${actual} must be ${expected}`); + expect(actual).toEqual(expected); + expect(actual).toEqual(strRes); + }); + } + } + }); + + describe("HMAC-MD5/SHA1 (rfc 2202 Test Cases)", async () => { + const rfc2202_md5 = [ + { + key: Buffer.from("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "hex"), + data: "Hi There", + hmac: "9294727a3638bb1c13f48ef8158bfc9d", + }, + { + key: "Jefe", + data: "what do ya want for nothing?", + hmac: "750c783e6ab0b503eaa86e310a5db738", + }, + { + key: Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex"), + data: Buffer.from( + "ddddddddddddddddddddddddddddddddddddddddddddddddd" + "ddddddddddddddddddddddddddddddddddddddddddddddddddd", + "hex", + ), + hmac: "56be34521d144c88dbb8c733f0e8b3f6", + }, + { + key: Buffer.from("0102030405060708090a0b0c0d0e0f10111213141516171819", "hex"), + data: Buffer.from( + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc" + + "dcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" + + "cdcdcdcdcd", + "hex", + ), + hmac: "697eaf0aca3a3aea3a75164746ffaa79", + }, + { + key: Buffer.from("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "hex"), + data: "Test With Truncation", + hmac: "56461ef2342edc00f9bab995690efd4c", + }, + { + key: Buffer.from( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaa", + "hex", + ), + data: "Test Using Larger Than Block-Size Key - Hash Key First", + hmac: "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd", + }, + { + key: Buffer.from( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaa", + "hex", + ), + data: "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + hmac: "6f630fad67cda0ee1fb1f562db3aa53e", + }, + ]; + + for (const { key, data, hmac } of rfc2202_md5) { + describe(`rfc 2202 md5 case ${hmac}`, async () => { + testHmac("md5", key, data, hmac); + }); + } + + const rfc2202_sha1 = [ + { + key: Buffer.from("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "hex"), + data: "Hi There", + hmac: "b617318655057264e28bc0b6fb378c8ef146be00", + }, + { + key: "Jefe", + data: "what do ya want for nothing?", + hmac: "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", + }, + { + key: Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex"), + data: Buffer.from( + "ddddddddddddddddddddddddddddddddddddddddddddd" + + "ddddddddddddddddddddddddddddddddddddddddddddd" + + "dddddddddd", + "hex", + ), + hmac: "125d7342b9ac11cd91a39af48aa17b4f63f175d3", + }, + { + key: Buffer.from("0102030405060708090a0b0c0d0e0f10111213141516171819", "hex"), + data: Buffer.from( + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc" + + "dcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" + + "cdcdcdcdcd", + "hex", + ), + hmac: "4c9007f4026250c6bc8414f9bf50c86c2d7235da", + }, + { + key: Buffer.from("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "hex"), + data: "Test With Truncation", + hmac: "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04", + }, + { + key: Buffer.from( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaa", + "hex", + ), + data: "Test Using Larger Than Block-Size Key - Hash Key First", + hmac: "aa4ae5e15272d00e95705637ce8a3b55ed402112", + }, + { + key: Buffer.from( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaa", + "hex", + ), + data: "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + hmac: "e8e99d0f45237d786d6bbaa7965c7808bbff1a91", + }, + ]; + + for (const { key, data, hmac } of rfc2202_sha1) { + describe(`rfc 2202 sha1 case ${hmac}`, async () => { + testHmac("sha1", key, data, hmac); + }); + } + }); + + test("sha256 w00t ucs2", async () => { + expect(createHmac("sha256", "w00t").digest("ucs2")).toEqual(createHmac("sha256", "w00t").digest().toString("ucs2")); + }); + + test("Check initialized -> uninitialized state transition after calling digest().", async () => { + { + const expected = + "\u0010\u0041\u0052\u00c5\u00bf\u00dc\u00a0\u007b\u00c6\u0033" + + "\u00ee\u00bd\u0046\u0019\u009f\u0002\u0055\u00c9\u00f4\u009d"; + + { + const h = createHmac("sha1", "key").update("data"); + expect(h.digest("latin1")).toBe(expected); + expect(h.digest("latin1")).toBe(""); + } + { + const h = createHmac("sha1", "key").update("data"); + expect(h.digest("buffer")).toEqual(Buffer.from(expected, "latin1")); + expect(h.digest("buffer")).toEqual(Buffer.from("")); + } + } + { + const expected = + "\u00f4\u002b\u00b0\u00ee\u00b0\u0018\u00eb\u00bd\u0045\u0097" + + "\u00ae\u0072\u0013\u0071\u001e\u00c6\u0007\u0060\u0084\u003f"; + { + const h = createHmac("sha1", "key"); + expect(h.digest("latin1")).toBe(expected); + expect(h.digest("latin1")).toBe(""); + } + { + const h = createHmac("sha1", "key"); + expect(h.digest("buffer")).toEqual(Buffer.from(expected, "latin1")); + expect(h.digest("buffer")).toEqual(Buffer.from("")); + } + } + }); + test("Invalid digest", async () => { + expect(() => createHmac("sha7", "key")).toThrow(/sha7 is not supported/); + }); + + test("secret digest", async () => { + const buf = Buffer.alloc(0); + const keyObject = createSecretKey(Buffer.alloc(0)); + expect(createHmac("sha256", buf).update("foo").digest()).toEqual( + createHmac("sha256", keyObject).update("foo").digest(), + ); + }); +}); diff --git a/test/js/node/crypto/crypto.key-objects.test.ts b/test/js/node/crypto/crypto.key-objects.test.ts new file mode 100644 index 000000000..b124ca479 --- /dev/null +++ b/test/js/node/crypto/crypto.key-objects.test.ts @@ -0,0 +1,1643 @@ +"use strict"; + +import { + createCipheriv, + createDecipheriv, + createSign, + createVerify, + createSecretKey, + createPublicKey, + createPrivateKey, + KeyObject, + randomBytes, + publicDecrypt, + publicEncrypt, + privateDecrypt, + privateEncrypt, + generateKeyPairSync, + generateKeySync, + generateKeyPair, + sign, + verify, + generateKey, +} from "crypto"; +import { test, it, expect, describe } from "bun:test"; +import { createContext, Script } from "node:vm"; +import fs from "fs"; +import path from "path"; + +const publicPem = fs.readFileSync(path.join(import.meta.dir, "fixtures", "rsa_public.pem"), "ascii"); +const privatePem = fs.readFileSync(path.join(import.meta.dir, "fixtures", "rsa_private.pem"), "ascii"); +const privateEncryptedPem = fs.readFileSync( + path.join(import.meta.dir, "fixtures", "rsa_private_encrypted.pem"), + "ascii", +); + +// Constructs a regular expression for a PEM-encoded key with the given label. +function getRegExpForPEM(label: string, cipher?: string) { + const head = `\\-\\-\\-\\-\\-BEGIN ${label}\\-\\-\\-\\-\\-`; + const rfc1421Header = cipher == null ? "" : `\nProc-Type: 4,ENCRYPTED\nDEK-Info: ${cipher},[^\n]+\n`; + const body = "([a-zA-Z0-9\\+/=]{64}\n)*[a-zA-Z0-9\\+/=]{1,64}"; + const end = `\\-\\-\\-\\-\\-END ${label}\\-\\-\\-\\-\\-`; + return new RegExp(`^${head}${rfc1421Header}\n${body}\n${end}\n$`); +} +const pkcs1PubExp = getRegExpForPEM("RSA PUBLIC KEY"); +const pkcs1PrivExp = getRegExpForPEM("RSA PRIVATE KEY"); +const pkcs1EncExp = (cipher: string) => getRegExpForPEM("RSA PRIVATE KEY", cipher); +const spkiExp = getRegExpForPEM("PUBLIC KEY"); +const pkcs8Exp = getRegExpForPEM("PRIVATE KEY"); +const pkcs8EncExp = getRegExpForPEM("ENCRYPTED PRIVATE KEY"); +const sec1Exp = getRegExpForPEM("EC PRIVATE KEY"); +const sec1EncExp = (cipher: string) => getRegExpForPEM("EC PRIVATE KEY", cipher); + +// Asserts that the size of the given key (in chars or bytes) is within 10% of +// the expected size. +function assertApproximateSize(key: any, expectedSize: number) { + const min = Math.floor(0.9 * expectedSize); + const max = Math.ceil(1.1 * expectedSize); + expect(key.length).toBeGreaterThanOrEqual(min); + expect(key.length).toBeLessThanOrEqual(max); +} +// Tests that a key pair can be used for encryption / decryption. +function testEncryptDecrypt(publicKey: any, privateKey: any) { + const message = "Hello Node.js world!"; + const plaintext = Buffer.from(message, "utf8"); + for (const key of [publicKey, privateKey]) { + const ciphertext = publicEncrypt(key, plaintext); + const received = privateDecrypt(privateKey, ciphertext); + expect(received.toString("utf8")).toEqual(message); + } +} + +// Tests that a key pair can be used for signing / verification. +function testSignVerify(publicKey: any, privateKey: any) { + const message = Buffer.from("Hello Node.js world!"); + + function oldSign(algo: string, data: string | Buffer, key: any) { + return createSign(algo).update(data).sign(key); + } + + function oldVerify(algo: string, data: string | Buffer, key: any, signature: any) { + return createVerify(algo).update(data).verify(key, signature); + } + + for (const signFn of [sign, oldSign]) { + const signature = signFn("SHA256", message, privateKey); + for (const verifyFn of [verify, oldVerify]) { + for (const key of [publicKey, privateKey]) { + const okay = verifyFn("SHA256", message, key, signature); + expect(okay).toBeTrue(); + } + } + } +} + +describe("crypto.KeyObjects", () => { + test("Attempting to create a key using other than CryptoKey should throw", async () => { + expect(() => new KeyObject("secret", "")).toThrow(); + expect(() => new KeyObject("secret")).toThrow(); + expect(() => KeyObject.from("invalid_key")).toThrow(); + }); + test("basics of createSecretKey should work", async () => { + const keybuf = randomBytes(32); + const key = createSecretKey(keybuf); + expect(key.type).toBe("secret"); + expect(key.toString()).toBe("[object KeyObject]"); + expect(key.symmetricKeySize).toBe(32); + expect(key.asymmetricKeyType).toBe(undefined); + expect(key.asymmetricKeyDetails).toBe(undefined); + + const exportedKey = key.export(); + expect(keybuf).toEqual(exportedKey); + + const plaintext = Buffer.from("Hello world", "utf8"); + + const cipher = createCipheriv("aes-256-ecb", key, null); + const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]); + + const decipher = createDecipheriv("aes-256-ecb", key, null); + const deciphered = Buffer.concat([decipher.update(ciphertext), decipher.final()]); + + expect(plaintext).toEqual(deciphered); + }); + + test("Passing an existing public key object to createPublicKey should throw", async () => { + // Passing an existing public key object to createPublicKey should throw. + const publicKey = createPublicKey(publicPem); + expect(() => createPublicKey(publicKey)).toThrow(); + + // Constructing a private key from a public key should be impossible, even + // if the public key was derived from a private key. + expect(() => createPrivateKey(createPublicKey(privatePem))).toThrow(); + + // Similarly, passing an existing private key object to createPrivateKey + // should throw. + const privateKey = createPrivateKey(privatePem); + expect(() => createPrivateKey(privateKey)).toThrow(); + }); + + test("basics should work", async () => { + const jwk = { + e: "AQAB", + n: + "t9xYiIonscC3vz_A2ceR7KhZZlDu_5bye53nCVTcKnWd2seY6UAdKersX6njr83Dd5OVe" + + "1BW_wJvp5EjWTAGYbFswlNmeD44edEGM939B6Lq-_8iBkrTi8mGN4YCytivE24YI0D4XZ" + + "MPfkLSpab2y_Hy4DjQKBq1ThZ0UBnK-9IhX37Ju_ZoGYSlTIGIhzyaiYBh7wrZBoPczIE" + + "u6et_kN2VnnbRUtkYTF97ggcv5h-hDpUQjQW0ZgOMcTc8n-RkGpIt0_iM_bTjI3Tz_gsF" + + "di6hHcpZgbopPL630296iByyigQCPJVzdusFrQN5DeC-zT_nGypQkZanLb4ZspSx9Q", + d: + "ktnq2LvIMqBj4txP82IEOorIRQGVsw1khbm8A-cEpuEkgM71Yi_0WzupKktucUeevQ5i0" + + "Yh8w9e1SJiTLDRAlJz66kdky9uejiWWl6zR4dyNZVMFYRM43ijLC-P8rPne9Fz16IqHFW" + + "5VbJqA1xCBhKmuPMsD71RNxZ4Hrsa7Kt_xglQTYsLbdGIwDmcZihId9VGXRzvmCPsDRf2" + + "fCkAj7HDeRxpUdEiEDpajADc-PWikra3r3b40tVHKWm8wxJLivOIN7GiYXKQIW6RhZgH-" + + "Rk45JIRNKxNagxdeXUqqyhnwhbTo1Hite0iBDexN9tgoZk0XmdYWBn6ElXHRZ7VCDQ", + p: + "8UovlB4nrBm7xH-u7XXBMbqxADQm5vaEZxw9eluc-tP7cIAI4sglMIvL_FMpbd2pEeP_B" + + "kR76NTDzzDuPAZvUGRavgEjy0O9j2NAs_WPK4tZF-vFdunhnSh4EHAF4Ij9kbsUi90NOp" + + "bGfVqPdOaHqzgHKoR23Cuusk9wFQ2XTV8", + q: + "wxHdEYT9xrpfrHPqSBQPpO0dWGKJEkrWOb-76rSfuL8wGR4OBNmQdhLuU9zTIh22pog-X" + + "PnLPAecC-4yu_wtJ2SPCKiKDbJBre0CKPyRfGqzvA3njXwMxXazU4kGs-2Fg-xu_iKbaI" + + "jxXrclBLhkxhBtySrwAFhxxOk6fFcPLSs", + dp: + "qS_Mdr5CMRGGMH0bKhPUWEtAixUGZhJaunX5wY71Xoc_Gh4cnO-b7BNJ_-5L8WZog0vr" + + "6PgiLhrqBaCYm2wjpyoG2o2wDHm-NAlzN_wp3G2EFhrSxdOux-S1c0kpRcyoiAO2n29rN" + + "Da-jOzwBBcU8ACEPdLOCQl0IEFFJO33tl8", + dq: + "WAziKpxLKL7LnL4dzDcx8JIPIuwnTxh0plCDdCffyLaT8WJ9lXbXHFTjOvt8WfPrlDP_" + + "Ylxmfkw5BbGZOP1VLGjZn2DkH9aMiwNmbDXFPdG0G3hzQovx_9fajiRV4DWghLHeT9wzJ" + + "fZabRRiI0VQR472300AVEeX4vgbrDBn600", + qi: + "k7czBCT9rHn_PNwCa17hlTy88C4vXkwbz83Oa-aX5L4e5gw5lhcR2ZuZHLb2r6oMt9rl" + + "D7EIDItSs-u21LOXWPTAlazdnpYUyw_CzogM_PN-qNwMRXn5uXFFhmlP2mVg2EdELTahX" + + "ch8kWqHaCSX53yvqCtRKu_j76V31TfQZGM", + kty: "RSA", + }; + const publicJwk = { kty: jwk.kty, e: jwk.e, n: jwk.n }; + + const publicKey = createPublicKey(publicPem); + expect(publicKey.type).toBe("public"); + expect(publicKey.toString()).toBe("[object KeyObject]"); + expect(publicKey.asymmetricKeyType).toBe("rsa"); + expect(publicKey.symmetricKeySize).toBe(undefined); + + const privateKey = createPrivateKey(privatePem); + expect(privateKey.type).toBe("private"); + expect(privateKey.toString()).toBe("[object KeyObject]"); + expect(privateKey.asymmetricKeyType).toBe("rsa"); + expect(privateKey.symmetricKeySize).toBe(undefined); + + // It should be possible to derive a public key from a private key. + const derivedPublicKey = createPublicKey(privateKey); + expect(derivedPublicKey.type).toBe("public"); + expect(derivedPublicKey.toString()).toBe("[object KeyObject]"); + expect(derivedPublicKey.asymmetricKeyType).toBe("rsa"); + expect(derivedPublicKey.symmetricKeySize).toBe(undefined); + + const publicKeyFromJwk = createPublicKey({ key: publicJwk, format: "jwk" }); + expect(publicKey.type).toBe("public"); + expect(publicKey.toString()).toBe("[object KeyObject]"); + expect(publicKey.asymmetricKeyType).toBe("rsa"); + expect(publicKey.symmetricKeySize).toBe(undefined); + + const privateKeyFromJwk = createPrivateKey({ key: jwk, format: "jwk" }); + expect(privateKey.type).toBe("private"); + expect(privateKey.toString()).toBe("[object KeyObject]"); + expect(privateKey.asymmetricKeyType).toBe("rsa"); + expect(privateKey.symmetricKeySize).toBe(undefined); + + // It should also be possible to import an encrypted private key as a public + // key. + const decryptedKey = createPublicKey({ + key: privateKey.export({ + type: "pkcs8", + format: "pem", + passphrase: Buffer.from("123"), + cipher: "aes-128-cbc", + }), + format: "pem", + passphrase: "123", // this is not documented, but it works + }); + expect(decryptedKey.type).toBe("public"); + expect(decryptedKey.asymmetricKeyType).toBe("rsa"); + + // Exporting the key using JWK should not work since this format does not + // support key encryption + expect(() => { + privateKey.export({ format: "jwk", passphrase: "secret" }); + }).toThrow(); + + // Test exporting with an invalid options object, this should throw. + for (const opt of [undefined, null, "foo", 0, NaN]) { + expect(() => publicKey.export(opt)).toThrow(); + } + + for (const keyObject of [publicKey, derivedPublicKey, publicKeyFromJwk]) { + const exported = keyObject.export({ format: "jwk" }); + expect(exported).toBeDefined(); + const { kty, n, e } = exported as { kty: string; n: string; e: string }; + expect({ kty, n, e }).toEqual({ kty: "RSA", n: jwk.n, e: jwk.e }); + } + + for (const keyObject of [privateKey, privateKeyFromJwk]) { + const exported = keyObject.export({ format: "jwk" }); + expect(exported).toEqual(jwk); + } + + const publicDER = publicKey.export({ + format: "der", + type: "pkcs1", + }); + + const privateDER = privateKey.export({ + format: "der", + type: "pkcs1", + }); + + expect(Buffer.isBuffer(publicDER)).toBe(true); + expect(Buffer.isBuffer(privateDER)).toBe(true); + const plaintext = Buffer.from("Hello world", "utf8"); + + const testDecryption = (fn, ciphertexts, decryptionKeys) => { + for (const ciphertext of ciphertexts) { + for (const key of decryptionKeys) { + const deciphered = fn(key, ciphertext); + expect(deciphered).toEqual(plaintext); + } + } + }; + + testDecryption( + privateDecrypt, + [ + // Encrypt using the public key. + publicEncrypt(publicKey, plaintext), + publicEncrypt({ key: publicKey }, plaintext), + publicEncrypt({ key: publicJwk, format: "jwk" }, plaintext), + + // Encrypt using the private key. + publicEncrypt(privateKey, plaintext), + publicEncrypt({ key: privateKey }, plaintext), + publicEncrypt({ key: jwk, format: "jwk" }, plaintext), + + // Encrypt using a public key derived from the private key. + publicEncrypt(derivedPublicKey, plaintext), + publicEncrypt({ key: derivedPublicKey }, plaintext), + + // Test distinguishing PKCS#1 public and private keys based on the + // DER-encoded data only. + publicEncrypt({ format: "der", type: "pkcs1", key: publicDER }, plaintext), + publicEncrypt({ format: "der", type: "pkcs1", key: privateDER }, plaintext), + ], + [ + privateKey, + { format: "pem", key: privatePem }, + { format: "der", type: "pkcs1", key: privateDER }, + { key: jwk, format: "jwk" }, + ], + ); + + testDecryption( + publicDecrypt, + [privateEncrypt(privateKey, plaintext)], + [ + // Decrypt using the public key. + publicKey, + { format: "pem", key: publicPem }, + { format: "der", type: "pkcs1", key: publicDER }, + { key: publicJwk, format: "jwk" }, + + // Decrypt using the private key. + privateKey, + { format: "pem", key: privatePem }, + { format: "der", type: "pkcs1", key: privateDER }, + { key: jwk, format: "jwk" }, + ], + ); + }); + + test("This should not cause a crash: https://github.com/nodejs/node/issues/25247", async () => { + expect(() => createPrivateKey({ key: "" })).toThrow(); + }); + test("This should not abort either: https://github.com/nodejs/node/issues/29904", async () => { + expect(() => createPrivateKey({ key: Buffer.alloc(0), format: "der", type: "spki" })).toThrow(); + }); + + test("BoringSSL will not parse PKCS#1", async () => { + // Unlike SPKI, PKCS#1 is a valid encoding for private keys (and public keys), + // so it should be accepted by createPrivateKey, but OpenSSL won't parse it. + expect(() => { + const key = createPublicKey(publicPem).export({ + format: "der", + type: "pkcs1", + }); + createPrivateKey({ key, format: "der", type: "pkcs1" }); + }).toThrow("Invalid use of PKCS#1 as private key"); + }); + + [ + { + private: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ed25519_private.pem"), "ascii"), + public: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ed25519_public.pem"), "ascii"), + keyType: "ed25519", + jwk: { + crv: "Ed25519", + x: "K1wIouqnuiA04b3WrMa-xKIKIpfHetNZRv3h9fBf768", + d: "wVK6M3SMhQh3NK-7GRrSV-BVWQx1FO5pW8hhQeu_NdA", + kty: "OKP", + }, + }, + { + private: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ed448_private.pem"), "ascii"), + public: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ed448_public.pem"), "ascii"), + keyType: "ed448", + jwk: { + crv: "Ed448", + x: "oX_ee5-jlcU53-BbGRsGIzly0V-SZtJ_oGXY0udf84q2hTW2RdstLktvwpkVJOoNb7o" + "Dgc2V5ZUA", + d: "060Ke71sN0GpIc01nnGgMDkp0sFNQ09woVo4AM1ffax1-mjnakK0-p-S7-Xf859QewX" + "jcR9mxppY", + kty: "OKP", + }, + }, + { + private: fs.readFileSync(path.join(import.meta.dir, "fixtures", "x25519_private.pem"), "ascii"), + public: fs.readFileSync(path.join(import.meta.dir, "fixtures", "x25519_public.pem"), "ascii"), + keyType: "x25519", + jwk: { + crv: "X25519", + x: "aSb8Q-RndwfNnPeOYGYPDUN3uhAPnMLzXyfi-mqfhig", + d: "mL_IWm55RrALUGRfJYzw40gEYWMvtRkesP9mj8o8Omc", + kty: "OKP", + }, + }, + { + private: fs.readFileSync(path.join(import.meta.dir, "fixtures", "x448_private.pem"), "ascii"), + public: fs.readFileSync(path.join(import.meta.dir, "fixtures", "x448_public.pem"), "ascii"), + keyType: "x448", + jwk: { + crv: "X448", + x: "ioHSHVpTs6hMvghosEJDIR7ceFiE3-Xccxati64oOVJ7NWjfozE7ae31PXIUFq6cVYg" + "vSKsDFPA", + d: "tMNtrO_q8dlY6Y4NDeSTxNQ5CACkHiPvmukidPnNIuX_EkcryLEXt_7i6j6YZMKsrWy" + "S0jlSYJk", + kty: "OKP", + }, + }, + ].forEach(info => { + const keyType = info.keyType; + // X25519 implementation is incomplete, Ed448 and X448 are not supported yet + const test = keyType === "ed25519" ? it : it.skip; + let privateKey: KeyObject; + test(`${keyType} from Buffer should work`, async () => { + const key = createPrivateKey(info.private); + privateKey = key; + expect(key.type).toBe("private"); + expect(key.asymmetricKeyType).toBe(keyType); + expect(key.symmetricKeySize).toBe(undefined); + expect(key.export({ type: "pkcs8", format: "pem" })).toEqual(info.private); + const jwt = key.export({ format: "jwk" }); + expect(jwt).toEqual(info.jwk); + }); + + test(`${keyType} createPrivateKey from jwk should work`, async () => { + const key = createPrivateKey({ key: info.jwk, format: "jwk" }); + expect(key.type).toBe("private"); + expect(key.asymmetricKeyType).toBe(keyType); + expect(key.symmetricKeySize).toBe(undefined); + expect(key.export({ type: "pkcs8", format: "pem" })).toEqual(info.private); + const jwt = key.export({ format: "jwk" }); + expect(jwt).toEqual(info.jwk); + }); + + [ + ["public", info.public], + ["private", info.private], + ["jwk", { key: info.jwk, format: "jwk" }], + ].forEach(([name, input]) => { + test(`${keyType} createPublicKey using ${name} key should work`, async () => { + const key = createPublicKey(input); + expect(key.type).toBe("public"); + expect(key.asymmetricKeyType).toBe(keyType); + expect(key.symmetricKeySize).toBe(undefined); + if (name == "public") { + expect(key.export({ type: "spki", format: "pem" })).toEqual(info.public); + } + if (name == "jwk") { + const jwt = { ...info.jwk }; + delete jwt.d; + const jwk_exported = key.export({ format: "jwk" }); + expect(jwk_exported).toEqual(jwt); + } + }); + }); + }); + + [ + { + private: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ec_p256_private.pem"), "ascii"), + public: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ec_p256_public.pem"), "ascii"), + keyType: "ec", + namedCurve: "prime256v1", + jwk: { + crv: "P-256", + d: "DxBsPQPIgMuMyQbxzbb9toew6Ev6e9O6ZhpxLNgmAEo", + kty: "EC", + x: "X0mMYR_uleZSIPjNztIkAS3_ud5LhNpbiIFp6fNf2Gs", + y: "UbJuPy2Xi0lW7UYTBxPK3yGgDu9EAKYIecjkHX5s2lI", + }, + }, + { + private: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ec_secp256k1_private.pem"), "ascii"), + public: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ec_secp256k1_public.pem"), "ascii"), + keyType: "ec", + namedCurve: "secp256k1", + jwk: { + crv: "secp256k1", + d: "c34ocwTwpFa9NZZh3l88qXyrkoYSxvC0FEsU5v1v4IM", + kty: "EC", + x: "cOzhFSpWxhalCbWNdP2H_yUkdC81C9T2deDpfxK7owA", + y: "-A3DAZTk9IPppN-f03JydgHaFvL1fAHaoXf4SX4NXyo", + }, + }, + { + private: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ec_p384_private.pem"), "ascii"), + public: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ec_p384_public.pem"), "ascii"), + keyType: "ec", + namedCurve: "secp384r1", + jwk: { + crv: "P-384", + d: "dwfuHuAtTlMRn7ZBCBm_0grpc1D_4hPeNAgevgelljuC0--k_LDFosDgBlLLmZsi", + kty: "EC", + x: "hON3nzGJgv-08fdHpQxgRJFZzlK-GZDGa5f3KnvM31cvvjJmsj4UeOgIdy3rDAjV", + y: "fidHhtecNCGCfLqmrLjDena1NSzWzWH1u_oUdMKGo5XSabxzD7-8JZxjpc8sR9cl", + }, + }, + { + private: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ec_p521_private.pem"), "ascii"), + public: fs.readFileSync(path.join(import.meta.dir, "fixtures", "ec_p521_public.pem"), "ascii"), + keyType: "ec", + namedCurve: "secp521r1", + jwk: { + crv: "P-521", + d: "Eghuafcab9jXW4gOQLeDaKOlHEiskQFjiL8klijk6i6DNOXcFfaJ9GW48kxpodw16ttAf9Z1WQstfzpKGUetHIk", + kty: "EC", + x: "AaLFgjwZtznM3N7qsfb86awVXe6c6djUYOob1FN-kllekv0KEXV0bwcDjPGQz5f6MxL" + "CbhMeHRavUS6P10rsTtBn", + y: "Ad3flexBeAfXceNzRBH128kFbOWD6W41NjwKRqqIF26vmgW_8COldGKZjFkOSEASxPB" + "cvA2iFJRUyQ3whC00j0Np", + }, + }, + ].forEach(info => { + const { keyType, namedCurve } = info; + const test = namedCurve === "secp256k1" ? it.skip : it; + let privateKey: KeyObject; + test(`${keyType} ${namedCurve} createPrivateKey from Buffer should work`, async () => { + const key = createPrivateKey(info.private); + privateKey = key; + expect(key.type).toBe("private"); + expect(key.asymmetricKeyType).toBe(keyType); + expect(key.asymmetricKeyDetails?.namedCurve).toBe(namedCurve); + expect(key.symmetricKeySize).toBe(undefined); + expect(key.export({ type: "pkcs8", format: "pem" })).toEqual(info.private); + const jwt = key.export({ format: "jwk" }); + expect(jwt).toEqual(info.jwk); + }); + + test(`${keyType} ${namedCurve} createPrivateKey from jwk should work`, async () => { + const key = createPrivateKey({ key: info.jwk, format: "jwk" }); + expect(key.type).toBe("private"); + expect(key.asymmetricKeyType).toBe(keyType); + expect(key.asymmetricKeyDetails?.namedCurve).toBe(namedCurve); + expect(key.symmetricKeySize).toBe(undefined); + expect(key.export({ type: "pkcs8", format: "pem" })).toEqual(info.private); + const jwt = key.export({ format: "jwk" }); + expect(jwt).toEqual(info.jwk); + }); + + [ + ["public", info.public], + ["private", info.private], + ["jwk", { key: info.jwk, format: "jwk" }], + ].forEach(([name, input]) => { + test(`${keyType} ${namedCurve} createPublicKey using ${name} should work`, async () => { + const key = createPublicKey(input); + expect(key.type).toBe("public"); + expect(key.asymmetricKeyType).toBe(keyType); + expect(key.asymmetricKeyDetails?.namedCurve).toBe(namedCurve); + expect(key.symmetricKeySize).toBe(undefined); + if (name == "public") { + expect(key.export({ type: "spki", format: "pem" })).toEqual(info.public); + } + if (name == "jwk") { + const jwt = { ...info.jwk }; + delete jwt.d; + const jwk_exported = key.export({ format: "jwk" }); + expect(jwk_exported).toEqual(jwt); + } + + const pkey = privateKey || info.private; + const signature = createSign("sha256").update("foo").sign({ key: pkey }); + const okay = createVerify("sha256").update("foo").verify({ key: key }, signature); + expect(okay).toBeTrue(); + }); + }); + }); + + test("private encrypted should work", async () => { + // Reading an encrypted key without a passphrase should fail. + expect(() => createPrivateKey(privateEncryptedPem)).toThrow(); + // Reading an encrypted key with a passphrase that exceeds OpenSSL's buffer + // size limit should fail with an appropriate error code. + expect(() => + createPrivateKey({ + key: privateEncryptedPem, + format: "pem", + passphrase: Buffer.alloc(1025, "a"), + }), + ).toThrow(); + // The buffer has a size of 1024 bytes, so this passphrase should be permitted + // (but will fail decryption). + expect(() => + createPrivateKey({ + key: privateEncryptedPem, + format: "pem", + passphrase: Buffer.alloc(1024, "a"), + }), + ).toThrow(); + const publicKey = createPublicKey({ + key: privateEncryptedPem, + format: "pem", + passphrase: "password", // this is not documented but should work + }); + expect(publicKey.type).toBe("public"); + expect(publicKey.asymmetricKeyType).toBe("rsa"); + expect(publicKey.symmetricKeySize).toBe(undefined); + + const privateKey = createPrivateKey({ + key: privateEncryptedPem, + format: "pem", + passphrase: "password", + }); + expect(privateKey.type).toBe("private"); + expect(privateKey.asymmetricKeyType).toBe("rsa"); + expect(privateKey.symmetricKeySize).toBe(undefined); + }); + + [2048, 4096].forEach(suffix => { + test(`RSA-${suffix} should work`, async () => { + { + const publicPem = fs.readFileSync(path.join(import.meta.dir, "fixtures", `rsa_public_${suffix}.pem`), "ascii"); + const privatePem = fs.readFileSync( + path.join(import.meta.dir, "fixtures", `rsa_private_${suffix}.pem`), + "ascii", + ); + const publicKey = createPublicKey(publicPem); + const expectedKeyDetails = { + modulusLength: suffix, + publicExponent: 65537n, + }; + expect(publicKey.type).toBe("public"); + expect(publicKey.asymmetricKeyType).toBe("rsa"); + expect(publicKey.asymmetricKeyDetails).toEqual(expectedKeyDetails); + + const privateKey = createPrivateKey(privatePem); + expect(privateKey.type).toBe("private"); + expect(privateKey.asymmetricKeyType).toBe("rsa"); + expect(privateKey.asymmetricKeyDetails).toEqual(expectedKeyDetails); + + for (const key of [privatePem, privateKey]) { + // Any algorithm should work. + for (const algo of ["sha1", "sha256"]) { + // Any salt length should work. + for (const saltLength of [undefined, 8, 10, 12, 16, 18, 20]) { + const signature = createSign(algo).update("foo").sign({ key, saltLength }); + for (const pkey of [key, publicKey, publicPem]) { + const okay = createVerify(algo).update("foo").verify({ key: pkey, saltLength }, signature); + expect(okay).toBeTrue(); + } + } + } + } + } + }); + }); + + test("Exporting an encrypted private key requires a cipher", async () => { + // Exporting an encrypted private key requires a cipher + const privateKey = createPrivateKey(privatePem); + expect(() => { + privateKey.export({ + format: "pem", + type: "pkcs8", + passphrase: "super-secret", + }); + }).toThrow(/cipher is required when passphrase is specified/); + }); + + test("secret export buffer format (default)", async () => { + const buffer = Buffer.from("Hello World"); + const keyObject = createSecretKey(buffer); + expect(keyObject.export()).toEqual(buffer); + expect(keyObject.export({})).toEqual(buffer); + expect(keyObject.export({ format: "buffer" })).toEqual(buffer); + expect(keyObject.export({ format: undefined })).toEqual(buffer); + }); + + test('exporting an "oct" JWK from a secret', async () => { + const buffer = Buffer.from("Hello World"); + const keyObject = createSecretKey(buffer); + const jwk = keyObject.export({ format: "jwk" }); + expect(jwk).toEqual({ kty: "oct", k: "SGVsbG8gV29ybGQ" }); + }); + + test("secret equals", async () => { + { + const first = Buffer.from("Hello"); + const second = Buffer.from("World"); + const keyObject = createSecretKey(first); + expect(createSecretKey(first).equals(createSecretKey(first))).toBeTrue(); + expect(createSecretKey(first).equals(createSecretKey(second))).toBeFalse(); + + expect(() => keyObject.equals(0)).toThrow(/otherKey must be a KeyObject/); + + expect(keyObject.equals(keyObject)).toBeTrue(); + expect(keyObject.equals(createPublicKey(publicPem))).toBeFalse(); + expect(keyObject.equals(createPrivateKey(privatePem))).toBeFalse(); + } + + { + const first = createSecretKey(Buffer.alloc(0)); + const second = createSecretKey(new ArrayBuffer(0)); + const third = createSecretKey(Buffer.alloc(1)); + expect(first.equals(first)).toBeTrue(); + expect(first.equals(second)).toBeTrue(); + expect(first.equals(third)).toBeFalse(); + expect(third.equals(first)).toBeFalse(); + } + }); + + ["ed25519", "x25519"].forEach(keyType => { + const test = keyType === "ed25519" ? it : it.skip; + test(`${keyType} equals should work`, async () => { + const first = generateKeyPairSync(keyType); + const second = generateKeyPairSync(keyType); + + const secret = generateKeySync("aes", { length: 128 }); + + expect(first.publicKey.equals(first.publicKey)).toBeTrue(); + + expect(first.publicKey.equals(createPublicKey(first.publicKey.export({ format: "pem", type: "spki" })))); + + expect(first.publicKey.equals(second.publicKey)).toBeFalse(); + expect(first.publicKey.equals(second.privateKey)).toBeFalse(); + expect(first.publicKey.equals(secret)).toBeFalse(); + + expect(first.privateKey.equals(first.privateKey)).toBeTrue(); + expect( + first.privateKey.equals(createPrivateKey(first.privateKey.export({ format: "pem", type: "pkcs8" }))), + ).toBeTrue(); + expect(first.privateKey.equals(second.privateKey)).toBeFalse(); + expect(first.privateKey.equals(second.publicKey)).toBeFalse(); + expect(first.privateKey.equals(secret)).toBeFalse(); + }); + }); + + test("This should not cause a crash: https://github.com/nodejs/node/issues/44471", async () => { + for (const key of ["", "foo", null, undefined, true, Boolean]) { + expect(() => { + createPublicKey({ key, format: "jwk" }); + }).toThrow(); + expect(() => { + createPrivateKey({ key, format: "jwk" }); + }).toThrow(); + } + }); + + ["hmac", "aes"].forEach(type => { + [128, 256].forEach(length => { + test(`generateKey ${type} ${length}`, async () => { + { + const key = generateKeySync(type, { length }); + expect(key).toBeDefined(); + const keybuf = key.export(); + expect(keybuf.byteLength).toBe(length / 8); + } + + const { promise, resolve, reject } = Promise.withResolvers(); + generateKey(type, { length }, (err, key) => { + if (err) { + reject(err); + } else { + resolve(key); + } + }); + + { + const key = await promise; + expect(key).toBeDefined(); + const keybuf = key.export(); + expect(keybuf.byteLength).toBe(length / 8); + } + }); + }); + }); + describe("Test async elliptic curve key generation with 'jwk' encoding and named curve", () => { + ["P-384", "P-256", "P-521", "secp256k1"].forEach(curve => { + const test = curve === "secp256k1" ? it.skip : it; + test(`should work with ${curve}`, async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + "ec", + { + namedCurve: curve, + publicKeyEncoding: { + format: "jwk", + }, + privateKeyEncoding: { + format: "jwk", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey, privateKey } = await (promise as Promise<{ publicKey: any; privateKey: any }>); + expect(typeof publicKey).toBe("object"); + expect(typeof privateKey).toBe("object"); + expect(publicKey.x).toBe(privateKey.x); + expect(publicKey.y).toBe(publicKey.y); + expect(publicKey.d).toBeUndefined(); + expect(privateKey.d).toBeDefined(); + expect(publicKey.kty).toEqual("EC"); + expect(publicKey.kty).toEqual(privateKey.kty); + expect(publicKey.crv).toEqual(curve); + expect(publicKey.crv).toEqual(privateKey.crv); + }); + }); + }); + + describe("Test async elliptic curve key generation with 'jwk' encoding and RSA.", () => { + [256, 1024, 2048].forEach(modulusLength => { + test(`should work with ${modulusLength}`, async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + "rsa", + { + modulusLength, + publicKeyEncoding: { + format: "jwk", + }, + privateKeyEncoding: { + format: "jwk", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey, privateKey } = await (promise as Promise<{ publicKey: any; privateKey: any }>); + expect(typeof publicKey).toEqual("object"); + expect(typeof privateKey).toEqual("object"); + expect(publicKey.kty).toEqual("RSA"); + expect(publicKey.kty).toEqual(privateKey.kty); + expect(typeof publicKey.n).toEqual("string"); + expect(publicKey.n).toEqual(privateKey.n); + expect(typeof publicKey.e).toEqual("string"); + expect(publicKey.e).toEqual(privateKey.e); + expect(typeof privateKey.d).toEqual("string"); + expect(typeof privateKey.p).toEqual("string"); + expect(typeof privateKey.q).toEqual("string"); + expect(typeof privateKey.dp).toEqual("string"); + expect(typeof privateKey.dq).toEqual("string"); + expect(typeof privateKey.qi).toEqual("string"); + }); + }); + }); + + describe("Test async elliptic curve key generation with 'jwk' encoding", () => { + ["ed25519", "ed448", "x25519", "x448"].forEach(type => { + const test = type === "ed25519" ? it : it.skip; + test(`should work with ${type}`, async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + type, + { + publicKeyEncoding: { + format: "jwk", + }, + privateKeyEncoding: { + format: "jwk", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey, privateKey } = await (promise as Promise<{ publicKey: any; privateKey: any }>); + expect(typeof publicKey).toEqual("object"); + expect(typeof privateKey).toEqual("object"); + expect(publicKey.x).toEqual(privateKey.x); + expect(publicKey.d).toBeUndefined(); + expect(privateKey.d).toBeDefined(); + expect(publicKey.kty).toEqual("OKP"); + expect(publicKey.kty).toEqual(privateKey.kty); + const expectedCrv = `${type.charAt(0).toUpperCase()}${type.slice(1)}`; + expect(publicKey.crv).toEqual(expectedCrv); + expect(publicKey.crv).toEqual(privateKey.crv); + }); + }); + }); + + test(`Test async RSA key generation with an encrypted private key, but encoded as DER`, async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + "rsa", + { + publicExponent: 0x10001, + modulusLength: 512, + publicKeyEncoding: { + type: "pkcs1", + format: "der", + }, + privateKeyEncoding: { + type: "pkcs1", + format: "pem", + cipher: "aes-256-cbc", + passphrase: "secret", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey: publicKeyDER, privateKey } = await (promise as Promise<{ + publicKey: Buffer; + privateKey: string; + }>); + expect(Buffer.isBuffer(publicKeyDER)).toBeTrue(); + assertApproximateSize(publicKeyDER, 74); + + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(pkcs1EncExp("AES-256-CBC")); + + const publicKey = { + key: publicKeyDER, + type: "pkcs1", + format: "der", + }; + expect(() => { + testEncryptDecrypt(publicKey, privateKey); + }).toThrow(); + + const key = { key: privateKey, passphrase: "secret" }; + testEncryptDecrypt(publicKey, key); + testSignVerify(publicKey, key); + }); + + test(`Test async RSA key generation with an encrypted private key`, async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + "rsa", + { + publicExponent: 0x10001, + modulusLength: 512, + publicKeyEncoding: { + type: "pkcs1", + format: "der", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "der", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey: publicKeyDER, privateKey: privateKeyDER } = await (promise as Promise<{ + publicKey: Buffer; + privateKey: Buffer; + }>); + expect(Buffer.isBuffer(publicKeyDER)).toBeTrue(); + assertApproximateSize(publicKeyDER, 74); + + expect(Buffer.isBuffer(privateKeyDER)).toBeTrue(); + + const publicKey = { + key: publicKeyDER, + type: "pkcs1", + format: "der", + }; + const privateKey = { + key: privateKeyDER, + format: "der", + type: "pkcs8", + passphrase: "secret", + }; + testEncryptDecrypt(publicKey, privateKey); + testSignVerify(publicKey, privateKey); + }); + + test(`Test async elliptic curve key generation, e.g. for ECDSA, with an encrypted private key`, async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + "ec", + { + namedCurve: "P-256", + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "pem", + cipher: "aes-128-cbc", + passphrase: "top secret", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey, privateKey } = await (promise as Promise<{ publicKey: string; privateKey: string }>); + expect(typeof publicKey).toBe("string"); + expect(publicKey).toMatch(spkiExp); + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(pkcs8EncExp); + + expect(() => { + testSignVerify(publicKey, privateKey); + }).toThrow(); + + testSignVerify(publicKey, { + key: privateKey, + passphrase: "top secret", + }); + }); + + test(`Test async explicit elliptic curve key generation with an encrypted private key`, async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + "ec", + { + namedCurve: "prime256v1", + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "sec1", + format: "pem", + cipher: "aes-128-cbc", + passphrase: "secret", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey, privateKey } = await (promise as Promise<{ publicKey: string; privateKey: string }>); + expect(typeof publicKey).toBe("string"); + expect(publicKey).toMatch(spkiExp); + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(sec1EncExp("AES-128-CBC")); + + expect(() => { + testSignVerify(publicKey, privateKey); + }).toThrow(); + + testSignVerify(publicKey, { + key: privateKey, + passphrase: "secret", + }); + }); + + test(`Test async explicit elliptic curve key generation, e.g. for ECDSA, with a SEC1 private key`, async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + "ec", + { + namedCurve: "prime256v1", + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "sec1", + format: "pem", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey, privateKey } = await (promise as Promise<{ publicKey: string; privateKey: string }>); + expect(typeof publicKey).toBe("string"); + expect(publicKey).toMatch(spkiExp); + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(sec1Exp); + testSignVerify(publicKey, privateKey); + }); + + test(`Test async elliptic curve key generation, e.g. for ECDSA, with an encrypted private key`, async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + "ec", + { + namedCurve: "prime256v1", + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "pem", + cipher: "aes-128-cbc", + passphrase: "top secret", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey, privateKey } = await (promise as Promise<{ publicKey: string; privateKey: string }>); + expect(typeof publicKey).toBe("string"); + expect(publicKey).toMatch(spkiExp); + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(pkcs8EncExp); + + expect(() => { + testSignVerify(publicKey, privateKey); + }).toThrow(); + + testSignVerify(publicKey, { + key: privateKey, + passphrase: "top secret", + }); + }); + + describe("Test sync elliptic curve key generation with 'jwk' encoding and named curve", () => { + ["P-384", "P-256", "P-521", "secp256k1"].forEach(curve => { + const test = curve === "secp256k1" ? it.skip : it; + test(`should work with ${curve}`, async () => { + const { publicKey, privateKey } = generateKeyPairSync("ec", { + namedCurve: curve, + publicKeyEncoding: { + format: "jwk", + }, + privateKeyEncoding: { + format: "jwk", + }, + }); + expect(typeof publicKey).toBe("object"); + expect(typeof privateKey).toBe("object"); + expect(publicKey.x).toBe(privateKey.x); + expect(publicKey.y).toBe(publicKey.y); + expect(publicKey.d).toBeUndefined(); + expect(privateKey.d).toBeDefined(); + expect(publicKey.kty).toEqual("EC"); + expect(publicKey.kty).toEqual(privateKey.kty); + expect(publicKey.crv).toEqual(curve); + expect(publicKey.crv).toEqual(privateKey.crv); + }); + }); + }); + + describe("Test sync elliptic curve key generation with 'jwk' encoding and RSA.", () => { + [256, 1024, 2048].forEach(modulusLength => { + test(`should work with ${modulusLength}`, async () => { + const { publicKey, privateKey } = generateKeyPairSync("rsa", { + modulusLength, + publicKeyEncoding: { + format: "jwk", + }, + privateKeyEncoding: { + format: "jwk", + }, + }); + expect(typeof publicKey).toEqual("object"); + expect(typeof privateKey).toEqual("object"); + expect(publicKey.kty).toEqual("RSA"); + expect(publicKey.kty).toEqual(privateKey.kty); + expect(typeof publicKey.n).toEqual("string"); + expect(publicKey.n).toEqual(privateKey.n); + expect(typeof publicKey.e).toEqual("string"); + expect(publicKey.e).toEqual(privateKey.e); + expect(typeof privateKey.d).toEqual("string"); + expect(typeof privateKey.p).toEqual("string"); + expect(typeof privateKey.q).toEqual("string"); + expect(typeof privateKey.dp).toEqual("string"); + expect(typeof privateKey.dq).toEqual("string"); + expect(typeof privateKey.qi).toEqual("string"); + }); + }); + }); + + describe("Test sync elliptic curve key generation with 'jwk' encoding", () => { + ["ed25519", "ed448", "x25519", "x448"].forEach(type => { + const test = type === "ed25519" ? it : it.skip; + test(`should work with ${type}`, async () => { + const { publicKey, privateKey } = generateKeyPairSync(type, { + publicKeyEncoding: { + format: "jwk", + }, + privateKeyEncoding: { + format: "jwk", + }, + }); + + expect(typeof publicKey).toEqual("object"); + expect(typeof privateKey).toEqual("object"); + expect(publicKey.x).toEqual(privateKey.x); + expect(publicKey.d).toBeUndefined(); + expect(privateKey.d).toBeDefined(); + expect(publicKey.kty).toEqual("OKP"); + expect(publicKey.kty).toEqual(privateKey.kty); + const expectedCrv = `${type.charAt(0).toUpperCase()}${type.slice(1)}`; + expect(publicKey.crv).toEqual(expectedCrv); + expect(publicKey.crv).toEqual(privateKey.crv); + }); + }); + }); + + test(`Test sync RSA key generation with an encrypted private key, but encoded as DER`, async () => { + const { publicKey: publicKeyDER, privateKey } = generateKeyPairSync("rsa", { + publicExponent: 0x10001, + modulusLength: 512, + publicKeyEncoding: { + type: "pkcs1", + format: "der", + }, + privateKeyEncoding: { + type: "pkcs1", + format: "pem", + cipher: "aes-256-cbc", + passphrase: "secret", + }, + }); + + expect(Buffer.isBuffer(publicKeyDER)).toBeTrue(); + assertApproximateSize(publicKeyDER, 74); + + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(pkcs1EncExp("AES-256-CBC")); + + const publicKey = { + key: publicKeyDER, + type: "pkcs1", + format: "der", + }; + expect(() => { + testEncryptDecrypt(publicKey, privateKey); + }).toThrow(); + + const key = { key: privateKey, passphrase: "secret" }; + testEncryptDecrypt(publicKey, key); + testSignVerify(publicKey, key); + }); + + test(`Test sync RSA key generation with an encrypted private key`, async () => { + const { publicKey: publicKeyDER, privateKey: privateKeyDER } = generateKeyPairSync("rsa", { + publicExponent: 0x10001, + modulusLength: 512, + publicKeyEncoding: { + type: "pkcs1", + format: "der", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "der", + }, + }); + + expect(Buffer.isBuffer(publicKeyDER)).toBeTrue(); + assertApproximateSize(publicKeyDER, 74); + + expect(Buffer.isBuffer(privateKeyDER)).toBeTrue(); + + const publicKey = { + key: publicKeyDER, + type: "pkcs1", + format: "der", + }; + const privateKey = { + key: privateKeyDER, + format: "der", + type: "pkcs8", + passphrase: "secret", + }; + testEncryptDecrypt(publicKey, privateKey); + testSignVerify(publicKey, privateKey); + }); + + test(`Test sync elliptic curve key generation, e.g. for ECDSA, with an encrypted private key`, async () => { + const { publicKey, privateKey } = generateKeyPairSync("ec", { + namedCurve: "P-256", + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "pem", + cipher: "aes-128-cbc", + passphrase: "top secret", + }, + }); + + expect(typeof publicKey).toBe("string"); + expect(publicKey).toMatch(spkiExp); + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(pkcs8EncExp); + + expect(() => { + testSignVerify(publicKey, privateKey); + }).toThrow(); + + testSignVerify(publicKey, { + key: privateKey, + passphrase: "top secret", + }); + }); + + test(`Test sync explicit elliptic curve key generation with an encrypted private key`, async () => { + const { publicKey, privateKey } = generateKeyPairSync( + "ec", + { + namedCurve: "prime256v1", + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "sec1", + format: "pem", + cipher: "aes-128-cbc", + passphrase: "secret", + }, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + expect(typeof publicKey).toBe("string"); + expect(publicKey).toMatch(spkiExp); + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(sec1EncExp("AES-128-CBC")); + + expect(() => { + testSignVerify(publicKey, privateKey); + }).toThrow(); + + testSignVerify(publicKey, { + key: privateKey, + passphrase: "secret", + }); + }); + + test(`Test sync explicit elliptic curve key generation, e.g. for ECDSA, with a SEC1 private key`, async () => { + const { publicKey, privateKey } = generateKeyPairSync("ec", { + namedCurve: "prime256v1", + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "sec1", + format: "pem", + }, + }); + + expect(typeof publicKey).toBe("string"); + expect(publicKey).toMatch(spkiExp); + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(sec1Exp); + testSignVerify(publicKey, privateKey); + }); + + test(`Test sync elliptic curve key generation, e.g. for ECDSA, with an encrypted private key`, async () => { + const { publicKey, privateKey } = generateKeyPairSync("ec", { + namedCurve: "prime256v1", + publicKeyEncoding: { + type: "spki", + format: "pem", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "pem", + cipher: "aes-128-cbc", + passphrase: "top secret", + }, + }); + + expect(typeof publicKey).toBe("string"); + expect(publicKey).toMatch(spkiExp); + expect(typeof privateKey).toBe("string"); + expect(privateKey).toMatch(pkcs8EncExp); + + expect(() => { + testSignVerify(publicKey, privateKey); + }).toThrow(); + + testSignVerify(publicKey, { + key: privateKey, + passphrase: "top secret", + }); + }); + // SKIPED because we round the key size to the nearest multiple of 8 like documented + test.skip(`this tests check that generateKeyPair returns correct bit length in KeyObject's asymmetricKeyDetails.`, async () => { + // This tests check that generateKeyPair returns correct bit length in + // https://github.com/nodejs/node/issues/46102#issuecomment-1372153541 + const { promise, resolve, reject } = Promise.withResolvers(); + generateKeyPair( + "rsa", + { + modulusLength: 513, + }, + (err, publicKey, privateKey) => { + if (err) { + return reject(err); + } + resolve({ publicKey, privateKey }); + }, + ); + + const { publicKey, privateKey } = await (promise as Promise<{ publicKey: KeyObject; privateKey: KeyObject }>); + expect(publicKey.asymmetricKeyDetails?.modulusLength).toBe(513); + expect(privateKey.asymmetricKeyDetails?.modulusLength).toBe(513); + }); + + function testRunInContext(fn: any) { + test("can generate key", () => { + const context = createContext({ generateKeySync }); + const result = fn(`generateKeySync("aes", { length: 128 })`, context); + expect(result).toBeDefined(); + const keybuf = result.export(); + expect(keybuf.byteLength).toBe(128 / 8); + }); + test("can be used on another context", () => { + const context = createContext({ generateKeyPairSync, assertApproximateSize, testEncryptDecrypt, testSignVerify }); + const result = fn( + ` + const { publicKey: publicKeyDER, privateKey: privateKeyDER } = generateKeyPairSync( + "rsa", + { + publicExponent: 0x10001, + modulusLength: 512, + publicKeyEncoding: { + type: "pkcs1", + format: "der", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "der", + }, + } + ); + + + assertApproximateSize(publicKeyDER, 74); + + const publicKey = { + key: publicKeyDER, + type: "pkcs1", + format: "der", + }; + const privateKey = { + key: privateKeyDER, + format: "der", + type: "pkcs8", + passphrase: "secret", + }; + testEncryptDecrypt(publicKey, privateKey); + testSignVerify(publicKey, privateKey); + `, + context, + ); + }); + } + describe("Script", () => { + describe("runInContext()", () => { + testRunInContext((code, context, options) => { + // @ts-expect-error + const script = new Script(code, options); + return script.runInContext(context); + }); + }); + describe("runInNewContext()", () => { + testRunInContext((code, context, options) => { + // @ts-expect-error + const script = new Script(code, options); + return script.runInNewContext(context); + }); + }); + describe("runInThisContext()", () => { + testRunInContext((code, context, options) => { + // @ts-expect-error + const script = new Script(code, options); + return script.runInThisContext(context); + }); + }); + }); +}); + +test.todo("RSA-PSS should work", async () => { + // Test RSA-PSS. + { + // This key pair does not restrict the message digest algorithm or salt + // length. + // const publicPem = fs.readFileSync(path.join(import.meta.dir, "fixtures", "rsa_pss_public_2048.pem"), "ascii"); + // const privatePem = fs.readFileSync(path.join(import.meta.dir, "fixtures", "rsa_pss_private_2048.pem"), "ascii"); + // const publicKey = createPublicKey(publicPem); + // const privateKey = createPrivateKey(privatePem); + // // Because no RSASSA-PSS-params appears in the PEM, no defaults should be + // // added for the PSS parameters. This is different from an empty + // // RSASSA-PSS-params sequence (see test below). + // const expectedKeyDetails = { + // modulusLength: 2048, + // publicExponent: 65537n, + // }; + // expect(publicKey.type).toBe("public"); + // expect(publicKey.asymmetricKeyType).toBe("rsa-pss"); + // expect(publicKey.asymmetricKeyDetails).toBe(expectedKeyDetails); + // expect(privateKey.type).toBe("private"); + // expect(privateKey.asymmetricKeyType).toBe("rsa-pss"); + // expect(privateKey.asymmetricKeyDetails).toBe(expectedKeyDetails); + // assert.throws( + // () => publicKey.export({ format: 'jwk' }), + // { code: 'ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE' }); + // assert.throws( + // () => privateKey.export({ format: 'jwk' }), + // { code: 'ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE' }); + // for (const key of [privatePem, privateKey]) { + // // Any algorithm should work. + // for (const algo of ['sha1', 'sha256']) { + // // Any salt length should work. + // for (const saltLength of [undefined, 8, 10, 12, 16, 18, 20]) { + // const signature = createSign(algo) + // .update('foo') + // .sign({ key, saltLength }); + // for (const pkey of [key, publicKey, publicPem]) { + // const okay = createVerify(algo) + // .update('foo') + // .verify({ key: pkey, saltLength }, signature); + // assert.ok(okay); + // } + // } + // } + // } + // // Exporting the key using PKCS#1 should not work since this would discard + // // any algorithm restrictions. + // assert.throws(() => { + // publicKey.export({ format: 'pem', type: 'pkcs1' }); + // }, { + // code: 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS' + // }); + // { + // // This key pair enforces sha1 as the message digest and the MGF1 + // // message digest and a salt length of 20 bytes. + // const publicPem = fixtures.readKey('rsa_pss_public_2048_sha1_sha1_20.pem'); + // const privatePem = + // fixtures.readKey('rsa_pss_private_2048_sha1_sha1_20.pem'); + // const publicKey = createPublicKey(publicPem); + // const privateKey = createPrivateKey(privatePem); + // // Unlike the previous key pair, this key pair contains an RSASSA-PSS-params + // // sequence. However, because all values in the RSASSA-PSS-params are set to + // // their defaults (see RFC 3447), the ASN.1 structure contains an empty + // // sequence. Node.js should add the default values to the key details. + // const expectedKeyDetails = { + // modulusLength: 2048, + // publicExponent: 65537n, + // hashAlgorithm: 'sha1', + // mgf1HashAlgorithm: 'sha1', + // saltLength: 20 + // }; + // assert.strictEqual(publicKey.type, 'public'); + // assert.strictEqual(publicKey.asymmetricKeyType, 'rsa-pss'); + // assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); + // assert.strictEqual(privateKey.type, 'private'); + // assert.strictEqual(privateKey.asymmetricKeyType, 'rsa-pss'); + // assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); + // } + // { + // // This key pair enforces sha256 as the message digest and the MGF1 + // // message digest and a salt length of at least 16 bytes. + // const publicPem = + // fixtures.readKey('rsa_pss_public_2048_sha256_sha256_16.pem'); + // const privatePem = + // fixtures.readKey('rsa_pss_private_2048_sha256_sha256_16.pem'); + // const publicKey = createPublicKey(publicPem); + // const privateKey = createPrivateKey(privatePem); + // assert.strictEqual(publicKey.type, 'public'); + // assert.strictEqual(publicKey.asymmetricKeyType, 'rsa-pss'); + // assert.strictEqual(privateKey.type, 'private'); + // assert.strictEqual(privateKey.asymmetricKeyType, 'rsa-pss'); + // for (const key of [privatePem, privateKey]) { + // // Signing with anything other than sha256 should fail. + // assert.throws(() => { + // createSign('sha1').sign(key); + // }, /digest not allowed/); + // // Signing with salt lengths less than 16 bytes should fail. + // for (const saltLength of [8, 10, 12]) { + // assert.throws(() => { + // createSign('sha1').sign({ key, saltLength }); + // }, /pss saltlen too small/); + // } + // // Signing with sha256 and appropriate salt lengths should work. + // for (const saltLength of [undefined, 16, 18, 20]) { + // const signature = createSign('sha256') + // .update('foo') + // .sign({ key, saltLength }); + // for (const pkey of [key, publicKey, publicPem]) { + // const okay = createVerify('sha256') + // .update('foo') + // .verify({ key: pkey, saltLength }, signature); + // assert.ok(okay); + // } + // } + // } + // } + // { + // // This key enforces sha512 as the message digest and sha256 as the MGF1 + // // message digest. + // const publicPem = + // fixtures.readKey('rsa_pss_public_2048_sha512_sha256_20.pem'); + // const privatePem = + // fixtures.readKey('rsa_pss_private_2048_sha512_sha256_20.pem'); + // const publicKey = createPublicKey(publicPem); + // const privateKey = createPrivateKey(privatePem); + // const expectedKeyDetails = { + // modulusLength: 2048, + // publicExponent: 65537n, + // hashAlgorithm: 'sha512', + // mgf1HashAlgorithm: 'sha256', + // saltLength: 20 + // }; + // assert.strictEqual(publicKey.type, 'public'); + // assert.strictEqual(publicKey.asymmetricKeyType, 'rsa-pss'); + // assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); + // assert.strictEqual(privateKey.type, 'private'); + // assert.strictEqual(privateKey.asymmetricKeyType, 'rsa-pss'); + // assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); + // // Node.js usually uses the same hash function for the message and for MGF1. + // // However, when a different MGF1 message digest algorithm has been + // // specified as part of the key, it should automatically switch to that. + // // This behavior is required by sections 3.1 and 3.3 of RFC4055. + // for (const key of [privatePem, privateKey]) { + // // sha256 matches the MGF1 hash function and should be used internally, + // // but it should not be permitted as the main message digest algorithm. + // for (const algo of ['sha1', 'sha256']) { + // assert.throws(() => { + // createSign(algo).sign(key); + // }, /digest not allowed/); + // } + // // sha512 should produce a valid signature. + // const signature = createSign('sha512') + // .update('foo') + // .sign(key); + // for (const pkey of [key, publicKey, publicPem]) { + // const okay = createVerify('sha512') + // .update('foo') + // .verify(pkey, signature); + // assert.ok(okay); + // } + // } + // } + // } + } +}); diff --git a/test/js/node/crypto/fixtures/ec_p256_private.pem b/test/js/node/crypto/fixtures/ec_p256_private.pem new file mode 100644 index 000000000..6bb0bb9cf --- /dev/null +++ b/test/js/node/crypto/fixtures/ec_p256_private.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgDxBsPQPIgMuMyQbx +zbb9toew6Ev6e9O6ZhpxLNgmAEqhRANCAARfSYxhH+6V5lIg+M3O0iQBLf+53kuE +2luIgWnp81/Ya1Gybj8tl4tJVu1GEwcTyt8hoA7vRACmCHnI5B1+bNpS +-----END PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/ec_p256_public.pem b/test/js/node/crypto/fixtures/ec_p256_public.pem new file mode 100644 index 000000000..08f7bd26d --- /dev/null +++ b/test/js/node/crypto/fixtures/ec_p256_public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEX0mMYR/uleZSIPjNztIkAS3/ud5L +hNpbiIFp6fNf2GtRsm4/LZeLSVbtRhMHE8rfIaAO70QApgh5yOQdfmzaUg== +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/ec_p384_private.pem b/test/js/node/crypto/fixtures/ec_p384_private.pem new file mode 100644 index 000000000..06393e263 --- /dev/null +++ b/test/js/node/crypto/fixtures/ec_p384_private.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDB3B+4e4C1OUxGftkEI +Gb/SCulzUP/iE940CB6+B6WWO4LT76T8sMWiwOAGUsuZmyKhZANiAASE43efMYmC +/7Tx90elDGBEkVnOUr4ZkMZrl/cqe8zfVy++MmayPhR46Ah3LesMCNV+J0eG15w0 +IYJ8uqasuMN6drU1LNbNYfW7+hR0woajldJpvHMPv7wlnGOlzyxH1yU= +-----END PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/ec_p384_public.pem b/test/js/node/crypto/fixtures/ec_p384_public.pem new file mode 100644 index 000000000..2b50f3bbc --- /dev/null +++ b/test/js/node/crypto/fixtures/ec_p384_public.pem @@ -0,0 +1,5 @@ +-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEhON3nzGJgv+08fdHpQxgRJFZzlK+GZDG +a5f3KnvM31cvvjJmsj4UeOgIdy3rDAjVfidHhtecNCGCfLqmrLjDena1NSzWzWH1 +u/oUdMKGo5XSabxzD7+8JZxjpc8sR9cl +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/ec_p521_private.pem b/test/js/node/crypto/fixtures/ec_p521_private.pem new file mode 100644 index 000000000..e4a8a655c --- /dev/null +++ b/test/js/node/crypto/fixtures/ec_p521_private.pem @@ -0,0 +1,8 @@ +-----BEGIN PRIVATE KEY----- +MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAEghuafcab9jXW4gO +QLeDaKOlHEiskQFjiL8klijk6i6DNOXcFfaJ9GW48kxpodw16ttAf9Z1WQstfzpK +GUetHImhgYkDgYYABAGixYI8Gbc5zNze6rH2/OmsFV3unOnY1GDqG9RTfpJZXpL9 +ChF1dG8HA4zxkM+X+jMSwm4THh0Wr1Euj9dK7E7QZwHd35XsQXgH13Hjc0QR9dvJ +BWzlg+luNTY8CkaqiBdur5oFv/AjpXRimYxZDkhAEsTwXLwNohSUVMkN8IQtNI9D +aQ== +-----END PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/ec_p521_public.pem b/test/js/node/crypto/fixtures/ec_p521_public.pem new file mode 100644 index 000000000..c0ed00f64 --- /dev/null +++ b/test/js/node/crypto/fixtures/ec_p521_public.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBosWCPBm3Oczc3uqx9vzprBVd7pzp +2NRg6hvUU36SWV6S/QoRdXRvBwOM8ZDPl/ozEsJuEx4dFq9RLo/XSuxO0GcB3d+V +7EF4B9dx43NEEfXbyQVs5YPpbjU2PApGqogXbq+aBb/wI6V0YpmMWQ5IQBLE8Fy8 +DaIUlFTJDfCELTSPQ2k= +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/ec_secp256k1_private.pem b/test/js/node/crypto/fixtures/ec_secp256k1_private.pem new file mode 100644 index 000000000..f753c751b --- /dev/null +++ b/test/js/node/crypto/fixtures/ec_secp256k1_private.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgc34ocwTwpFa9NZZh3l88 +qXyrkoYSxvC0FEsU5v1v4IOhRANCAARw7OEVKlbGFqUJtY10/Yf/JSR0LzUL1PZ1 +4Ol/ErujAPgNwwGU5PSD6aTfn9NycnYB2hby9XwB2qF3+El+DV8q +-----END PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/ec_secp256k1_public.pem b/test/js/node/crypto/fixtures/ec_secp256k1_public.pem new file mode 100644 index 000000000..e95322efb --- /dev/null +++ b/test/js/node/crypto/fixtures/ec_secp256k1_public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEcOzhFSpWxhalCbWNdP2H/yUkdC81C9T2 +deDpfxK7owD4DcMBlOT0g+mk35/TcnJ2AdoW8vV8Adqhd/hJfg1fKg== +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/ed25519_private.pem b/test/js/node/crypto/fixtures/ed25519_private.pem new file mode 100644 index 000000000..f837457cb --- /dev/null +++ b/test/js/node/crypto/fixtures/ed25519_private.pem @@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEIMFSujN0jIUIdzSvuxka0lfgVVkMdRTuaVvIYUHrvzXQ +-----END PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/ed25519_public.pem b/test/js/node/crypto/fixtures/ed25519_public.pem new file mode 100644 index 000000000..4127a471b --- /dev/null +++ b/test/js/node/crypto/fixtures/ed25519_public.pem @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEAK1wIouqnuiA04b3WrMa+xKIKIpfHetNZRv3h9fBf768= +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/ed448_private.pem b/test/js/node/crypto/fixtures/ed448_private.pem new file mode 100644 index 000000000..9643665d6 --- /dev/null +++ b/test/js/node/crypto/fixtures/ed448_private.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEcCAQAwBQYDK2VxBDsEOdOtCnu9bDdBqSHNNZ5xoDA5KdLBTUNPcKFaOADNX32s +dfpo52pCtPqfku/l3/OfUHsF43EfZsaaWA== +-----END PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/ed448_public.pem b/test/js/node/crypto/fixtures/ed448_public.pem new file mode 100644 index 000000000..b767109b1 --- /dev/null +++ b/test/js/node/crypto/fixtures/ed448_public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAoX/ee5+jlcU53+BbGRsGIzly0V+SZtJ/oGXY0udf84q2hTW2 +RdstLktvwpkVJOoNb7oDgc2V5ZUA +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/rsa_private.pem b/test/js/node/crypto/fixtures/rsa_private.pem new file mode 100644 index 000000000..215e5cc51 --- /dev/null +++ b/test/js/node/crypto/fixtures/rsa_private.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAt9xYiIonscC3vz/A2ceR7KhZZlDu/5bye53nCVTcKnWd2seY +6UAdKersX6njr83Dd5OVe1BW/wJvp5EjWTAGYbFswlNmeD44edEGM939B6Lq+/8i +BkrTi8mGN4YCytivE24YI0D4XZMPfkLSpab2y/Hy4DjQKBq1ThZ0UBnK+9IhX37J +u/ZoGYSlTIGIhzyaiYBh7wrZBoPczIEu6et/kN2VnnbRUtkYTF97ggcv5h+hDpUQ +jQW0ZgOMcTc8n+RkGpIt0/iM/bTjI3Tz/gsFdi6hHcpZgbopPL630296iByyigQC +PJVzdusFrQN5DeC+zT/nGypQkZanLb4ZspSx9QIDAQABAoIBAQCS2erYu8gyoGPi +3E/zYgQ6ishFAZWzDWSFubwD5wSm4SSAzvViL/RbO6kqS25xR569DmLRiHzD17VI +mJMsNECUnPrqR2TL256OJZaXrNHh3I1lUwVhEzjeKMsL4/ys+d70XPXoiocVblVs +moDXEIGEqa48ywPvVE3Fngeuxrsq3/GCVBNiwtt0YjAOZxmKEh31UZdHO+YI+wNF +/Z8KQCPscN5HGlR0SIQOlqMANz49aKStrevdvjS1UcpabzDEkuK84g3saJhcpAhb +pGFmAf5GTjkkhE0rE1qDF15dSqrKGfCFtOjUeK17SIEN7E322ChmTReZ1hYGfoSV +cdFntUINAoGBAPFKL5QeJ6wZu8R/ru11wTG6sQA0Jub2hGccPXpbnPrT+3CACOLI +JTCLy/xTKW3dqRHj/wZEe+jUw88w7jwGb1BkWr4BI8tDvY9jQLP1jyuLWRfrxXbp +4Z0oeBBwBeCI/ZG7FIvdDTqWxn1aj3Tmh6s4ByqEdtwrrrJPcBUNl01fAoGBAMMR +3RGE/ca6X6xz6kgUD6TtHVhiiRJK1jm/u+q0n7i/MBkeDgTZkHYS7lPc0yIdtqaI +Plz5yzwHnAvuMrv8LSdkjwioig2yQa3tAij8kXxqs7wN5418DMV2s1OJBrPthYPs +bv4im2iI8V63JQS4ZMYQbckq8ABYccTpOnxXDy0rAoGBAKkvzHa+QjERhjB9GyoT +1FhLQIsVBmYSWrp1+cGO9V6HPxoeHJzvm+wTSf/uS/FmaINL6+j4Ii4a6gWgmJts +I6cqBtqNsAx5vjQJczf8KdxthBYa0sXTrsfktXNJKUXMqIgDtp9vazQ2vozs8AQX +FPAAhD3SzgkJdCBBRSTt97ZfAoGAWAziKpxLKL7LnL4dzDcx8JIPIuwnTxh0plCD +dCffyLaT8WJ9lXbXHFTjOvt8WfPrlDP/Ylxmfkw5BbGZOP1VLGjZn2DkH9aMiwNm +bDXFPdG0G3hzQovx/9fajiRV4DWghLHeT9wzJfZabRRiI0VQR472300AVEeX4vgb +rDBn600CgYEAk7czBCT9rHn/PNwCa17hlTy88C4vXkwbz83Oa+aX5L4e5gw5lhcR +2ZuZHLb2r6oMt9rlD7EIDItSs+u21LOXWPTAlazdnpYUyw/CzogM/PN+qNwMRXn5 +uXFFhmlP2mVg2EdELTahXch8kWqHaCSX53yvqCtRKu/j76V31TfQZGM= +-----END RSA PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/rsa_private_2048.pem b/test/js/node/crypto/fixtures/rsa_private_2048.pem new file mode 100644 index 000000000..0e5bde2e0 --- /dev/null +++ b/test/js/node/crypto/fixtures/rsa_private_2048.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEArk4OqxBqU5/k0FoUDU7CpZpjz6YJEXUpyqeJmFRVZPMUv/Rc +7U4seLY+Qp6k26T/wlQ2WJWuyY+VJcbQNWLvjJWks5HWknwDuVs6sjuTM8CfHWn1 +960JkK5Ec2TjRhCQ1KJy+uc3GJLtWb4rWVgTbbaaC5fiR1/GeuJ8JH1Q50lB3mDs +NGIk1U5jhNaYY82hYvlbErf6Ft5njHK0BOM5OTvQ6BBv7c363WNG7tYlNw1J40du +p9OQPo5JmXN/h+sRbdgG8iUxrkRibuGv7loh52QQgq2snznuRMdKidRfUZjCDGgw +bgK23Q7n8VZ9Y10j8PIvPTLJ83PX4lOEA37JlwIDAQABAoIBACoL2Ev5lLyBaI+9 ++vJO2nNaL9OKSMu2SJODIJTnWwYUASBg0P3Jir6/r3sgi8IUJkH5UHbD/LrQcPkA +4X7PU9vEyUsr1efWFIvk7t7JsjOctoVA5z2Mty74arivUIe5PUadvUC6/7Zk0u6A +CjLuJRmlH7nGNKZk+xrvgWTH+fkgc5ddbFxoGH129RcVC+ePbsi1EF60C9KbJvp1 +xjUJ5cDtNYnZ/g+ULo6ZJjRG5kUCVSI8H/Nc/DmStKsjN0isKpNGofU5ArEwywGC +Cqxz/tr4hT2haAkVEto04ooYpqDUSqGEfPpLWL+CjFNPfCsWJ1tX5LQRvpu6eukd +FO72oVECgYEA4+Ot7RQtGOtPeaxl3P7sbEzBZk0W/ZhCk+mzE2iYh0QXU44VtjtO +/9CENajTklckiwlxjqBZ5NO1SiMQKBcmqkoA03x/DEujo2rMVuNPoc6ZYp1Gc4qA +4ImkMQNsM7Swum42rKE960WoiWW7dsdEAq6vqgeApZlMU8lcKRAlOZkCgYEAw85H +3bjF7gMatVibsWzj0zp2L4616m2v5Z3YkgohGRAvm1912DI5ku5Nmy9am57Z1EP2 +UtDOxahd/Vf6mK9lR4YEbNW1TenykViQJ6lmljOFUeZEZYYO3O+fthkyN/42l5yn +MyUANTTb2rvt8amdRr0ARdRqWJmt5NfJzYBV+q8CgYB1ZjuZoQVCiybcRcYMPX/K +oxgW/avUZPYXgRNx8jZxqNBjiRUCVjdybhdOFXU5NI9s2SaZFV56Fd6VHM8b+CFB +JPKcAMzqpqTccQ5nzJ6fevFl7iP3LekKw53EakD5uiI5SMH92OsvIymZ7sDOhgUx +ZJC2hTrvFLRPjbJerSSgMQKBgAv5iZuduT0dI30DtkHbjvNUF/ZAnA+CNcetJ5mG +1Q9bVg4CgIqAR9UcjdJ3yurJhDjfDylxa7Pa4CSmRMUhtOfy4kJlr3jcXeFVsTs7 +uPJmpDimBHjRAgew/+t7Dv8tpNkQ04jlMmYOnYN7CspEvUGePW4H15kjjOb563WN +67QxAoGAdhJPaHVtDBUrobn50ORVkVNJVZPBhEDbR6tNtHsgEevH7iYjxAdxEeUa +c9S2iV9lir3hkrQceiYWAADcphWfO1HyP5Uld4sJzYiEGbSM7a0zRQjYlQgXFbZo +SAc6Gok78kwECPwpmeH4lpGVeKNmzEteSBVYxGb9b6C/SSsu7l0= +-----END RSA PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/rsa_private_4096.pem b/test/js/node/crypto/fixtures/rsa_private_4096.pem new file mode 100644 index 000000000..4177b9ef9 --- /dev/null +++ b/test/js/node/crypto/fixtures/rsa_private_4096.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAxeStwofbjtZuol4lwKn1w08AzcSNLHfCqNFHa+W7er8is7LQ +sPljtPT4yn4lsao83ngHFvSC3tbMiRNDpUHYqH2wBuUkuOmCtYkZLi0307H0CwcV +V6W5P3tNEt80IJ+PqlRxtTknezUtbOasbIi/aornVWG+psgqDGrFZ4oTsWtiE0Sv +i7sDqN5E2dijmH/YYnlnwqszgzHdtAnARp1bG34E64sqWCmLoGCfPdHtym/CSdxO +LOsDV15jrwODZQ/TJZ5thkwKZRxu7g9fwlhA1PiI5WDP4reXNaqa2bSgrzpAljQE +xYs4N0L7okSVOJQX9BEaoWtq8NLU8MpMdGoHNDU0Xr60Lfr58Z5qn8RGEvlTxoCb +PJzPV2zgzD/lmEqft6NnfTclveA3sd8xSrOBUn4o3S8hS0b9Su7PBukHjM96/e0R +eoIshSwXlQTLr2Ft8KwupyPm1ltNcTDtjqHcIWU6Bg+kPy9mxSVtGGZYAPtqGzNB +A/m+oOja/OSPxAblPdln691DaDuZs5nuZCGwGcLaJWgiyoqvXAcyXDZFyH4OZZh8 +rsBLKbnFXHZ/ziG0cAozEygZEPJappw8Lx/ady7WL/SJjxooiKapc7Bnfy8eSLV3 ++XAKxhLW/MQ6ChJ+e/8ExAY02ca4MpCvqwIk9TfV6FM8pWGqHzQFj0v3NL0CAwEA +AQKCAgBTb8eTbZS09NRQwUFJql9kqbq9B1I+nYAFjbd/Vq1lY5FOEubKt1vCwEbl +mapq7kwbwJ+8nftP2WEDqouq8chXwialwZdqH4ps4BEt1wLizvUGcUYeXlFs4p/s +hQ+FccExH8mRjzeGSzWL5PZuDHoogchnx36K83pHIf15Wk5TT+NaHGunjoJMgOqm +ryDK+5xQaL/G5Egj2LKRZksbet0fClMovNRtt5aXWCXL+uc3o0dXvPt5FN2jyLhe +4ixUQAfWpKWpKgZ3+zUKSpElb/Bl2yRdEiSUgrPOfNAtWmsldnok2mnooHpjUmqm +UCRaZpZy4YNI6/F6+Gmv3Ju/ubSvHzoxQLlvgUqWAnVshivF1TJImHSIiLIvBKPp +29SD6maWIT1DC9sKC4E1gq7VO4762l1//zEOAY7XK0Z7LrbZO4WXHnsgFOpGthQ3 +g9Qi/SeM6mb5xEJTBUBTmkhGs1x8jolzca30mqv8T63W4PXkXHmZdK7vyH5useiI +s0eGUeaYK892WgfxCBo24JCNQiAcH/wTwV4l4yROqeH2V4ShbIYmCzla++7vsPYW +hAwQR9eH0+4ogTkaMQrm16plZk0ezVX9BKK8KTnd4G9/T18VstQbiowF2/cKnGKC +OqrmoR2vHOksQdUJVmnwCRqU1symBxhY0GSIps98v+lUYExKQQKCAQEA/uVYE2/H +eNcV/uWAI9LspANXHJE33TFMZ8SuyOYtp3MYJizmQ1uT7Om2LEanDnNiz+fAQhrE +vo1sDIF9xOAde2qjIH+iDzcLvFPgC3gkQspFjU31M9OO5xAjzBxfL3KDiG2MtmTR +hNuKJX56eCOqkEp6WKaWOA35ccaKYHxNzMS49weCv95ZPpR9q0J1sgzD7HtVh4yu +XI01/BC8F0RmYjtsuUo+PmB6sO2K94uqqo0GPUos7Mhgrbff3L36EkOPgmRiA1AV +Zy1sKKxUKspGQ3m1fg+CA/+GZGckvYkVot1lFrwmrS2dok8EhT1HcVJde+++jx7z +JsRLgFRvKHXklwKCAQEAxsAfxIQjjjKmuyJCzIvxG7lnuzovdy4OEdSuJL4yK5m3 +4BHJHn+yHeRIcrDnJKUTUYffcH/OjOnJS94BA6wH1tEuvGQz6LV6UpwApZ1M/2md +nP0eC2L2JtSRL8mdxfyqXDloWMpD7rncBZ6ChLEZ6sWYa6WBQTARmPVePyUpNNG2 +qymxN3/vRBGGBunD3j6zX0M0szWK5iU+qsYDy3KzCKG8FU7XxwzRbP7iARRD5Hpt +Zmy2W52EJg1uhmlVXJMm32SEBfrD2oDmlnjAqaZdqi5Mq2e4uB3dhM9RwJppSALG +BY6k9DeanAFbOlawMJri2pk7B0phCn+DN2pg0+W3ywKCAQBeTwzfZCQxmaMRxGg8 +2PWlWXcJotFAjdTvL95bho6tve/ZcBNiKKf6qB43E40L07VjpyODUdQpjLnFhsO5 +7BH8b+AbTh3v8zXsYDwtAi6oZ56EQavPmR7ubxJPms+9BmmUOLQvZ+39ch0S8lDt +0oRxDp1l330FEGaSqhrYyCUg9khZXfYKd4IdnWNB0j0pu39iJ9/lXy/EHpsywB5X +nX8kKUh45fdRrPC4NauNG6fxomwEkUU99oWOwNGbIs87orOeUvXQs/i3TB8QjXI2 +wtBsdsOn+KTqRci7rU3ysp3GvJOCbesBeDcyrnnFsn6Udx0Plgyzd4gPd+FXgeX+ +2l/RAoIBAH81FKAY2xD2RlTb1tlIcGeIQWZKFXs4VPUApP0LZt0VI+UcPRdyL7SG +GgCeTTLdHQI/7rj4dGEoeRg/3XJWNyY8+KbHk5nMHaCmDJvzlAaduK10LDipfFba +Epr9dif0Ua15aNn7i4NOHg7Sp0L6f1YOZkHvykzI0VqPIWVVCYyu9TWUF8Mn9SIh +/SCLmjuy8ed1AlP5Xw9yoyt2VZNvtDtAGTuiHOVfxOL4N/rs149y9HZr+kOlC6G3 +Uxhgbqwz2tt8YCvblmNRwURpwRZUTvrPa28Bke713oRUlUSrD9txOwDvjZBpzmEv +VQ5/0YEqgSvcizVdW8L2XiunwJWfIAUCggEBALr4RF9TYa37CImZOs+vJ8FGRKMz +h1EUwO2PvuITvkTtu/7E4IjyxAo5dkAokkWQCGABciiDJJEYUWqcUX45qQChOgtm +NU2od6f9tgyDFxN5KS8cE32NXV3rJXs3bBZmIKLSPETf3uIPuEpFPjpdR5v5jlV+ +TDjH4RrItE3hDCvypTXhXXMmWp3VfYbgEfIP03uR2iIhL+/g3BUqbrywPEsTViSN +NM/uBDQyamXLXB1bQ2I/Ob41I82PD1iNCqGi7ZvZ3eVYGgUTQyw6Q4O8glTPP9cC +SFVXwE9gHbLe8TqfTZCWrM6crGX6Bb6hV2tqNsA+7J69U9NGuw5GNqXjafU= +-----END RSA PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/rsa_private_encrypted.pem b/test/js/node/crypto/fixtures/rsa_private_encrypted.pem new file mode 100644 index 000000000..f1914289e --- /dev/null +++ b/test/js/node/crypto/fixtures/rsa_private_encrypted.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,DB3D20E60E8FDC3356BD79712FF8EF7E + +K+vu0U3IFTJBBi6zW5Zng80O1jXq/ZmlOFs/j/SQpPwfW1Do9i/Dwa7ntBlTwrCm +sd3IIPgu2ikfLwxvbxsZN540oCaCqaZ/bmmyzH3MyVDA9MllUu+X8+Q3ATzcYa9R +U5XfF5DAXsSRnstCbmKagWVQpO0oX8k3ratfny6Ixq86Y82tK8+o5YiBFq1kqa+9 +4yat7IWQbqV5ifUtUPCHZwEqBt+WKazX05BqERjkckHdpfaDrBvSSPXTwoLm6uRR +ktkUVpO4tHMZ4VlcTfFtpz8gdYYod0nM6vz26hvbESHSwztSgMhmKdsE5eqmYfgu +F4WkEN4bqAiPjKK3jnUKPt/vg2oKYFQlVYFl9QnBjiRqcQTi3e9lwn1hI7uoMb6g +HuaCc57JJHPN/ZLP3ts4ZxFbwUjTGioh5Zh6WozG3L3+Ujwq/sDrAskRyzdcuP7I +Rs3oLbHY03OHyg8IbxR5Iu89l6FLqnR45yvbxXtZ7ImGOPM5Z9pB1CzDhGDx2F6g +J/Kf/7ZF2DmYUVbVKDfESEDhRfuMAVzhasDPTRqipSA5QvJVQY+J/6QDPrNNmHVB +4e4ouHIDWERUf0t1Be7THvP3X8OJozj2HApzqa5ZCaJDo8eaL8TCD5uH75ID5URJ +VscGHaUXT8/sxfHi1x8BibW5W5J/akFsnrnJU/1BZgGznIxjf5tKfHGppSIVdlKP +3ghYNmEIFPNJ6cxuUA0D2IOV4uO3FTCU6seIzvJhYkmXnticcZYGtmGxXKrodtzS +J1YuaNkkO/YRZah285lQ6QCIhCFo4Oa4ILjgoTQISuw7nQj5ESyncauzLUBXKX0c +XDUej64KNTvVF9UXdG48fYvNmSZWCnTye4UmPu17FmwpVra38U+EdoLyWyMIAI5t +rP6Hhgc9BxOo41Im9QpTcAPfKAknP8Rbm3ACJG5T9FKq/c29d1E//eFR6SL51e/a +yWdCgJN/FJOAX60+erPwoVoRFEttAeDPkklgFGdc8F4LIYAig9gEZ92ykFFz3fWz +jIcUVLrL+IokFbPVUBoMihqVyMQsWH+5Qq9wjxf6EDIf0BVtm9U4BJoOkPStFIfF +Kof7OVv7izyL8R/GIil9VQs9ftwkIUPeXx2Hw0bE3HJ3C8K4+mbLg3tKhGnBDU5Z +Xm5mLHoCRBa3ZRFWZtigX7POszdLAzftYo8o65Be4OtPS+tQAORk9gHsXATv7dDB +OGw61x5KA55LHVHhWaRvu3J8E7nhxw0q/HskyZhDC+Y+Xs6vmQSb4nO4ET4NYX1P +m3PMdgGoqRDJ2jZw4eoQdRKCM0EHSepSAYpO1tcAXhPZS4ITogoRgPpVgOebEQUL +nKNeNu/BxMSH/IH15jjDLF3TiEoguF9xdTaCxIBzE1SFpVO0u9m9vXpWdPThVgsb +VcEI487p7v9iImP3BYPT8ZYvytC26EH0hyOrwhahTvTb4vXghkLIyvPUg1lZHc6e +aPHb2AzYAHLnp/ehDQGKWrCOJ1JE2vBv8ZkLa+XZo7YASXBRZitPOMlvykEyzxmR +QAmNhKGvFmeM2mmHAp0aC03rgF3lxNsXQ1CyfEdq3UV9ReSnttq8gtrJfCwxV+wY +-----END RSA PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/rsa_pss_private_2048.pem b/test/js/node/crypto/fixtures/rsa_pss_private_2048.pem new file mode 100644 index 000000000..ffca137a7 --- /dev/null +++ b/test/js/node/crypto/fixtures/rsa_pss_private_2048.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADALBgkqhkiG9w0BAQoEggSoMIIEpAIBAAKCAQEAy4OMdS84PlgI5CRL +bdbud9Ru7vprFr2YNNUmdT7D3YgApiv8CjzKXLiVDnbMET+lwmtag/EcZsxVCKov +su30pYASBriHOiMVYui9+ZaJoQ9yI6lOjG1RbuUBJXNSjHBJxqBqmcgZOb1mdRr/ +eXzpAMWJ3hfuLojU2+zUSJ3/rvepepcLFG2q9nA0+PJskJ7Pnh3L0ydnv3U3hduM +n5OVfm/Jx1FPyZpD184tJff+N+MY3s3hIcfuOnL9Pl4RPGeaTC4T1o460NaG6bG7 +c2Whg6NOaVgaFIaiNbrTTNCpVjeTyalsTXYlQQ3hiKjst0Q7pfFEkJDo8qiqLad1 +Msl59wIDAQABAoIBAQC6G8aqs0/f02nuGDLSc6cH9kCsUlz0ItW6GuJcfdVoFSNi +0v5d7lGwkSveWk0ryOSw8rOHzUqHx3xLvDZ6jpkXcBMMClu/kq3QEb8JK90YaKOc +cQvf52h83Pc7ZEatH1KYTcKudwp6fvXfSZ0vYEdD6WG2tHOgIollxSIsdjCHs1qi +7baNHdK9T4DveuEZNcZ+LraZ1haHmFeqIPcy+KvpGuTaLCg5FPhH2jsIkw9apr7i +iFLi+IJ7S5Bn/8XShmJWk4hPyx0jtIkC5r2iJnHf4x+XYWZfdo7oew3Dg6Pa7T6r +I164Nnaw0u0LvO4gQdvYaJ/j9A602nHTp7Tsq8chAoGBAOtVHgIqpmdzwR5KjotW +LuGXDdO9X6Xfge9ca2MlWH1jOj+zqEV7JtrjnZAzzOgP2kgqzpIR71Njs8wkaxTJ +Tle0Ke6R/ghU9YOQgRByKjqJfQXHZnYFPsMg0diNYLroJ4SG8LO4+2SygTYZ4eKL +qU0bda3QvQ7FL+rTNQBy01b9AoGBAN1jEQI80JxCT7AMvXE6nObIhbkASHte4yOE +1CBwcOuBEGcuvMOvQVMzKITgea6+kgsu4ids4dM5PTPapQgpKqIIQ2/eSesaf56g +73clGGSTPHJP0v+EfKg4+GYJf8o2swT0xDHkgWLgjjdsncB9hATc2j6DvHeau18d +pgCLz9kDAoGAXl/SGvhTp2UqayVnKMW1I07agrGNLA4II5+iiS4u4InskCNSNhr/ +KATj6TJ82AuTdCGGmdmLapuvPQzVzI42VsGvlzcA8wJvOwW2XIwMF1GPy8N9eZL8 +6m+89+Uqh4oWXvVmjgx+9JEJdFLI3Xs4t+1tMfll+AhoAPoWZUmnK1kCgYAvEBxR +iXQfg8lE97BeHcO1G/OxfGnsMCPBLT+bFcwrhGhkRv9B6kPM2BdJCB9WEpUhY3oY +P4FSUdy85UIoFfhGMdOEOJEmNZ/jrPq7LVueJd63vlhwkU2exV2o82QDLNWpvA7p +PFZ1Gp+hEKoIfaZPElQi7gZmtrIWaksb2pz42QKBgQCct9NP2qJfqeS4206RDnfv +M238/O2lNhLWdSwY0g+tcN+I1sGs3+4vvrm95cxwAmXZyIM11wjdMcAPNxibodY7 +vufsebPHDBA0j0yuTjGkXefUKd1GdO88i5fppzxB7prDX9//DsWWrFhIMMRNYe0Q +aeHd/NPuHcjZKcnaVBgukQ== +-----END PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/rsa_pss_public_2048.pem b/test/js/node/crypto/fixtures/rsa_pss_public_2048.pem new file mode 100644 index 000000000..ade38f20a --- /dev/null +++ b/test/js/node/crypto/fixtures/rsa_pss_public_2048.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIDALBgkqhkiG9w0BAQoDggEPADCCAQoCggEBAMuDjHUvOD5YCOQkS23W7nfU +bu76axa9mDTVJnU+w92IAKYr/Ao8yly4lQ52zBE/pcJrWoPxHGbMVQiqL7Lt9KWA +Ega4hzojFWLovfmWiaEPciOpToxtUW7lASVzUoxwScagapnIGTm9ZnUa/3l86QDF +id4X7i6I1Nvs1Eid/673qXqXCxRtqvZwNPjybJCez54dy9MnZ791N4XbjJ+TlX5v +ycdRT8maQ9fOLSX3/jfjGN7N4SHH7jpy/T5eETxnmkwuE9aOOtDWhumxu3NloYOj +TmlYGhSGojW600zQqVY3k8mpbE12JUEN4Yio7LdEO6XxRJCQ6PKoqi2ndTLJefcC +AwEAAQ== +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/rsa_public.pem b/test/js/node/crypto/fixtures/rsa_public.pem new file mode 100644 index 000000000..8c30cfa52 --- /dev/null +++ b/test/js/node/crypto/fixtures/rsa_public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt9xYiIonscC3vz/A2ceR +7KhZZlDu/5bye53nCVTcKnWd2seY6UAdKersX6njr83Dd5OVe1BW/wJvp5EjWTAG +YbFswlNmeD44edEGM939B6Lq+/8iBkrTi8mGN4YCytivE24YI0D4XZMPfkLSpab2 +y/Hy4DjQKBq1ThZ0UBnK+9IhX37Ju/ZoGYSlTIGIhzyaiYBh7wrZBoPczIEu6et/ +kN2VnnbRUtkYTF97ggcv5h+hDpUQjQW0ZgOMcTc8n+RkGpIt0/iM/bTjI3Tz/gsF +di6hHcpZgbopPL630296iByyigQCPJVzdusFrQN5DeC+zT/nGypQkZanLb4ZspSx +9QIDAQAB +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/rsa_public_2048.pem b/test/js/node/crypto/fixtures/rsa_public_2048.pem new file mode 100644 index 000000000..0c80ceb4d --- /dev/null +++ b/test/js/node/crypto/fixtures/rsa_public_2048.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArk4OqxBqU5/k0FoUDU7C +pZpjz6YJEXUpyqeJmFRVZPMUv/Rc7U4seLY+Qp6k26T/wlQ2WJWuyY+VJcbQNWLv +jJWks5HWknwDuVs6sjuTM8CfHWn1960JkK5Ec2TjRhCQ1KJy+uc3GJLtWb4rWVgT +bbaaC5fiR1/GeuJ8JH1Q50lB3mDsNGIk1U5jhNaYY82hYvlbErf6Ft5njHK0BOM5 +OTvQ6BBv7c363WNG7tYlNw1J40dup9OQPo5JmXN/h+sRbdgG8iUxrkRibuGv7loh +52QQgq2snznuRMdKidRfUZjCDGgwbgK23Q7n8VZ9Y10j8PIvPTLJ83PX4lOEA37J +lwIDAQAB +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/rsa_public_4096.pem b/test/js/node/crypto/fixtures/rsa_public_4096.pem new file mode 100644 index 000000000..4fd0bbc1c --- /dev/null +++ b/test/js/node/crypto/fixtures/rsa_public_4096.pem @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeStwofbjtZuol4lwKn1 +w08AzcSNLHfCqNFHa+W7er8is7LQsPljtPT4yn4lsao83ngHFvSC3tbMiRNDpUHY +qH2wBuUkuOmCtYkZLi0307H0CwcVV6W5P3tNEt80IJ+PqlRxtTknezUtbOasbIi/ +aornVWG+psgqDGrFZ4oTsWtiE0Svi7sDqN5E2dijmH/YYnlnwqszgzHdtAnARp1b +G34E64sqWCmLoGCfPdHtym/CSdxOLOsDV15jrwODZQ/TJZ5thkwKZRxu7g9fwlhA +1PiI5WDP4reXNaqa2bSgrzpAljQExYs4N0L7okSVOJQX9BEaoWtq8NLU8MpMdGoH +NDU0Xr60Lfr58Z5qn8RGEvlTxoCbPJzPV2zgzD/lmEqft6NnfTclveA3sd8xSrOB +Un4o3S8hS0b9Su7PBukHjM96/e0ReoIshSwXlQTLr2Ft8KwupyPm1ltNcTDtjqHc +IWU6Bg+kPy9mxSVtGGZYAPtqGzNBA/m+oOja/OSPxAblPdln691DaDuZs5nuZCGw +GcLaJWgiyoqvXAcyXDZFyH4OZZh8rsBLKbnFXHZ/ziG0cAozEygZEPJappw8Lx/a +dy7WL/SJjxooiKapc7Bnfy8eSLV3+XAKxhLW/MQ6ChJ+e/8ExAY02ca4MpCvqwIk +9TfV6FM8pWGqHzQFj0v3NL0CAwEAAQ== +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/x25519_private.pem b/test/js/node/crypto/fixtures/x25519_private.pem new file mode 100644 index 000000000..926c4e3a2 --- /dev/null +++ b/test/js/node/crypto/fixtures/x25519_private.pem @@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VuBCIEIJi/yFpueUawC1BkXyWM8ONIBGFjL7UZHrD/Zo/KPDpn +-----END PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/x25519_public.pem b/test/js/node/crypto/fixtures/x25519_public.pem new file mode 100644 index 000000000..e2d756bd1 --- /dev/null +++ b/test/js/node/crypto/fixtures/x25519_public.pem @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VuAyEAaSb8Q+RndwfNnPeOYGYPDUN3uhAPnMLzXyfi+mqfhig= +-----END PUBLIC KEY----- diff --git a/test/js/node/crypto/fixtures/x448_private.pem b/test/js/node/crypto/fixtures/x448_private.pem new file mode 100644 index 000000000..61cd52c39 --- /dev/null +++ b/test/js/node/crypto/fixtures/x448_private.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEYCAQAwBQYDK2VvBDoEOLTDbazv6vHZWOmODQ3kk8TUOQgApB4j75rpInT5zSLl +/xJHK8ixF7f+4uo+mGTCrK1sktI5UmCZ +-----END PRIVATE KEY----- diff --git a/test/js/node/crypto/fixtures/x448_public.pem b/test/js/node/crypto/fixtures/x448_public.pem new file mode 100644 index 000000000..6475d0438 --- /dev/null +++ b/test/js/node/crypto/fixtures/x448_public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEIwBQYDK2VvAzkAioHSHVpTs6hMvghosEJDIR7ceFiE3+Xccxati64oOVJ7NWjf +ozE7ae31PXIUFq6cVYgvSKsDFPA= +-----END PUBLIC KEY----- diff --git a/test/js/node/dns/node-dns.test.js b/test/js/node/dns/node-dns.test.js index d549017b2..1988e9155 100644 --- a/test/js/node/dns/node-dns.test.js +++ b/test/js/node/dns/node-dns.test.js @@ -394,3 +394,14 @@ describe("dns.lookupService", () => { expect(service).toStrictEqual(expected[1]); }); }); + +// Deprecated reference: https://nodejs.org/api/deprecations.html#DEP0118 +describe("lookup deprecated behavior", () => { + it.each([undefined, false, null, NaN, ""])("dns.lookup", domain => { + dns.lookup(domain, (error, address, family) => { + expect(error).toBeNull(); + expect(address).toBeNull(); + expect(family).toBe(4); + }); + }); +}); diff --git a/test/js/node/process/process.test.js b/test/js/node/process/process.test.js index 4fb678dce..fd91fdef5 100644 --- a/test/js/node/process/process.test.js +++ b/test/js/node/process/process.test.js @@ -263,6 +263,15 @@ describe("process.exitCode", () => { }); }); +it("process exitCode range (#6284)", () => { + const { exitCode, stdout } = spawnSync({ + cmd: [bunExe(), join(import.meta.dir, "process-exitCode-fixture.js"), "255"], + env: bunEnv, + }); + expect(exitCode).toBe(255); + expect(stdout.toString().trim()).toBe("PASS"); +}); + it("process.exit", () => { const { exitCode, stdout } = spawnSync({ cmd: [bunExe(), join(import.meta.dir, "process-exit-fixture.js")], |