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