import crypto , { HexBase64Latin1Encoding , Utf8AsciiLatin1Encoding } from 'crypto' ; import forge from 'node-forge' ; /**
 * Returns the serial number of the given X.509 certificate as an uppercased hexadecimal string
 */ export function getFormattedSerialNumber ( certificate ) { const { serialNumber } = certificate ; return serialNumber ? serialNumber . replace ( /^0+/ , '' ) . toUpperCase ( ) : null ; } /**
 * Extracts a certificate from PKCS#12
 * This is assumed to be a conventional PKCS#12 where there is exactly one certificate and one key
 */ export function getX509Certificate ( p12 ) { const certBagType = forge . pki . oids . certBag ; const bags = p12 . getBags ( { bagType : certBagType } ) [ certBagType ] ; if ( ! bags || bags . length === 0 ) { throw new Error ( `PKCS12: No certificates found` ) ; } return getX509CertificateFromBag ( bags [ 0 ] ) ; } /**
 * Extracts a certificate from PKCS#12
 * This is assumed to be a PKCS#12 containing a keystore where the friendlyName (alias) contains a PrivateKeyEntry
 * A PrivateKeyEntry contains exactly one certificate and one key
 * https://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.PrivateKeyEntry.html
 */ export function getX509CertificateByFriendlyName ( p12 , friendlyName ) { const certBagType = forge . pki . oids . certBag ; const bags = p12 . getBags ( { friendlyName : friendlyName . toLowerCase ( ) , bagType : certBagType } ) . friendlyName ; if ( ! bags || bags . length === 0 ) { return null ; } return getX509CertificateFromBag ( bags [ 0 ] ) ; } function getX509CertificateFromBag ( bag ) { const { cert , asn1 } = bag ; if ( ! cert && asn1 ) { throw new Error ( 'PKCS12: unknown X.509 certificate type' ) ; } if ( ! cert ) { throw new Error ( 'PKCS12: bag is not a certificate' ) ; } return cert ; } export function getX509Asn1ByFriendlyName ( p12 , friendlyName ) { const certBagType = forge . pki . oids . certBag ; const bags = p12 . getBags ( { friendlyName : friendlyName . toLowerCase ( ) , bagType : certBagType } ) . friendlyName ; if ( ! bags || bags . length === 0 ) { return null ; } const { cert , asn1 } = bags [ 0 ] ; if ( cert ) { return forge . pki . certificateToAsn1 ( cert ) ; } return asn1 ?? null ; } export function parsePKCS12 ( p12BufferOrBase64String , maybePassword ) { const base64EncodedP12 = Buffer . isBuffer ( p12BufferOrBase64String ) ? p12BufferOrBase64String . toString ( 'base64' ) : p12BufferOrBase64String ; const password = String ( maybePassword ?? '' ) ; const p12Der = forge . util . decode64 ( base64EncodedP12 ) ; const p12Asn1 = forge . asn1 . fromDer ( p12Der ) ; return forge . pkcs12 . pkcs12FromAsn1 ( p12Asn1 , password ) ; } function getHash ( data , { hashAlgorithm , hashEncoding , inputEncoding , } ) { const hash = crypto . createHash ( hashAlgorithm ?? 'sha1' ) ; if ( inputEncoding ) { hash . update ( data , inputEncoding ) ; } else { hash . update ( data ) ; } return hash . digest ( hashEncoding ?? 'hex' ) ; } export function getAsn1Hash ( asn1 , { hashAlgorithm , } ) { const certDer = forge . asn1 . toDer ( asn1 ) . getBytes ( ) ; return getHash ( certDer , { hashAlgorithm , hashEncoding : 'hex' , inputEncoding : 'latin1' } ) ; } export function getCertificateFingerprint ( certificate , { hashAlgorithm , } ) { const certAsn1 = forge . pki . certificateToAsn1 ( certificate ) ; return getAsn1Hash ( certAsn1 , { hashAlgorithm } ) ; }