From 54033346f945ec196699a8ec123f5906d85d9ca4 Mon Sep 17 00:00:00 2001 From: pehmo1 Date: Thu, 12 Aug 2021 22:27:58 +0300 Subject: [PATCH] Add pkcs12chain.js and util.js pkcs12chain returns a PFX with private key and cert chain. Comes from: https://github.com/PeculiarVentures/PKI.js/issues/104 util.js contains various conversion functions, the asn1js examples all use inline conversions so no pre-made functions available. formatPEM.js came from pkijs examples (examples_common.js). --- static/js/pkcs12chain.js | 120 +++++++++++++++++++++++++++++++++++++++ static/js/util.js | 51 +++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 static/js/pkcs12chain.js create mode 100644 static/js/util.js diff --git a/static/js/pkcs12chain.js b/static/js/pkcs12chain.js new file mode 100644 index 0000000..65d0741 --- /dev/null +++ b/static/js/pkcs12chain.js @@ -0,0 +1,120 @@ +import * as asn1js from "asn1js"; +import { + stringToArrayBuffer, + fromBase64, +} from "pvutils"; +import { + getRandomValues +} from "../node_modules/pkijs/src/common.js"; +import Certificate from "../node_modules/pkijs/src/Certificate.js"; +import PrivateKeyInfo from "../node_modules/pkijs/src/PrivateKeyInfo"; +import Attribute from "../node_modules/pkijs/src/Attribute"; +import SafeBag from "../node_modules/pkijs/src/SafeBag"; +import PKCS8ShroudedKeyBag from "../node_modules/pkijs/src/PKCS8ShroudedKeyBag"; +import PFX from "../node_modules/pkijs/src/PFX"; +import AuthenticatedSafe from "../node_modules/pkijs/src/AuthenticatedSafe"; +import SafeContents from "../node_modules/pkijs/src/SafeContents"; +import CertBag from "../node_modules/pkijs/src/CertBag"; + +export async function pkcs12chain(priv, certs, password, hash_alg) { + const asn1 = asn1js.fromBER(stringToArrayBuffer(fromBase64(priv))); + const pkcs8Simpl = new PrivateKeyInfo({schema: asn1.result}); + + const keyLocalIDBuffer = new ArrayBuffer(4); + const keyLocalIDView = new Uint8Array(keyLocalIDBuffer); + getRandomValues(keyLocalIDView); + + const bitArray = new ArrayBuffer(1); + const bitView = new Uint8Array(bitArray); + + bitView[0] = bitView[0] | 0x80; + + const keyUsage = new asn1js.BitString({ + valueHex: bitArray, + unusedBits: 7 + }); + + pkcs8Simpl.attributes = [ + new Attribute({ + type: "2.5.29.15", + values: [ + keyUsage + ] + }) + ]; + + const safeBags = [ + new SafeBag({ + bagId: "1.2.840.113549.1.12.10.1.2", + bagValue: new PKCS8ShroudedKeyBag({ + parsedValue: pkcs8Simpl + }), + bagAttributes: [ + new Attribute({ + type: "1.2.840.113549.1.9.21", // localKeyID + values: [ + new asn1js.OctetString({valueHex: keyLocalIDBuffer}) + ] + }) + ] + }) + ]; + + const numCerts = certs.length; + for (let i=0;i { + let arrayBuf = new ArrayBuffer(0); + arrayBuf = await crypto.exportKey("pkcs8", privKey); + + resolve(formatPEM(toBase64(arrayBufferToString(arrayBuf)))); + }); +} + +export async function privKeyToPem(privKey, crypto) { + return new Promise(async (resolve, reject) => { + let privKeyExported = await crypto.exportKey("pkcs8", privKey); + let privKeyBody = formatPEM( + toBase64( + String.fromCharCode.apply(null, new Uint8Array(privKeyExported)) + ) + ); + let privKeyPem = `-----BEGIN RSA PRIVATE KEY-----\r\n${privKeyBody}\r\n-----END RSA PRIVATE KEY-----\r\n`; + + resolve(privKeyPem); + }); +} + +export async function certReqToPem(csr) { + return new Promise(async (resolve, reject) => { + let resPem = "-----BEGIN CERTIFICATE REQUEST-----\r\n"; + resPem = `${resPem}${formatPEM( + toBase64(arrayBufferToString(csr.toSchema().toBER(false))) + )}`; + resPem = `${resPem}\r\n-----END CERTIFICATE REQUEST-----\r\n`; + + resolve(resPem); + }); +} \ No newline at end of file