/** * Set the assertion. * * @param SAML2_Assertion $assertion The assertion. * @param XMLSecurityKey $key The key we should use to encrypt the assertion. * @throws Exception */ public function setAssertion(SAML2_Assertion $assertion, XMLSecurityKey $key) { $xml = $assertion->toXML(); SAML2_Utils::getContainer()->debugMessage($xml, 'encrypt'); $enc = new XMLSecEnc(); $enc->setNode($xml); $enc->type = XMLSecEnc::Element; switch ($key->type) { case XMLSecurityKey::TRIPLEDES_CBC: case XMLSecurityKey::AES128_CBC: case XMLSecurityKey::AES192_CBC: case XMLSecurityKey::AES256_CBC: $symmetricKey = $key; break; case XMLSecurityKey::RSA_1_5: case XMLSecurityKey::RSA_OAEP_MGF1P: $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); $symmetricKey->generateSessionKey(); $enc->encryptKey($key, $symmetricKey); break; default: throw new Exception('Unknown key type for encryption: ' . $key->type); } $this->encryptedData = $enc->encryptNode($symmetricKey); }
public function addUserToken($userName, $password = NULL, $passwordDigest = FALSE) { if ($passwordDigest && empty($password)) { throw new Exception("Cannot calculate the digest without a password"); } $security = $this->locateSecurityHeader(); $token = $this->SOAPDoc->createElementNS(WSSESoap::WSUNS, WSSESoap::WSUPFX . ':UsernameToken'); $security->insertBefore($token, $security->firstChild); $username = $this->SOAPDoc->createElementNS(WSSESoap::WSUNS, WSSESoap::WSUPFX . ':Username', $userName); $token->appendChild($username); /* Generate nonce - create a 256 bit session key to be used */ $objKey = new XMLSecurityKey(XMLSecurityKey::AES256_CBC); $nonce = $objKey->generateSessionKey(); unset($objKey); $createdate = gmdate("Y-m-d\\TH:i:s") . 'Z'; if ($password) { $passType = '#PasswordText'; if ($passwordDigest) { $password = base64_encode(sha1($nonce . $createdate . $password, true)); $passType = '#PasswordDigest'; } $passwordNode = $this->SOAPDoc->createElementNS(WSSESoap::WSUNS, WSSESoap::WSUPFX . ':Password', $userName); $token->appendChild($passwordNode); $passwordNode->setAttribute('Type', $passType); } $nonceNode = $this->SOAPDoc->createElementNS(WSSESoap::WSUNS, WSSESoap::WSUPFX . ':Nonce', base64_encode($nonce)); $token->appendChild($nonceNode); $created = $this->SOAPDoc->createElementNS(WSSESoap::WSUNS, WSSESoap::WSUPFX . ':Created', $createdate); $token->appendChild($created); return $token; }
public function __doRequest($request, $location, $saction, $version) { $doc = new DOMDocument('1.0'); $doc->loadXML($request); $objWSSE = new WSSESoap($doc); /* add Timestamp with no expiration timestamp */ $objWSSE->addTimestamp(); /* create new XMLSec Key using AES256_CBC and type is private key */ $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private')); /* load the private key from file - last arg is bool if key in file (true) or is string (false) */ $objKey->loadKey(PRIVATE_KEY, true); /* Sign the message - also signs appropiate WS-Security items */ $options = array("insertBefore" => false); $objWSSE->signSoapDoc($objKey, $options); /* Add certificate (BinarySecurityToken) to the message */ $token = $objWSSE->addBinaryToken(file_get_contents(CERT_FILE)); /* Attach pointer to Signature */ $objWSSE->attachTokentoSig($token); $objKey = new XMLSecurityKey(XMLSecurityKey::AES256_CBC); $objKey->generateSessionKey(); $siteKey = new XMLSecurityKey(XMLSecurityKey::RSA_OAEP_MGF1P, array('type' => 'public')); $siteKey->loadKey(SERVICE_CERT, true, true); $options = array("KeyInfo" => array("X509SubjectKeyIdentifier" => true)); $objWSSE->encryptSoapDoc($siteKey, $objKey, $options); $retVal = parent::__doRequest($objWSSE->saveXML(), $location, $saction, $version); $doc = new DOMDocument(); $doc->loadXML($retVal); $options = array("keys" => array("private" => array("key" => PRIVATE_KEY, "isFile" => true, "isCert" => false))); $objWSSE->decryptSoapDoc($doc, $options); return $doc->saveXML(); }
function __doRequest($request, $location, $saction, $version) { $doc = new DOMDocument('1.0'); $doc->loadXML($request); $objWSSE = new WSSESoap($doc); $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private')); $objKey->loadKey(PRIVATE_KEY, TRUE); $options = array("insertBefore" => TRUE); $objWSSE->signSoapDoc($objKey, $options); $objWSSE->addIssuerSerial(CERT_FILE); $objKey = new XMLSecurityKey(XMLSecurityKey::AES256_CBC); $objKey->generateSessionKey(); #está wea está rara, no pasa el wsdl y cambía el puerto o.O $location = "https://201.238.207.130:7200/WSWebpayTransaction/cxf/WSWebpayService?wsdl"; #die($location); #die(CERT_FILE." ".PRIVATE_KEY); $retVal = parent::__doRequest($objWSSE->saveXML(), $location, $saction, $version); $doc = new DOMDocument(); $doc->loadXML($retVal); return $doc->saveXML(); /* if ($this->useSSL){ $locationparts = parse_url($location); $location = 'https://'; if(isset($locationparts['host'])) $location .= $locationparts['host']; if(isset($locationparts['port'])) $location .= ':'.$locationparts['port']; if(isset($locationparts['path'])) $location .= $locationparts['path']; if(isset($locationparts['query'])) $location .= '?'.$locationparts['query']; } $doc = new DOMDocument('1.0'); $doc->loadXML($request); $objWSSE = new WSSESoap($doc); $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1,array('type' => 'private')); $objKey->loadKey(PRIVATE_KEY, TRUE); $options = array("insertBefore" => TRUE); $objWSSE->signSoapDoc($objKey, $options); $objWSSE->addIssuerSerial(CERT_FILE); $objKey = new XMLSecurityKey(XMLSecurityKey::AES256_CBC); $objKey->generateSessionKey(); $retVal = parent::__doRequest($objWSSE->saveXML(), $location, $saction, $version); $doc = new DOMDocument(); $doc->loadXML($retVal); return $doc->saveXML(); */ }
public function testGenerateSessionKeyParity() { /* Run the test several times, to increase the chance of detecting an error. */ for ($t = 0; $t < 16; $t++) { $key = new XMLSecurityKey(XMLSecurityKey::TRIPLEDES_CBC); $k = $key->generateSessionKey(); for ($i = 0; $i < strlen($k); $i++) { $byte = ord($k[$i]); $parity = 0; while ($byte !== 0) { $parity ^= $byte & 1; $byte >>= 1; } $this->assertEquals(1, $parity); } } }
/** * Add an EncryptedAttribute Statement-node to the assertion. * * @param DOMElement $root The assertion element we should add the Encrypted Attribute Statement to. */ private function addEncryptedAttributeStatement(DOMElement $root) { if ($this->requiredEncAttributes == FALSE) { return; } $document = $root->ownerDocument; $attributeStatement = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:AttributeStatement'); $root->appendChild($attributeStatement); foreach ($this->attributes as $name => $values) { $document2 = new DOMDocument(); $attribute = $document2->createElementNS(SAML2_Const::NS_SAML, 'saml:Attribute'); $attribute->setAttribute('Name', $name); $document2->appendChild($attribute); if ($this->nameFormat !== SAML2_Const::NAMEFORMAT_UNSPECIFIED) { $attribute->setAttribute('NameFormat', $this->nameFormat); } foreach ($values as $value) { if (is_string($value)) { $type = 'xs:string'; } elseif (is_int($value)) { $type = 'xs:integer'; } else { $type = NULL; } $attributeValue = $document2->createElementNS(SAML2_Const::NS_SAML, 'saml:AttributeValue'); $attribute->appendChild($attributeValue); if ($type !== NULL) { $attributeValue->setAttributeNS(SAML2_Const::NS_XSI, 'xsi:type', $type); } if ($value instanceof DOMNodeList) { for ($i = 0; $i < $value->length; $i++) { $node = $document2->importNode($value->item($i), TRUE); $attributeValue->appendChild($node); } } else { $attributeValue->appendChild($document2->createTextNode($value)); } } /*Once the attribute nodes are built, the are encrypted*/ $EncAssert = new XMLSecEnc(); $EncAssert->setNode($document2->documentElement); $EncAssert->type = 'http://www.w3.org/2001/04/xmlenc#Element'; /* * Attributes are encrypted with a session key and this one with * $EncryptionKey */ $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES256_CBC); $symmetricKey->generateSessionKey(); $EncAssert->encryptKey($this->encryptionKey, $symmetricKey); $EncrNode = $EncAssert->encryptNode($symmetricKey); $EncAttribute = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:EncryptedAttribute'); $attributeStatement->appendChild($EncAttribute); $n = $document->importNode($EncrNode, true); $EncAttribute->appendChild($n); } }
/** * Generates a nameID. * * @param string $value fingerprint * @param string $spnq SP Name Qualifier * @param string $format SP Format * @param string $cert IdP Public cert to encrypt the nameID * * @return string $nameIDElement DOMElement | XMLSec nameID */ public static function generateNameId($value, $spnq, $format, $cert = null) { $doc = new DOMDocument(); $nameId = $doc->createElement('saml:NameID'); $nameId->setAttribute('SPNameQualifier', $spnq); $nameId->setAttribute('Format', $format); $nameId->appendChild($doc->createTextNode($value)); $doc->appendChild($nameId); if (!empty($cert)) { $seckey = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, array('type' => 'public')); $seckey->loadKey($cert); $enc = new XMLSecEnc(); $enc->setNode($nameId); $enc->type = XMLSecEnc::Element; $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); $symmetricKey->generateSessionKey(); $enc->encryptKey($seckey, $symmetricKey); $encryptedData = $enc->encryptNode($symmetricKey); $newdoc = new DOMDocument(); $encryptedID = $newdoc->createElement('saml:EncryptedID'); $newdoc->appendChild($encryptedID); $encryptedID->appendChild($encryptedID->ownerDocument->importNode($encryptedData, true)); return $newdoc->saveXML($encryptedID); } else { return $doc->saveXML($nameId); } }
/** * Encrypt the NameID in the LogoutRequest. * * @param XMLSecurityKey $key The encryption key. */ public function encryptNameId(XMLSecurityKey $key) { /* First create a XML representation of the NameID. */ $doc = new DOMDocument(); $root = $doc->createElement('root'); $doc->appendChild($root); SAML2_Utils::addNameId($root, $this->nameId); $nameId = $root->firstChild; SAML2_Utils::getContainer()->debugMessage($nameId, 'encrypt'); /* Encrypt the NameID. */ $enc = new XMLSecEnc(); $enc->setNode($nameId); $enc->type = XMLSecEnc::Element; $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); $symmetricKey->generateSessionKey(); $enc->encryptKey($key, $symmetricKey); $this->encryptedNameId = $enc->encryptNode($symmetricKey); $this->nameId = NULL; }
/** * @throws \Exception */ public function testEncryptNoReplace() { $dom = new \DOMDocument(); $dom->load(dirname(__FILE__) . '/../basic-doc.xml'); $origData = $dom->saveXML(); $objKey = new XMLSecurityKey(XMLSecurityKey::AES256_CBC); $objKey->generateSessionKey(); $siteKey = new XMLSecurityKey(XMLSecurityKey::RSA_OAEP_MGF1P, array('type' => 'public')); $siteKey->loadKey(dirname(__FILE__) . '/../mycert.pem', true, true); $enc = new XMLSecEnc(); $enc->setNode($dom->documentElement); $enc->encryptKey($siteKey, $objKey); $enc->type = XMLSecEnc::Element; $encNode = $enc->encryptNode($objKey, false); $newData = $dom->saveXML(); $this->assertEquals($origData, $newData, "Original data was modified"); $this->assertFalse($encNode->namespaceURI !== XMLSecEnc::XMLENCNS || $encNode->localName !== 'EncryptedData', "Encrypted node wasn't a <xenc:EncryptedData>-element"); }
public function addUserToken($userName, $password = NULL, $passwordDigest = FALSE) { if ($passwordDigest && empty($password)) { throw new Exception("Cannot calculate the digest without a password"); } $security = $this->locateSecurityHeader(); $token = $this->soapDoc->createElementNS(WSSESoap::WSSENS, WSSESoap::WSSEPFX . ':UsernameToken'); //$token->setAttributeNS(WSSESoap::WSUNS, WSSESoap::WSUPFX.':Id', XMLSecurityDSig::generate_GUID()); $token->setAttribute(WSSESoap::XMLNS . ":" . WSSESoap::WSSEPFX, WSSESoap::WSSENS); $token->setAttribute("xmlns:wsu", WSSESoap::WSUNS); $security->insertBefore($token, $security->firstChild); $username = $this->soapDoc->createElementNS(WSSESoap::WSSENS, WSSESoap::WSSEPFX . ':Username', $userName); $username->setAttribute(WSSESoap::XMLNS . ":" . WSSESoap::WSSEPFX, WSSESoap::WSSENS); $token->appendChild($username); /* Generate nonce - create a 256 bit session key to be used */ $objKey = new XMLSecurityKey(XMLSecurityKey::AES256_CBC); $nonce = $objKey->generateSessionKey(); unset($objKey); $createdate = gmdate("Y-m-d\\TH:i:s") . 'Z'; if ($password) { $passType = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'; if ($passwordDigest) { $password = base64_encode(sha1($nonce . $createdate . $password, true)); $passType = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest'; } $passwordNode = $this->soapDoc->createElementNS(WSSESoap::WSSENS, WSSESoap::WSSEPFX . ':Password', $password); $token->appendChild($passwordNode); $passwordNode->setAttribute('xmlns:wsse', WSSESoap::WSSENS); $passwordNode->setAttribute('Type', $passType); } $nonceNode = $this->soapDoc->createElementNS(WSSESoap::WSSENS, WSSESoap::WSSEPFX . ':Nonce', base64_encode($nonce)); $token->appendChild($nonceNode); $created = $this->soapDoc->createElementNS(WSSESoap::WSUNS, WSSESoap::WSUPFX . ':Created', $createdate); $token->appendChild($created); }
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(); } }