From 29b5c986cd63ffc1f4818e083b768cab7ce3200c Mon Sep 17 00:00:00 2001 From: Jackson Roberts Date: Wed, 25 Feb 2026 21:55:09 -0600 Subject: [PATCH] convert PKCS#1 keys to PKCS#8 at load time --- src/constants.ts | 42 ++++++++++++------- .../credentials/generateSecureValue.ts | 8 +--- src/modules/credentials/readSecureValue.ts | 6 +-- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 9c91465..14c67a9 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,5 @@ import { readFileSync } from "fs"; +import crypto from "crypto"; import { PrismaPg } from "@prisma/adapter-pg"; import { Prisma, PrismaClient } from "../generated/prisma/client"; import * as msal from "@azure/msal-node"; @@ -28,21 +29,32 @@ const isProduction = process.env.NODE_ENV === "production"; const readKeyFile = (path: string) => readFileSync(path).toString(); -export const accessTokenPrivateKey = isProduction - ? process.env.ACCESS_TOKEN_PRIVATE_KEY! - : readKeyFile(`.accessToken.key`); -export const refreshTokenPrivateKey = isProduction - ? process.env.REFRESH_TOKEN_PRIVATE_KEY! - : readKeyFile(`.refreshToken.key`); -export const permissionsPrivateKey = isProduction - ? process.env.PERMISSIONS_PRIVATE_KEY! - : readKeyFile(`.permissions.key`); -export const secureValuesPrivateKey = isProduction - ? process.env.SECURE_VALUES_PRIVATE_KEY! - : readKeyFile(`.secureValues.key`); -export const secureValuesPublicKey = isProduction - ? process.env.SECURE_VALUES_PUBLIC_KEY! - : readKeyFile(`public-keys/.secureValues.pub`); +/** + * Convert a PKCS#1 PEM key to PKCS#8 PEM format. + * The compiled Bun binary on Ubuntu uses an OpenSSL that doesn't auto-detect PKCS#1 format, + * so we normalize all keys to PKCS#8 at load time. + */ +const toPkcs8Private = (pem: string) => + crypto.createPrivateKey({ key: pem, format: "pem", type: "pkcs1" }).export({ type: "pkcs8", format: "pem" }) as string; + +const toPkcs8Public = (pem: string) => + crypto.createPublicKey({ key: pem, format: "pem", type: "pkcs1" }).export({ type: "spki", format: "pem" }) as string; + +export const accessTokenPrivateKey = toPkcs8Private( + isProduction ? process.env.ACCESS_TOKEN_PRIVATE_KEY! : readKeyFile(`.accessToken.key`), +); +export const refreshTokenPrivateKey = toPkcs8Private( + isProduction ? process.env.REFRESH_TOKEN_PRIVATE_KEY! : readKeyFile(`.refreshToken.key`), +); +export const permissionsPrivateKey = toPkcs8Private( + isProduction ? process.env.PERMISSIONS_PRIVATE_KEY! : readKeyFile(`.permissions.key`), +); +export const secureValuesPrivateKey = toPkcs8Private( + isProduction ? process.env.SECURE_VALUES_PRIVATE_KEY! : readKeyFile(`.secureValues.key`), +); +export const secureValuesPublicKey = toPkcs8Public( + isProduction ? process.env.SECURE_VALUES_PUBLIC_KEY! : readKeyFile(`public-keys/.secureValues.pub`), +); // Microsoft Auth Constants const msalConfig: msal.Configuration = { diff --git a/src/modules/credentials/generateSecureValue.ts b/src/modules/credentials/generateSecureValue.ts index 9565ba9..b29b2c6 100644 --- a/src/modules/credentials/generateSecureValue.ts +++ b/src/modules/credentials/generateSecureValue.ts @@ -6,12 +6,8 @@ export const generateSecureValue = (content: string) => { // Generate a hash of the content const hash = Password.hash(content); - // Parse the PKCS#1 PEM key into a proper KeyObject - const publicKey = crypto.createPublicKey({ - key: secureValuesPublicKey, - format: "pem", - type: "pkcs1", - }); + // Parse the PEM key into a proper KeyObject + const publicKey = crypto.createPublicKey(secureValuesPublicKey); // Encrypt the content using the .secureValues.pub public key const encrypted = crypto.publicEncrypt( diff --git a/src/modules/credentials/readSecureValue.ts b/src/modules/credentials/readSecureValue.ts index 1010831..dda7548 100644 --- a/src/modules/credentials/readSecureValue.ts +++ b/src/modules/credentials/readSecureValue.ts @@ -3,11 +3,7 @@ import crypto from "crypto"; import { secureValuesPrivateKey } from "../../constants"; import GenericError from "../../Errors/GenericError"; -const privateKey = crypto.createPrivateKey({ - key: secureValuesPrivateKey, - format: "pem", - type: "pkcs1", -}); +const privateKey = crypto.createPrivateKey(secureValuesPrivateKey); export const readSecureValue = ( encryptedContent: string,