diff --git a/src/XMLSecurityDSig.php b/src/XMLSecurityDSig.php index cb525388..696f6d70 100644 --- a/src/XMLSecurityDSig.php +++ b/src/XMLSecurityDSig.php @@ -990,6 +990,7 @@ public static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $i $issuerSerial = false; $subjectName = false; + $addPubKeyInfo = false; if (is_array($options)) { if (! empty($options['issuerSerial'])) { $issuerSerial = true; @@ -997,12 +998,16 @@ public static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $i if (! empty($options['subjectName'])) { $subjectName = true; } + if (! empty($options['pubKeyInfo'])) { + $addPubKeyInfo = true; + } } // Attach all certificate nodes and any additional data foreach ($certs as $X509Cert) { - if ($issuerSerial || $subjectName) { - if ($certData = openssl_x509_parse("-----BEGIN CERTIFICATE-----\n".chunk_split($X509Cert, 64, "\n")."-----END CERTIFICATE-----\n")) { + if ($issuerSerial || $subjectName || $addPubKeyInfo) { + $certString = "-----BEGIN CERTIFICATE-----\n".chunk_split($X509Cert, 64, "\n")."-----END CERTIFICATE-----\n"; + if ($certData = openssl_x509_parse($certString)) { if ($subjectName && ! empty($certData['subject'])) { if (is_array($certData['subject'])) { $parts = array(); @@ -1035,6 +1040,17 @@ public static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $i $x509Node = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'X509SerialNumber', $certData['serialNumber']); $x509IssuerNode->appendChild($x509Node); } + if ($addPubKeyInfo) { + $pubkeyInfo = openssl_pkey_get_details(openssl_pkey_get_public($certString)); + if ($pubkeyInfo['type'] === OPENSSL_KEYTYPE_RSA) { + $keyValueNode = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'KeyValue'); + $keyInfo -> appendChild($keyValueNode); + $rsaKeyValueNode = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'RSAKeyValue'); + $keyValueNode -> appendChild($rsaKeyValueNode); + $rsaKeyValueNode -> appendChild($baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'Modulus', base64_encode($pubkeyInfo["rsa"]["n"]))); + $rsaKeyValueNode -> appendChild($baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'Exponent', base64_encode($pubkeyInfo["rsa"]["e"]))); + } + } } } diff --git a/tests/sign-subject-key-info.res b/tests/sign-subject-key-info.res new file mode 100644 index 00000000..35b75d48 --- /dev/null +++ b/tests/sign-subject-key-info.res @@ -0,0 +1,11 @@ + + + + + Hello, World! + + + + + scTXEJcKZm9Mb0ldX7LSRbAKY8g=TPHrAOC4iXv5Uwk4oROJXuXHVJ7bUgmUVsAdr21oPhy37ROqT8ZsaWHxAFnBnc5XmXKkzu1yYrlNA7Im9nmAXwMZCH4xZvvFTBR2UA49F8Of92GKRLqwy+OBp/zA0FnEOKB9ji/ZYEMeZ4SoV7fY+avoJ4u5UBjlj/dtQrZVQcftdOw1+urvIo43PYpxLeIVxs+fnO8o6+pc80OLOhzT0tcnNLkYZvfTufdi2PjDuJvjaNP+HGbvSkleUoSwngAFDu4yABKudiEYENxzesP09HtMrWnmjNy2MAejq71ABsXPlx2O1acDA5b9eYRTmZTfxOQwRTxTn6fUb2GNJsPS8A== +CN=xmlseclibs/www.cdatazone.org,O=xmlseclibs.php Library,L=Limington,ST=Maine,C=USMIIEVDCCAzygAwIBAgIJAPTrkMJbCOr1MA0GCSqGSIb3DQEBBQUAMHkxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVNYWluZTESMBAGA1UEBxMJTGltaW5ndG9uMR8wHQYDVQQKExZ4bWxzZWNsaWJzLnBocCBMaWJyYXJ5MSUwIwYDVQQDExx4bWxzZWNsaWJzL3d3dy5jZGF0YXpvbmUub3JnMB4XDTA4MDcwNzIwMjIzMVoXDTE4MDcwNTIwMjIzMVoweTELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBU1haW5lMRIwEAYDVQQHEwlMaW1pbmd0b24xHzAdBgNVBAoTFnhtbHNlY2xpYnMucGhwIExpYnJhcnkxJTAjBgNVBAMTHHhtbHNlY2xpYnMvd3d3LmNkYXRhem9uZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDttdMyM5ISVD1Uz+BHAPrxVJ6N1eZonfg3DMvZVT0Zy64+qcXj8zuHC6lolDsfGnD8LUttraQ7qCL+bHKps+hjAhCRdx5Wcn4iDrlFpxFL7INnr6vekzsCQ45BPUrvksF9FKa7yX4iSDButmPfoT14gPnIuSe8Y5UeGe6Lk6sF0WgHyL+JmxOu377Kuhah2pXZ1+z7V4JIlNgemJtKlqrvgGeuE9TagfGHUL9BuZK5fUx/RSDUjqxUeKU3fft9fGIAZl0dduitC2Otv4dr1gxLrUmI+ZZ75FmtfKQT7SmS92QVI2B5WAPlL1bnbvhkZiyw7nFE+Q/wGJ2myE4RIFjdAgMBAAGjgd4wgdswHQYDVR0OBBYEFEC5iG0uGXLpQG/zMj/4TuDWfTpHMIGrBgNVHSMEgaMwgaCAFEC5iG0uGXLpQG/zMj/4TuDWfTpHoX2kezB5MQswCQYDVQQGEwJVUzEOMAwGA1UECBMFTWFpbmUxEjAQBgNVBAcTCUxpbWluZ3RvbjEfMB0GA1UEChMWeG1sc2VjbGlicy5waHAgTGlicmFyeTElMCMGA1UEAxMceG1sc2VjbGlicy93d3cuY2RhdGF6b25lLm9yZ4IJAPTrkMJbCOr1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBACmSKrte07VrGB8dtrN5mrt28ILickQjguu46h6vChgQ4YfIAoA1KWNsZJUuuIzTDjE5xz2hsW37CI0yrNesv2ho2hhP+fIaxCGmcwLYXL80UaPRglYk5+wPWFOt3QFAVoEgwjLX9+y+c2Gu7xLgHAFZVRjQ5hhKT0Nj3vhnt0k8LcognNl1wKuWda7VL4tODp/2IOXr5o5v/OL3UesGfeWfvr8LVmMc5f7/vLAu1+2Yk+/C9/EZyf3BDZQ4z8ae/iwqprCTUIEjhUDcq4+0YN2EIw6suGE2FtWlsIywNErmoOhdrmntU61n3nFCQBi7QDUnZrAFrl4/bmk3eRJ00nE=7bXTMjOSElQ9VM/gRwD68VSejdXmaJ34NwzL2VU9GcuuPqnF4/M7hwupaJQ7Hxpw/C1Lba2kO6gi/mxyqbPoYwIQkXceVnJ+Ig65RacRS+yDZ6+r3pM7AkOOQT1K75LBfRSmu8l+IkgwbrZj36E9eID5yLknvGOVHhnui5OrBdFoB8i/iZsTrt++yroWodqV2dfs+1eCSJTYHpibSpaq74BnrhPU2oHxh1C/QbmSuX1Mf0Ug1I6sVHilN337fXxiAGZdHXborQtjrb+Ha9YMS61JiPmWe+RZrXykE+0pkvdkFSNgeVgD5S9W5274ZGYssO5xRPkP8BidpshOESBY3Q==AQAB diff --git a/tests/xml-sign-subject-key-info.phpt b/tests/xml-sign-subject-key-info.phpt new file mode 100644 index 00000000..678f1fe8 --- /dev/null +++ b/tests/xml-sign-subject-key-info.phpt @@ -0,0 +1,45 @@ +--TEST-- +Basic Signature With Subject and Key Info +--FILE-- +load(dirname(__FILE__) . '/basic-doc.xml'); + +$objDSig = new XMLSecurityDSig(); + +$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); + +$objDSig->addReference($doc, XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature')); + +$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private')); +/* load private key */ +$objKey->loadKey(dirname(__FILE__) . '/privkey.pem', TRUE); + +/* if key has Passphrase, set it using $objKey->passphrase = " */ + + +$objDSig->sign($objKey); + +/* Add associated public key */ +$objDSig->add509Cert(file_get_contents(dirname(__FILE__) . '/mycert.pem'), TRUE, FALSE, array('subjectName'=>TRUE, 'pubKeyInfo'=>TRUE)); + +$objDSig->appendSignature($doc->documentElement); +$doc->save(dirname(__FILE__) . '/sign-subject-key-info.xml'); + +$sign_output = file_get_contents(dirname(__FILE__) . '/sign-subject-key-info.xml'); +$sign_output_def = file_get_contents(dirname(__FILE__) . '/sign-subject-key-info.res'); +if ($sign_output != $sign_output_def) { + echo "NOT THE SAME\n"; +} +echo "DONE\n"; +?> +--EXPECTF-- +DONE