function signXML($token, $privkey) { $sigdoc = new DOMDocument(); if (!$sigdoc->loadXML($token)) { throw new Exception("Invalid XML!"); } $sigNode = $sigdoc->firstChild; $enc = new XMLSecurityDSig(); $enc->idKeys[] = 'ID'; $enc->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); $enc->addReference($sigNode, XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N)); $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private', 'library' => 'openssl')); $key->loadKey($privkey, false, false); $enc->sign($key); $enc->appendSignature($sigNode); return $sigdoc->saveXML(); }
public function signSoapDoc($objKey, $options = null) { $objDSig = new XMLSecurityDSig(); $objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); $arNodes = array(); foreach ($this->secNode->childNodes as $node) { if ($node->nodeType == XML_ELEMENT_NODE) { $arNodes[] = $node; } } foreach ($this->secNode->parentNode->childNodes as $node) { if ($this->signAllHeaders || $node->localName == 'To') { if ($node->nodeType == XML_ELEMENT_NODE && $node->namespaceURI != self::WSSENS) { $arNodes[] = $node; } } } if ($this->signBody) { foreach ($this->envelope->childNodes as $node) { if ($node->namespaceURI == $this->soapNS && $node->localName == 'Body') { $arNodes[] = $node; break; } } } $algorithm = XMLSecurityDSig::SHA1; if (is_array($options) && isset($options["algorithm"])) { $algorithm = $options["algorithm"]; } $arOptions = array('prefix' => self::WSUPFX, 'prefix_ns' => self::WSUNS); $objDSig->addReferenceList($arNodes, $algorithm, null, $arOptions); $objDSig->sign($objKey); $insertTop = true; if (is_array($options) && isset($options["insertBefore"])) { $insertTop = (bool) $options["insertBefore"]; } $objDSig->appendSignature($this->secNode, $insertTop); /* New suff */ if (is_array($options)) { if (!empty($options["KeyInfo"])) { if (!empty($options["KeyInfo"]["X509SubjectKeyIdentifier"])) { $sigNode = $this->secNode->firstChild->nextSibling; $objDoc = $sigNode->ownerDocument; $keyInfo = $sigNode->ownerDocument->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo'); $sigNode->appendChild($keyInfo); $tokenRef = $objDoc->createElementNS(self::WSSENS, self::WSSEPFX . ':SecurityTokenReference'); $keyInfo->appendChild($tokenRef); $reference = $objDoc->createElementNS(self::WSSENS, self::WSSEPFX . ':KeyIdentifier'); $reference->setAttribute("ValueType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier"); $reference->setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"); $tokenRef->appendChild($reference); $x509 = openssl_x509_parse($objKey->getX509Certificate()); $keyid = $x509["extensions"]["subjectKeyIdentifier"]; $arkeyid = split(":", $keyid); $data = ""; foreach ($arkeyid as $hexchar) { $data .= chr(hexdec($hexchar)); } $dataNode = new DOMText(base64_encode($data)); $reference->appendChild($dataNode); } } } }
public function signSoapDoc($objKey) { $objDSig = new XMLSecurityDSig(); $objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); $arNodes = array(); foreach ($this->secNode->childNodes as $node) { if ($node->nodeType == XML_ELEMENT_NODE) { $arNodes[] = $node; } } if ($this->signAllHeaders) { foreach ($this->secNode->parentNode->childNodes as $node) { if ($node->nodeType == XML_ELEMENT_NODE && $node->namespaceURI != WSSESoap::WSSENS) { $arNodes[] = $node; } } } foreach ($this->envelope->childNodes as $node) { if ($node->namespaceURI == $this->soapNS && $node->localName == 'Body') { $arNodes[] = $node; break; } } $arOptions = array('prefix' => WSSESoap::WSUPFX, 'prefix_ns' => WSSESoap::WSUNS); $objDSig->addReferenceList($arNodes, XMLSecurityDSig::SHA1, NULL, $arOptions); $objDSig->sign($objKey); $objDSig->appendSignature($this->secNode, TRUE); }
/** * Sign the specified DOMDocument * * @see https://github.com/Maks3w/xmlseclibs/blob/v1.3.0/tests/xml-sign.phpt * * @param DOMDocument $document * @return DOMDocument */ private function sign_document(DOMDocument $document) { $result = false; try { $dsig = new XMLSecurityDSig(); // For canonicalization purposes the exclusive (9) algorithm must be used. // @see http://pronamic.nl/wp-content/uploads/2012/12/iDEAL-Merchant-Integration-Guide-ENG-v3.3.1.pdf #page 30 $dsig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); // For hashing purposes the SHA-256 (11) algorithm must be used. // @see http://pronamic.nl/wp-content/uploads/2012/12/iDEAL-Merchant-Integration-Guide-ENG-v3.3.1.pdf #page 30 $dsig->addReference($document, XMLSecurityDSig::SHA256, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature'), array('force_uri' => true)); // For signature purposes the RSAWithSHA 256 (12) algorithm must be used. // @see http://pronamic.nl/wp-content/uploads/2012/12/iDEAL-Merchant-Integration-Guide-ENG-v3.3.1.pdf #page 31 $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type' => 'private')); $key->passphrase = $this->private_key_password; $key->loadKey($this->private_key); // Test if we can get an private key object, to prefent the following errors: // Warning: openssl_sign() [function.openssl-sign]: supplied key param cannot be coerced into a private key $result = openssl_get_privatekey($this->private_key, $this->private_key_password); if (false !== $result) { // Sign $dsig->sign($key); // The public key must be referenced using a fingerprint of an X.509 // certificate. The fingerprint must be calculated according // to the following formula HEX(SHA-1(DER certificate)) (13) // @see http://pronamic.nl/wp-content/uploads/2012/12/iDEAL-Merchant-Integration-Guide-ENG-v3.3.1.pdf #page 31 $fingerprint = Pronamic_WP_Pay_Gateways_IDealAdvanced_Security::getShaFingerprint($this->private_certificate); $dsig->addKeyInfoAndName($fingerprint); // Add the signature $dsig->appendSignature($document->documentElement); $result = $document; } else { throw new Exception('Can not load private key'); } } catch (Exception $e) { $this->error = new WP_Error('xml_security', $e->getMessage(), $e); } return $result; }
function processDocument() { global $src_file, $target_file, $user_pubkey_file_path, $user_cert_file_path; require dirname(__FILE__) . '/xmlseclibs.php'; if (file_exists($target_file)) { unlink($target_file); } $doc = new DOMDocument(); $doc->load($src_file); $objDSig = new XMLSecurityDSig(); $objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); $objDSig->addReference($doc, XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature')); /* gako pribatu bat behar dugu prozesua burutzeko. orain edozein erabiliko dugu. gero txartelekoarekin ordezkatzeko */ $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private')); /* if key has Passphrase, set it using $objKey->passphrase = <passphrase> " */ $objKey->loadKey(dirname(__FILE__) . '/privkey.pem', TRUE); $objDSig->sign($objKey); /* Add associated public key */ // $objDSig->add509Cert(file_get_contents(dirname(__FILE__) . '/mycert.pem')); // $objDSig->add509Cert(file_get_contents($user_cert_file_path)); if (!file_exists($user_cert_file_path)) { debug('File not found', $user_cert_file_path); } else { $objDSig->add509Cert($user_cert_file_path); } $objDSig->appendSignature($doc->documentElement); $doc->save($target_file); }
/** * @dataProvider testXmlSignProvider * @throws \Exception */ public function testXmlSign($dsigAlgorithm, $keyType, $expectedFileName) { $doc = new \DOMDocument(); $doc->load(dirname(__FILE__) . '/../basic-doc.xml'); $objDSig = new XMLSecurityDSig(); $objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); $objDSig->addReference($doc, $dsigAlgorithm, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature')); $objKey = new XMLSecurityKey($keyType, array('type' => 'private')); /* load private key */ $objKey->loadKey(dirname(__FILE__) . '/../privkey.pem', true); /* if key has Passphrase, set it using $objKey->passphrase = <passphrase> " */ $objDSig->sign($objKey); /* Add associated public key */ $objDSig->add509Cert(file_get_contents(dirname(__FILE__) . '/../mycert.pem')); $objDSig->appendSignature($doc->documentElement); $sign_output = $doc->saveXML(); $sign_output_def = file_get_contents($expectedFileName); $this->assertEquals($sign_output_def, $sign_output, "Signature doesn't match"); }
$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); $objDSig->addReference($doc, XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature')); /* gako pribatu bat behar dugu prozesua burutzeko. orain edozein erabiliko dugu. gero txartelekoarekin ordezkatzeko */ $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private')); /* if key has Passphrase, set it using $objKey->passphrase = <passphrase> " */ $objKey->loadKey(dirname(__FILE__) . '/privkey.pem', TRUE); $objDSig->sign($objKey); /* Add associated public key */ // $objDSig->add509Cert(file_get_contents(dirname(__FILE__) . '/mycert.pem')); // $objDSig->add509Cert(file_get_contents($user_cert_file_path)); if (!file_exists($user_cert_file_path)) { die('File not found : ' . $user_cert_file_path); } else { $objDSig->add509Cert($user_cert_file_path); } $objDSig->appendSignature($doc->documentElement); $doc->save($target_file); ?> <h3>Por favor, apriete el botón "Enviar" para acabar con el registro del fichero en la Agencia de Proteccion de datos</h3> <?php echo '<form id="formMyFirma" name="formMyFirma" method="post" onsubmit="document.getElementById(\'sinatuta\').value = signDigest(document.getElementById(\'sinatzeko\').value);" action="' . str_replace("http://", "https://", UsuarioPeer::getRuta()) . '/notificaciones/enviar/id_notificacion/' . $notificacion->notid . '/id_fichero/' . $notificacion->id_fichero . '/yafirmado/1">'; echo '<input type="hidden" id="sinatzeko" name="sinatzeko" value="' . trim(strip_tags(_CANON_DATA)) . '">'; echo '<input type="hidden" id="sinatuta" name="sinatuta" value="">'; //echo '<input onclick="document.getElementById(\'sinatuta\').value = signDigest(document.getElementById(\'sinatzeko\').value);" value="Firmar documento con tarjeta" type="button"><br />'; echo '<input type="submit" name="submit" value="Enviar" /><br />'; echo '</form>'; echo '<script type="text/javascript">'; echo '/*document.getElementById(\'sinatuta\').value = signDigest(document.getElementById(\'sinatzeko\').value);*/'; echo 'document.getElementById(\'formMyFirma\').submit();'; echo '</script><br />';
public function sendResponse($response, $idmetaindex, $spentityid, $relayState = null) { $idpmd = $this->metadata->getMetaData($idmetaindex, 'saml20-idp-hosted'); $spmd = $this->metadata->getMetaData($spentityid, 'saml20-sp-remote'); $destination = $spmd['AssertionConsumerService']; if (empty($idpmd['privatekey'])) { throw new Exception('SAML: RSA private key not configured. This is required to sign the authentication response.'); } if (empty($idpmd['certificate'])) { throw new Exception('SAML: X.509 certificate not configured. This is required to attach to the authentication response.'); } // XMLDSig. Sign the complete request with the key stored in cert/server.pem $objXMLSecDSig = new XMLSecurityDSig(); $objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); try { $responsedom = new DOMDocument(); $responsedom->loadXML(str_replace("\n", "", str_replace("\r", "", $response))); } catch (Exception $e) { throw new Exception("foo"); } $responseroot = $responsedom->getElementsByTagName('Response')->item(0); $firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0); /* Determine what we should sign - either the Response element or the Assertion. The default * is to sign the Assertion, but that can be overridden by the 'signresponse' option in the * SP metadata or 'saml20.signresponse' in the global configuration. */ $signResponse = FALSE; if (array_key_exists('signresponse', $spmd) && $spmd['signresponse'] !== NULL) { $signResponse = $spmd['signresponse']; if (!is_bool($signResponse)) { throw new Exception('Expected the \'signresponse\' option in the metadata of the' . ' SP \'' . $spmd['entityid'] . '\' to be a boolean value.'); } } else { $signResponse = $this->configuration->getBoolean('saml20.signresponse', FALSE); } if ($signResponse) { // Sign the response. $objXMLSecDSig->addReferenceList(array($responseroot), XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N), array('id_name' => 'ID')); } else { // Sign the assertion. $objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N), array('id_name' => 'ID')); } $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private')); if (array_key_exists('privatekey_pass', $idpmd)) { $objKey->passphrase = $idpmd['privatekey_pass']; } $objKey->loadKey($idpmd['privatekey']); $objXMLSecDSig->sign($objKey); $objXMLSecDSig->add509Cert($idpmd['certificate'], true); if ($signResponse) { $objXMLSecDSig->appendSignature($responseroot, true, false); } else { $objXMLSecDSig->appendSignature($firstassertionroot, true, true); } if (isset($spmd['assertion.encryption']) && $spmd['assertion.encryption']) { $encryptedassertion = $responsedom->createElement("saml:EncryptedAssertion"); $encryptedassertion->setAttribute("xmlns:saml", "urn:oasis:names:tc:SAML:2.0:assertion"); $firstassertionroot->parentNode->replaceChild($encryptedassertion, $firstassertionroot); $encryptedassertion->appendChild($firstassertionroot); $enc = new XMLSecEnc(); $enc->setNode($firstassertionroot); $enc->type = XMLSecEnc::Element; $objKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); if (isset($spmd['sharedkey'])) { $objKey->loadkey($spmd['sharedkey']); } else { $key = $objKey->generateSessionKey(); $objKey->loadKey($key); if (empty($spmd['certificate'])) { throw new Exception("Public key for encrypting assertion needed, but not specified for saml20-sp-remote id: " . $spentityid); } $keyKey = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, array('type' => 'public')); $keyKey->loadKey($spmd['certificate']); $enc->encryptKey($keyKey, $objKey); } $encNode = $enc->encryptNode($objKey); # replacing the unencrypted node } $response = $responsedom->saveXML(); SimpleSAML_Utilities::validateXMLDocument($response, 'saml20'); # openssl genrsa -des3 -out server.key 1024 # openssl rsa -in server.key -out server.pem # openssl req -new -key server.key -out server.csr # openssl x509 -req -days 60 -in server.csr -signkey server.key -out server.crt if ($this->configuration->getValue('debug')) { $p = new SimpleSAML_XHTML_Template($this->configuration, 'post-debug.php'); $p->data['header'] = 'SAML Response Debug-mode'; $p->data['RelayStateName'] = 'RelayState'; $p->data['RelayState'] = $relayState; $p->data['destination'] = $destination; $p->data['response'] = str_replace("\n", "", base64_encode($response)); $p->data['responseHTML'] = htmlentities($responsedom->saveHTML()); $p->show(); } else { $p = new SimpleSAML_XHTML_Template($this->configuration, 'post.php'); $p->data['RelayStateName'] = 'RelayState'; $p->data['RelayState'] = $relayState; $p->data['destination'] = $destination; $p->data['response'] = base64_encode($response); $p->show(); } }