OneLogin_Saml2_Utils::decryptElement PHP Method

decryptElement() public static method

Decrypts an encrypted element.
public static decryptElement ( DOMElement $encryptedData, XMLSecurityKey $inputKey ) : DOMElement
$encryptedData DOMElement The encrypted data.
$inputKey XMLSecurityKey The decryption key.
return DOMElement The decrypted element.
    public static function decryptElement(DOMElement $encryptedData, XMLSecurityKey $inputKey)
    {
        $enc = new XMLSecEnc();
        $enc->setNode($encryptedData);
        $enc->type = $encryptedData->getAttribute("Type");
        $symmetricKey = $enc->locateKey($encryptedData);
        if (!$symmetricKey) {
            throw new Exception('Could not locate key algorithm in encrypted data.');
        }
        $symmetricKeyInfo = $enc->locateKeyInfo($symmetricKey);
        if (!$symmetricKeyInfo) {
            throw new Exception('Could not locate <dsig:KeyInfo> for the encrypted key.');
        }
        $inputKeyAlgo = $inputKey->getAlgorithm();
        if ($symmetricKeyInfo->isEncrypted) {
            $symKeyInfoAlgo = $symmetricKeyInfo->getAlgorithm();
            if ($symKeyInfoAlgo === XMLSecurityKey::RSA_OAEP_MGF1P && $inputKeyAlgo === XMLSecurityKey::RSA_1_5) {
                $inputKeyAlgo = XMLSecurityKey::RSA_OAEP_MGF1P;
            }
            if ($inputKeyAlgo !== $symKeyInfoAlgo) {
                throw new Exception('Algorithm mismatch between input key and key used to encrypt ' . ' the symmetric key for the message. Key was: ' . var_export($inputKeyAlgo, true) . '; message was: ' . var_export($symKeyInfoAlgo, true));
            }
            $encKey = $symmetricKeyInfo->encryptedCtx;
            $symmetricKeyInfo->key = $inputKey->key;
            $keySize = $symmetricKey->getSymmetricKeySize();
            if ($keySize === null) {
                // To protect against "key oracle" attacks
                throw new Exception('Unknown key size for encryption algorithm: ' . var_export($symmetricKey->type, true));
            }
            $key = $encKey->decryptKey($symmetricKeyInfo);
            if (strlen($key) != $keySize) {
                $encryptedKey = $encKey->getCipherValue();
                $pkey = openssl_pkey_get_details($symmetricKeyInfo->key);
                $pkey = sha1(serialize($pkey), true);
                $key = sha1($encryptedKey . $pkey, true);
                /* Make sure that the key has the correct length. */
                if (strlen($key) > $keySize) {
                    $key = substr($key, 0, $keySize);
                } elseif (strlen($key) < $keySize) {
                    $key = str_pad($key, $keySize);
                }
            }
            $symmetricKey->loadkey($key);
        } else {
            $symKeyAlgo = $symmetricKey->getAlgorithm();
            if ($inputKeyAlgo !== $symKeyAlgo) {
                throw new Exception('Algorithm mismatch between input key and key in message. ' . 'Key was: ' . var_export($inputKeyAlgo, true) . '; message was: ' . var_export($symKeyAlgo, true));
            }
            $symmetricKey = $inputKey;
        }
        $decrypted = $enc->decryptNode($symmetricKey, false);
        $xml = '<root xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' . $decrypted . '</root>';
        $newDoc = new DOMDocument();
        $newDoc->preserveWhiteSpace = false;
        $newDoc->formatOutput = true;
        $newDoc = self::loadXML($newDoc, $xml);
        if (!$newDoc) {
            throw new Exception('Failed to parse decrypted XML.');
        }
        $decryptedElement = $newDoc->firstChild->firstChild;
        if ($decryptedElement === null) {
            throw new Exception('Missing encrypted element.');
        }
        return $decryptedElement;
    }

Usage Example

Example #1
0
 /**
  * Tests the decryptElement method of the OneLogin_Saml2_Utils
  *
  * @covers OneLogin_Saml2_Utils::decryptElement
  */
 public function testDecryptElement()
 {
     $settingsDir = TEST_ROOT . '/settings/';
     include $settingsDir . 'settings1.php';
     $settings = new OneLogin_Saml2_Settings($settingsInfo);
     $key = $settings->getSPkey();
     $seckey = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, array('type' => 'private'));
     $seckey->loadKey($key);
     $xmlNameIdEnc = base64_decode(file_get_contents(TEST_ROOT . '/data/responses/response_encrypted_nameid.xml.base64'));
     $domNameIdEnc = new DOMDocument();
     $domNameIdEnc->loadXML($xmlNameIdEnc);
     $encryptedNameIDNodes = $domNameIdEnc->getElementsByTagName('EncryptedID');
     $encryptedData = $encryptedNameIDNodes->item(0)->firstChild;
     $decryptedNameId = OneLogin_Saml2_Utils::decryptElement($encryptedData, $seckey);
     $this->assertEquals('saml:NameID', $decryptedNameId->tagName);
     $this->assertEquals('2de11defd199f8d5bb63f9b7deb265ba5c675c10', $decryptedNameId->nodeValue);
     $xmlAsssertionEnc = base64_decode(file_get_contents(TEST_ROOT . '/data/responses/valid_encrypted_assertion.xml.base64'));
     $domAsssertionEnc = new DOMDocument();
     $domAsssertionEnc->loadXML($xmlAsssertionEnc);
     $encryptedAssertionEncNodes = $domAsssertionEnc->getElementsByTagName('EncryptedAssertion');
     $encryptedAssertionEncNode = $encryptedAssertionEncNodes->item(0);
     $encryptedDataAssertNodes = $encryptedAssertionEncNode->getElementsByTagName('EncryptedData');
     $encryptedDataAssert = $encryptedDataAssertNodes->item(0);
     $decryptedAssertion = OneLogin_Saml2_Utils::decryptElement($encryptedDataAssert, $seckey);
     $this->assertEquals('saml:Assertion', $decryptedAssertion->tagName);
     try {
         $res = OneLogin_Saml2_Utils::decryptElement($encryptedNameIDNodes->item(0), $seckey);
         $this->assertTrue(false);
     } catch (Exception $e) {
         $this->assertContains('Algorithm mismatch between input key and key in message', $e->getMessage());
     }
     $key2 = file_get_contents(TEST_ROOT . '/data/misc/sp2.key');
     $seckey2 = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, array('type' => 'private'));
     $seckey2->loadKey($key2);
     $decryptedNameId2 = OneLogin_Saml2_Utils::decryptElement($encryptedData, $seckey2);
     $this->assertEquals('saml:NameID', $decryptedNameId2->tagName);
     $this->assertEquals('2de11defd199f8d5bb63f9b7deb265ba5c675c10', $decryptedNameId2->nodeValue);
     $key3 = file_get_contents(TEST_ROOT . '/data/misc/sp2.key');
     $seckey3 = new XMLSecurityKey(XMLSecurityKey::RSA_SHA512, array('type' => 'private'));
     $seckey3->loadKey($key3);
     try {
         $res = OneLogin_Saml2_Utils::decryptElement($encryptedData, $seckey3);
         $this->assertTrue(false);
     } catch (Exception $e) {
         $this->assertContains('Algorithm mismatch between input key and key used to encrypt  the symmetric key for the message', $e->getMessage());
     }
     $xmlNameIdEnc2 = base64_decode(file_get_contents(TEST_ROOT . '/data/responses/invalids/encrypted_nameID_without_EncMethod.xml.base64'));
     $domNameIdEnc2 = new DOMDocument();
     $domNameIdEnc2->loadXML($xmlNameIdEnc2);
     $encryptedNameIDNodes2 = $domNameIdEnc2->getElementsByTagName('EncryptedID');
     $encryptedData2 = $encryptedNameIDNodes2->item(0)->firstChild;
     try {
         $res = OneLogin_Saml2_Utils::decryptElement($encryptedData2, $seckey);
         $this->assertTrue(false);
     } catch (Exception $e) {
         $this->assertContains('Unable to locate algorithm for this Encrypted Key', $e->getMessage());
     }
     $xmlNameIdEnc3 = base64_decode(file_get_contents(TEST_ROOT . '/data/responses/invalids/encrypted_nameID_without_keyinfo.xml.base64'));
     $domNameIdEnc3 = new DOMDocument();
     $domNameIdEnc3->loadXML($xmlNameIdEnc3);
     $encryptedNameIDNodes3 = $domNameIdEnc3->getElementsByTagName('EncryptedID');
     $encryptedData3 = $encryptedNameIDNodes3->item(0)->firstChild;
     try {
         $res = OneLogin_Saml2_Utils::decryptElement($encryptedData3, $seckey);
         $this->assertTrue(false);
     } catch (Exception $e) {
         $this->assertContains('Algorithm mismatch between input key and key in message', $e->getMessage());
     }
 }
All Usage Examples Of OneLogin_Saml2_Utils::decryptElement