import { util , asn1 , pkcs12 , pki } from 'node-forge' ; import { readFileSync } from 'fs' ; export interface Pkcs12ReadResult { ca ? : string [ ] ; cert ? : string ; key ? : string ; } remarks privateRemarks param path param password returns export const readPkcs12Keystore = ( path , password ? ) : Pkcs12ReadResult => { const p12base64 = readFileSync ( path , 'base64' ) ; const p12Der = util . decode64 ( p12base64 ) ; const p12Asn1 = asn1 . fromDer ( p12Der ) ; const p12 = pkcs12 . pkcs12FromAsn1 ( p12Asn1 , password ) ; const keyObj = getKey ( p12 ) ; const { ca , cert } = getCerts ( p12 , keyObj ?. publicKeyData ) ; return { ca , cert , key : keyObj ?. key } ; } ; remarks param path param password returns export const readPkcs12Truststore = ( path , password ? ) : string [ ] | undefined => { const p12base64 = readFileSync ( path , 'base64' ) ; const p12Der = util . decode64 ( p12base64 ) ; const p12Asn1 = asn1 . fromDer ( p12Der ) ; const p12 = pkcs12 . pkcs12FromAsn1 ( p12Asn1 , password ) ; const keyObj = getKey ( p12 ) ; const { ca } = getCerts ( p12 , keyObj ?. publicKeyData ) ; return ca ; } ; interface BigInteger { data : number [ ] ; t : number ; s : number ; toString ( ) : string ; compareTo ( bn ) : number ; } interface PublicKeyData { n : BigInteger ; e : BigInteger ; } const doesPubKeyMatch = ( a ? , b ? ) => { if ( a && b ) { return a . n . compareTo ( b . n ) === 0 && a . e . compareTo ( b . e ) === 0 ; } return false ; } ; const getCerts = ( p12 , pubKey ? ) => { const bags = getBags ( p12 , pki . oids . certBag ) ; let ca ; let cert ; if ( bags && bags . length ) { const certs = bags . map ( convertCert ) . filter ( ( x ) => x !== undefined ) ; cert = certs . find ( ( x ) => doesPubKeyMatch ( x ! . publicKeyData , pubKey ) ) ?. cert ; ca = certs . filter ( ( x ) => ! doesPubKeyMatch ( x ! . publicKeyData , pubKey ) ) . map ( ( x ) => x ! . cert ) ; if ( ca . length === 0 ) { ca = undefined ; } } return { ca , cert } ; } ; export const convertCert = ( bag ) => { const cert = bag . cert ; if ( cert ) { const pem = pki . certificateToPem ( cert ) ; const key = cert . publicKey as pki . rsa . PublicKey ; const publicKeyData = { n : key . n as BigInteger , e : key . e as BigInteger , } ; return { cert : pem , publicKeyData , } ; } return undefined ; } ; const getKey = ( p12 ) => { const bags = [ ... ( getBags ( p12 , pki . oids . keyBag ) || [ ] ) , ... ( getBags ( p12 , pki . oids . pkcs8ShroudedKeyBag ) || [ ] ) , ] ; if ( bags && bags . length ) { if ( bags . length > 1 ) { throw new Error ( `Keystore contains multiple private keys.` ) ; } const key = bags [ 0 ] . key as pki . rsa . PrivateKey ; if ( key ) { const pem = pki . privateKeyToPem ( key ) ; const publicKeyData = { n : key . n as BigInteger , e : key . e as BigInteger , } ; return { key : pem , publicKeyData , } ; } } return undefined ; } ; const getBags = ( p12 , bagType ) => { const bagObj = p12 . getBags ( { bagType } ) ; const bags = bagObj [ bagType ] ; if ( bags && bags . length ) { return bags ; } return undefined ; } ;