66use DOMNode ;
77use DOMXPath ;
88use Exception ;
9+ use phpseclib3 \File \X509 ;
910use RobRichards \XMLSecLibs \Utils \XPath as XPath ;
1011
1112/**
@@ -1039,44 +1040,28 @@ public static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $i
10391040 // Attach all certificate nodes and any additional data
10401041 foreach ($ certs as $ X509Cert ) {
10411042 if ($ issuerSerial || $ subjectName ) {
1042- if ($ certData = openssl_x509_parse ("-----BEGIN CERTIFICATE----- \n" .chunk_split ($ X509Cert , 64 , "\n" )."-----END CERTIFICATE----- \n" )) {
1043- if ($ subjectName && ! empty ($ certData ['subject ' ])) {
1044- if (is_array ($ certData ['subject ' ])) {
1045- $ parts = array ();
1046- foreach ($ certData ['subject ' ] AS $ key => $ value ) {
1047- if (is_array ($ value )) {
1048- foreach ($ value as $ valueElement ) {
1049- array_unshift ($ parts , "$ key= $ valueElement " );
1050- }
1051- } else {
1052- array_unshift ($ parts , "$ key= $ value " );
1053- }
1054- }
1055- $ subjectNameValue = implode (', ' , $ parts );
1056- } else {
1057- $ subjectNameValue = $ certData ['subject ' ];
1043+ $ pem = "-----BEGIN CERTIFICATE----- \n" .chunk_split ($ X509Cert , 64 , "\n" )."-----END CERTIFICATE----- \n" ;
1044+ $ x509 = new X509 ();
1045+ if ($ certData = $ x509 ->loadX509 ($ pem )) {
1046+ if ($ subjectName ) {
1047+ $ subjectNameValue = self ::getX509NameString ($ x509 , false );
1048+ if ($ subjectNameValue !== null ) {
1049+ $ x509SubjectNode = $ baseDoc ->createElementNS (self ::XMLDSIGNS , $ dsig_pfx .'X509SubjectName ' , $ subjectNameValue );
1050+ $ x509DataNode ->appendChild ($ x509SubjectNode );
10581051 }
1059- $ x509SubjectNode = $ baseDoc ->createElementNS (self ::XMLDSIGNS , $ dsig_pfx .'X509SubjectName ' , $ subjectNameValue );
1060- $ x509DataNode ->appendChild ($ x509SubjectNode );
10611052 }
1062- if ($ issuerSerial && ! empty ($ certData ['issuer ' ]) && ! empty ($ certData ['serialNumber ' ])) {
1063- if (is_array ($ certData ['issuer ' ])) {
1064- $ parts = array ();
1065- foreach ($ certData ['issuer ' ] AS $ key => $ value ) {
1066- array_unshift ($ parts , "$ key= $ value " );
1067- }
1068- $ issuerName = implode (', ' , $ parts );
1069- } else {
1070- $ issuerName = $ certData ['issuer ' ];
1053+ if ($ issuerSerial ) {
1054+ $ issuerName = self ::getX509NameString ($ x509 , true );
1055+ $ serialNumber = self ::getX509SerialNumber ($ certData );
1056+ if ($ issuerName !== null && $ serialNumber !== null ) {
1057+ $ x509IssuerNode = $ baseDoc ->createElementNS (self ::XMLDSIGNS , $ dsig_pfx .'X509IssuerSerial ' );
1058+ $ x509DataNode ->appendChild ($ x509IssuerNode );
1059+
1060+ $ x509Node = $ baseDoc ->createElementNS (self ::XMLDSIGNS , $ dsig_pfx .'X509IssuerName ' , $ issuerName );
1061+ $ x509IssuerNode ->appendChild ($ x509Node );
1062+ $ x509Node = $ baseDoc ->createElementNS (self ::XMLDSIGNS , $ dsig_pfx .'X509SerialNumber ' , $ serialNumber );
1063+ $ x509IssuerNode ->appendChild ($ x509Node );
10711064 }
1072-
1073- $ x509IssuerNode = $ baseDoc ->createElementNS (self ::XMLDSIGNS , $ dsig_pfx .'X509IssuerSerial ' );
1074- $ x509DataNode ->appendChild ($ x509IssuerNode );
1075-
1076- $ x509Node = $ baseDoc ->createElementNS (self ::XMLDSIGNS , $ dsig_pfx .'X509IssuerName ' , $ issuerName );
1077- $ x509IssuerNode ->appendChild ($ x509Node );
1078- $ x509Node = $ baseDoc ->createElementNS (self ::XMLDSIGNS , $ dsig_pfx .'X509SerialNumber ' , $ certData ['serialNumber ' ]);
1079- $ x509IssuerNode ->appendChild ($ x509Node );
10801065 }
10811066 }
10821067
@@ -1086,6 +1071,49 @@ public static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $i
10861071 }
10871072 }
10881073
1074+ /**
1075+ * Format an X.509 DN in openssl_x509_parse-compatible reverse RDN order.
1076+ *
1077+ * @param X509 $x509
1078+ * @param bool $issuer
1079+ * @return string|null
1080+ */
1081+ private static function getX509NameString (X509 $ x509 , $ issuer )
1082+ {
1083+ $ dnArray = $ issuer ? $ x509 ->getIssuerDN (X509 ::DN_OPENSSL ) : $ x509 ->getDN (X509 ::DN_OPENSSL );
1084+ if (! is_array ($ dnArray ) || empty ($ dnArray )) {
1085+ return null ;
1086+ }
1087+
1088+ $ parts = array ();
1089+ foreach ($ dnArray as $ key => $ value ) {
1090+ if (is_array ($ value )) {
1091+ foreach ($ value as $ valueElement ) {
1092+ array_unshift ($ parts , "$ key= $ valueElement " );
1093+ }
1094+ } else {
1095+ array_unshift ($ parts , "$ key= $ value " );
1096+ }
1097+ }
1098+ return implode (', ' , $ parts );
1099+ }
1100+
1101+ /**
1102+ * @param array $certData
1103+ * @return string|null
1104+ */
1105+ private static function getX509SerialNumber (array $ certData )
1106+ {
1107+ if (! isset ($ certData ['tbsCertificate ' ]['serialNumber ' ])) {
1108+ return null ;
1109+ }
1110+ $ serial = $ certData ['tbsCertificate ' ]['serialNumber ' ];
1111+ if (is_object ($ serial ) && method_exists ($ serial , 'toString ' )) {
1112+ return $ serial ->toString ();
1113+ }
1114+ return (string ) $ serial ;
1115+ }
1116+
10891117 /**
10901118 * @param string $cert
10911119 * @param bool $isPEMFormat
0 commit comments