diff --git a/lib/SAML2/Assertion.php b/lib/SAML2/Assertion.php
index 076000fd06fcc2aa7890a7eaf7e11e2f7f70bbbf..eece94e94007103a256b705b8de4412de442b9b1 100644
--- a/lib/SAML2/Assertion.php
+++ b/lib/SAML2/Assertion.php
@@ -42,6 +42,16 @@ class SAML2_Assertion implements SAML2_SignedElement {
 	private $nameId;
 
 
+	/**
+	 * The encrypted NameId of the subject.
+	 *
+	 * If this is not NULL, the NameId needs decryption before it can be accessed.
+	 *
+	 * @var DOMElement|NULL
+	 */
+	private $encryptedNameId;
+
+
 	/**
 	 * The earliest time this assertion is valid, as an UNIX timestamp.
 	 *
@@ -220,14 +230,19 @@ class SAML2_Assertion implements SAML2_SignedElement {
 		}
 		$subject = $subject[0];
 
-		$nameId = SAML2_Utils::xpQuery($subject, './saml_assertion:NameID');
+		$nameId = SAML2_Utils::xpQuery($subject, './saml_assertion:NameID | ./saml_assertion:EncryptedID/xenc:EncryptedData');
 		if (empty($nameId)) {
-			throw new Exception('Missing <saml:NameID> in <saml:Subject>.');
+			throw new Exception('Missing <saml:NameID> or <saml:EncryptedID> in <saml:Subject>.');
 		} elseif (count($nameId) > 1) {
-			throw new Exception('More than one <saml:NameID> in <saml:Subject>.');
+			throw new Exception('More than one <saml:NameID> or <saml:EncryptedD> in <saml:Subject>.');
 		}
 		$nameId = $nameId[0];
-		$this->nameId = SAML2_Utils::parseNameId($nameId);
+		if ($nameId->localName === 'EncryptedData') {
+			/* The NameID element is encrypted. */
+			$this->encryptedNameId = $nameId;
+		} else {
+			$this->nameId = SAML2_Utils::parseNameId($nameId);
+		}
 
 		$subjectConfirmation = SAML2_Utils::xpQuery($subject, './saml_assertion:SubjectConfirmation');
 		if (empty($subjectConfirmation)) {
@@ -553,6 +568,11 @@ class SAML2_Assertion implements SAML2_SignedElement {
 	 * @return array|NULL  The name identifier of the assertion.
 	 */
 	public function getNameId() {
+
+		if ($this->encryptedNameId !== NULL) {
+			throw new Exception('Attempted to retrieve encrypted NameID without decrypting it first.');
+		}
+
 		return $this->nameId;
 	}
 
@@ -572,6 +592,40 @@ class SAML2_Assertion implements SAML2_SignedElement {
 	}
 
 
+	/**
+	 * Check whether the NameId is encrypted.
+	 *
+	 * @return TRUE if the NameId is encrypted, FALSE if not.
+	 */
+	public function isNameIdEncrypted() {
+
+		if ($this->encryptedNameId !== NULL) {
+			return TRUE;
+		}
+
+		return FALSE;
+	}
+
+
+	/**
+	 * Decrypt the NameId of the subject in the assertion.
+	 *
+	 * @param XMLSecurityKey $key  The decryption key.
+	 */
+	public function decryptNameId(XMLSecurityKey $key) {
+
+		if ($this->encryptedNameId === NULL) {
+			/* No NameID to decrypt. */
+			return;
+		}
+
+		$nameId = SAML2_Utils::decryptElement($this->encryptedNameId, $key);
+		$this->nameId = SAML2_Utils::parseNameId($nameId);
+
+		$this->encryptedNameId = NULL;
+	}
+
+
 	/**
 	 * Retrieve the earliest timestamp this assertion is valid.
 	 *