diff --git a/lib/SAML2/Utils.php b/lib/SAML2/Utils.php
index fe83f12ab607ef60b74a5e4994cae50f704edc9c..156ab941eb82f2c1dd15215ee2bd890500a6d644 100644
--- a/lib/SAML2/Utils.php
+++ b/lib/SAML2/Utils.php
@@ -239,6 +239,89 @@ class SAML2_Utils {
 		$objXMLSecDSig->insertSignature($root, $insertBefore);
 
 	}
+
+
+	/**
+	 * Decrypt an encrypted element.
+	 *
+	 * @param DOMElement $encryptedData  The encrypted data.
+	 * @param XMLSecurityKey $inputKey  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->getAlgorith();
+		if ($symmetricKeyInfo->isEncrypted) {
+			$symKeyInfoAlgo = $symmetricKeyInfo->getAlgorith();
+
+			if ($symKeyInfoAlgo === XMLSecurityKey::RSA_OAEP_MGF1P && $inputKeyAlgo === XMLSecurityKey::RSA_1_5) {
+				/*
+				 * The RSA key formats are equal, so loading an RSA_1_5 key
+				 * into an RSA_OAEP_MGF1P key can be done without problems.
+				 * We therefore pretend that the input key is an
+				 * RSA_OAEP_MGF1P key.
+				 */
+				$inputKeyAlgo = XMLSecurityKey::RSA_OAEP_MGF1P;
+			}
+
+			/* Make sure that the input key format is the same as the one used to encrypt the key. */
+			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;
+			$key = $encKey->decryptKey($symmetricKeyInfo);
+			$symmetricKey->loadkey($key);
+		} else {
+			$symKeyAlgo = $symmetricKey->getAlgorith();
+			/* Make sure that the input key has the correct format. */
+			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);
+
+		/*
+		 * This is a workaround for the case where only a subset of the XML
+		 * tree was serialized for encryption. In that case, we may miss the
+		 * namespaces needed to parse the XML.
+		 */
+		$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();
+		if (!$newDoc->loadXML($xml)) {
+			throw new Exception('Failed to parse decrypted XML. Maybe the wrong sharedkey was used?');
+		}
+		$decryptedElement = $newDoc->firstChild->firstChild;
+		if ($decryptedElement === NULL) {
+			throw new Exception('Missing encrypted element.');
+		}
+
+		return $decryptedElement;
+	}
+
 }
 
 ?>
\ No newline at end of file