From 3c03e64e6f198a63d9a795c96c9472622100741d Mon Sep 17 00:00:00 2001 From: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> Date: Fri, 29 May 2026 20:33:33 +0000 Subject: [PATCH] Replace non-browser-friendly createPrivateKey call with custom function to convert pkcs1 to pkcs8 --- src/core/lib/RSA.mjs | 49 +++++++++++++++++++++++++++++++++ src/core/operations/JWTSign.mjs | 5 ++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/core/lib/RSA.mjs b/src/core/lib/RSA.mjs index 9037379c..1909172a 100644 --- a/src/core/lib/RSA.mjs +++ b/src/core/lib/RSA.mjs @@ -7,6 +7,7 @@ */ import forge from "node-forge"; +import * as asn1js from "asn1js"; export const MD_ALGORITHMS = { "SHA-1": forge.md.sha1, @@ -15,3 +16,51 @@ export const MD_ALGORITHMS = { "SHA-384": forge.md.sha384, "SHA-512": forge.md.sha512, }; + +const rsaEncryptionOID = "1.2.840.113549.1.1.1"; + +/** + * Convert PKCS#1 RSA private key (PEM) to PKCS#8 PEM + * @param {string} originalPem + * @returns {string} + */ +export function pkcs1ToPkcs8(originalPem) { + // remove PEM headers + const b64 = originalPem + .replace(/-----BEGIN RSA PRIVATE KEY-----/g, "") + .replace(/-----END RSA PRIVATE KEY-----/g, "") + .replace(/\s+/g, ""); + + const pkcs1Der = Uint8Array.from(atob(b64), c => c.charCodeAt(0)).buffer; + + // PKCS#8 structure: + // PrivateKeyInfo ::= SEQUENCE { + // version INTEGER, + // privateKeyAlgorithm AlgorithmIdentifier, + // privateKey OCTET STRING + // } + + const pkcs8Schema = new asn1js.Sequence({ + value: [ + new asn1js.Integer({ value: 0 }), + new asn1js.Sequence({ + value: [ + // rsaEncryption OID + new asn1js.ObjectIdentifier({ value: rsaEncryptionOID }), + new asn1js.Null() + ] + }), + new asn1js.OctetString({ valueHex: pkcs1Der }) + ] + }); + + const pkcs8Der = pkcs8Schema.toBER(false); + + const pkcs8B64 = btoa( + String.fromCharCode(...new Uint8Array(pkcs8Der)) + ); + + const lines = pkcs8B64.match(/.{1,64}/g).join("\n"); + + return `-----BEGIN PRIVATE KEY-----\n${lines}\n-----END PRIVATE KEY-----`; +} diff --git a/src/core/operations/JWTSign.mjs b/src/core/operations/JWTSign.mjs index bd0ac662..f2c81a40 100644 --- a/src/core/operations/JWTSign.mjs +++ b/src/core/operations/JWTSign.mjs @@ -5,10 +5,9 @@ */ import Operation from "../Operation.mjs"; import { SignJWT, importPKCS8 } from "jose"; -import { createPrivateKey } from "crypto"; import OperationError from "../errors/OperationError.mjs"; import {JWT_ALGORITHMS} from "../lib/JWT.mjs"; - +import {pkcs1ToPkcs8} from "../lib/RSA.mjs"; /** * JWT Sign operation @@ -57,7 +56,7 @@ class JWTSign extends Operation { let secret; try { if (key.startsWith("-----BEGIN RSA PRIVATE KEY-----")) { - secret = await createPrivateKey(key); + secret = await importPKCS8(pkcs1ToPkcs8(key), algorithm); } else if (key.startsWith("-----BEGIN PRIVATE KEY-----")) { secret = await importPKCS8(key, algorithm); } else {