diff --git a/docs/source/simplesamlphp-idp.xml b/docs/source/simplesamlphp-idp.xml
index 4ae2351b1fb2b6863b599c586e50df208ed2648c..f0a9f8fe24936b5b95695f17c280bc5bfa20dd10 100644
--- a/docs/source/simplesamlphp-idp.xml
+++ b/docs/source/simplesamlphp-idp.xml
@@ -570,6 +570,27 @@ openssl x509 -req -days 60 -in server2.csr -signkey server2.key -out server2.crt
               is <literal>false</literal>.</para>
             </glossdef>
           </glossentry>
+
+          <glossentry>
+            <glossterm>assertion.enctyption</glossterm>
+
+            <glossdef>
+              <para>Boolean, default <literal>false</literal>. Defines whether
+              this IdP shoul encrypt assertions to this SP.</para>
+            </glossdef>
+          </glossentry>
+
+          <glossentry>
+            <glossterm>sharedkey</glossterm>
+
+            <glossdef>
+              <para>Used for optional symmetric encryption of assertions.
+              Currently the algorithm is hardcoded to AES128_CBC/RIJNDAEL_128
+              which uses up to 128 bit for the passphrase/key. If you want to
+              use a sessionkey which is encrypted by this idp's private key do
+              not specify a sharedkey.</para>
+            </glossdef>
+          </glossentry>
         </glosslist>
       </section>
     </section>
diff --git a/docs/source/simplesamlphp-sp.xml b/docs/source/simplesamlphp-sp.xml
index 1552150aa40a9dbab9ecab2af92cb98ecc8d54ea..76d0ccc99ac069ae84686db36a3332cf7c4d507b 100644
--- a/docs/source/simplesamlphp-sp.xml
+++ b/docs/source/simplesamlphp-sp.xml
@@ -447,6 +447,30 @@
               validating signatures.</para>
             </glossdef>
           </glossentry>
+
+          <glossentry>
+            <glossterm>assertion.encryption</glossterm>
+
+            <glossdef>
+              <para>Set to true if the remote idp encrypts assertions.
+              Encrypted assertions are decrypted regardless of the value this
+              field if the neccesary certificate or key is available, but if
+              it is set to true and an unencrypted assertion is recieved an
+              exception is raised.</para>
+            </glossdef>
+          </glossentry>
+
+          <glossentry>
+            <glossterm>sharedkey</glossterm>
+
+            <glossdef>
+              <para>Used for optional symmetric decryption of assertions.
+              Currently the algorithm is hardcoded to AES128_CBC/RIJNDAEL_128
+              which uses up to 128 bit for the passphrase/key. Not necessary
+              if the idp uses a sessionkey which is encrypted by the idp's
+              private key.</para>
+            </glossdef>
+          </glossentry>
         </glosslist>
       </section>
 
diff --git a/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php b/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php
index e79559b959969ef0e1f266fa7692eb28bc93a2b4..21db2627c45fb0aa9efc12556b831bb26cceacf9 100644
--- a/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php
+++ b/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php
@@ -125,11 +125,7 @@ class SimpleSAML_Bindings_SAML20_HTTPPost {
 		
 		/* load the private key from file - last arg is bool if key in file (TRUE) or is string (FALSE) */
 		$objKey->loadKey($privatekey,TRUE);
-		
-		
-		
-		
-		
+				
 		$objXMLSecDSig->sign($objKey);
 		
 		$public_cert = file_get_contents($publiccert);
@@ -146,6 +142,43 @@ class SimpleSAML_Bindings_SAML20_HTTPPost {
 		$objXMLSecDSig->appendSignature($firstassertionroot, true, true);
 		//$objXMLSecDSig->appendSignature($responseroot, true, false);
 		
+		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 (!isset($spmd['certificate'])) {
+					throw new Exception("Public key for encrypting assertion needed, but not specified for saml20-sp-remote id: " . $spentityid);
+				}
+
+				$sp_publiccert = @file_get_contents($this->configuration->getPathValue('certdir') . $spmd['certificate']);
+
+				if ($sp_publiccert === FALSE) {
+					throw new Exception("Public key for encrypting assertion specified but not found for saml20-sp-remote id: " . $spentityid . " Filename: " . $spmd['certificate']);
+				}
+				
+				$keyKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'public'));
+				
+				$keyKey->loadKey($sp_publiccert);
+				
+				$enc->encryptKey($keyKey, $objKey);
+			}
+			$encNode = $enc->encryptNode($objKey); # replacing the unencrypted node
+	
+		}
 		$response = $responsedom->saveXML();
 		
 		
diff --git a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
index d97ee857b844413aa861ac487dd2d5a5eebbe008..76b4669fa505af3be43ab3c7a15a77926070f88e 100644
--- a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
+++ b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
@@ -167,6 +167,68 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 	}
 
 
+	/**
+	* This function decrypts the Assertion in the AuthnResponse
+	* It throws an exception if the encryptAssertion for the remote idp is true and
+	* the assertion is not encrypted
+	* To Do: handle multible assertions
+	*/
+	private function decryptAssertion() {
+
+		$dom = $this->getDOM();
+		$encryptedassertion = $this->doXPathQuery('/samlp:Response/saml:EncryptedAssertion')->item(0);
+		$objenc = new XMLSecEnc();
+		$encData = $objenc->locateEncryptedData($dom);
+		if ($encData) {	
+			$spmd = $this->metadata->getMetaDataCurrent('saml20-sp-hosted');
+			$spid = $this->metadata->getMetaDataCurrentEntityID('saml20-sp-hosted');
+			$objenc->setNode($encData);
+			$objenc->type = $encData->getAttribute("Type");
+
+			$key = NULL;
+			$objKey = $objenc->locateKey($encData);
+			if ($objKey) {
+				if ($objKeyInfo = $objenc->locateKeyInfo($objKey)) {
+					if ($objKeyInfo->isEncrypted) {
+						$objencKey = $objKeyInfo->encryptedCtx;
+						if (!isset($spmd['privatekey'])) {
+							throw new Exception("Private key for decrypting assertion needed, but not specified for saml20-sp-hosted id: " . $spid);
+						}
+						$privatekey = @file_get_contents($this->configuration->getPathValue('certdir') . $spmd['privatekey']);
+						if ($privatekey === FALSE) {
+							throw new Exception("Private key for decrypting assertion specified but not found for saml20-sp-hosted id: " . $spid . " Filename: " . $spmd['privatekey']);
+						}
+						$objKeyInfo->loadKey($privatekey);
+						$key = $objencKey->decryptKey($objKeyInfo);
+					} else {
+						$idpmd = $this->metadata->getMetaData($this->issuer, 'saml20-idp-remote');
+						if (!isset( $idpmd['sharedkey'])) {
+							throw new Exception("Shared key for decrypting assertion needed, but not specified for saml20-idp-remote id: " . $this->issuer);
+						}
+						$key = $idpmd['sharedkey'];
+					}
+				}
+			}
+
+			if (empty($objKey) || empty($key)) {
+				throw new Exception("Error loading key to handle Decryption: >" . var_export($objKey, true));
+			}
+			$objKey->loadkey($key);
+			
+			$decrypted = $objenc->decryptNode($objKey, false);
+	
+			$newdoc = new DOMDocument();
+			$newdoc->loadXML('<root xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'.$decrypted.'</root>');
+			$importEnc = $encData->ownerDocument->importNode($newdoc->documentElement->firstChild, TRUE);
+			$encryptedassertion->parentNode->replaceChild($importEnc, $encryptedassertion);
+		} else {
+			$md = $this->metadata->getMetaData($this->issuer, 'saml20-idp-remote');
+			if (isset($md['assertion.encryption']) && $md['assertion.encryption']) {
+				throw new Exception('Received unencrypted assertion from [' . $this->issuer . '] contrary to its metadata attribute [assertion.encryption]: ' . $md['assertion.encryption']);
+			}
+		}
+	}
+
 	/**
 	 * This function validates the signature element of this response. It will throw an exception
 	 * if it is unable to validate the signature.
@@ -180,7 +242,7 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 
 		$publickey = FALSE;
 		if (isset($md['certificate'])) {
-			$publickey = file_get_contents($this->configuration->getPathValue('certdir') . $md['certificate']);
+			$publickey = @file_get_contents($this->configuration->getPathValue('certdir') . $md['certificate']);
 			if (!$publickey) {
 				throw new Exception("Optional saml20-idp-remote metadata 'certificate' set, but no certificate found");			
 			}
@@ -408,6 +470,8 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 		/* Find the issuer of this response. */
 		$this->issuer = $this->findIssuer();
 
+		$this->decryptAssertion();
+
 		/* Validate the signature element. */
 		$this->validateSignature();
 
@@ -531,6 +595,8 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 		$authnResponse = '<samlp:Response 
 			xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
 			xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
+			xmlns:xs="http://www.w3.org/2001/XMLSchema"
+			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 			ID="' . $id . '"
 			InResponseTo="' . htmlspecialchars($inresponseto) . '" Version="2.0"
 			IssueInstant="' . $issueInstant . '"
@@ -606,7 +672,7 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 	private static function enc_attribute($name, $values, $base64 = false) {
 		assert(is_array($values));
 
-		$ret = '<saml:Attribute Name="' . htmlspecialchars($name) . '">';
+		$ret = '<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"  Name="' . htmlspecialchars($name) . '">';
 
 		foreach($values as $value) {
 			if($base64) {
@@ -615,7 +681,7 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 				$text = htmlspecialchars($value);
 			}
 
-			$ret .= '<saml:AttributeValue xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">' .
+			$ret .= '<saml:AttributeValue xsi:type="xs:string">' .
 			        $text . '</saml:AttributeValue>';
 		}
 
diff --git a/lib/xmlseclibs.php b/lib/xmlseclibs.php
index 7e65d0be81c7599a5bc83492f2b9ba17cd475c99..6892306eb09a0295cf9c979f56ae194cff9483e9 100644
--- a/lib/xmlseclibs.php
+++ b/lib/xmlseclibs.php
@@ -258,6 +258,7 @@ class XMLSecurityKey {
             case (XMLSecurityKey::RSA_SHA1):
                 $this->cryptParams['library'] = 'openssl';
                 $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
+                $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
                 if (is_array($params) && ! empty($params['type'])) {
                     if ($params['type'] == 'public' || $params['type'] == 'private') {
                         $this->cryptParams['type'] = $params['type'];
@@ -415,7 +416,7 @@ class XMLSecurityKey {
     private function encryptOpenSSL($data) {
         if ($this->cryptParams['type'] == 'public') {
             if (! openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
-                throw new Exception('Failure encrypting Data');
+                throw new Exception('Failure encrypting Data ' . openssl_error_string() . "###" . $this->key);
                 return;
             }
         } else {
@@ -435,7 +436,7 @@ class XMLSecurityKey {
             }
         } else {
             if (! openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
-                throw new Exception('Failure decrypting Data');
+                throw new Exception('Failure decrypting Data' . openssl_error_string() . "###" . $this->key);
                 return;
             }
         }
diff --git a/www/admin/metadata.php b/www/admin/metadata.php
index 1070a3e22e1a22a11fb84cc23e665727866e0757..c690214458f5f251a20e286cca54ef2e8ec8b67a 100644
--- a/www/admin/metadata.php
+++ b/www/admin/metadata.php
@@ -44,7 +44,7 @@ try {
 		foreach ($metalist AS $entityid => $mentry) {
 			$results[$entityid] = SimpleSAML_Utilities::checkAssocArrayRules($mentry,
 				array('entityid', 'SingleSignOnService', 'SingleLogoutService', 'certFingerprint'),
-				array('name', 'description', 'base64attributes', 'certificate', 'hint.cidr', 'saml2.relaxvalidation', 'SingleLogoutServiceResponse', 'request.signing', 'attributemap', 'attributealter')
+				array('name', 'description', 'base64attributes', 'certificate', 'hint.cidr', 'saml2.relaxvalidation', 'SingleLogoutServiceResponse', 'request.signing', 'attributemap', 'attributealter', 'sharedkey', 'assertion.encryption')
 			);
 		}
 		$et->data['metadata.saml20-idp-remote'] = $results;
@@ -67,7 +67,7 @@ try {
 		foreach ($metalist AS $entityid => $mentry) {
 			$results[$entityid] = SimpleSAML_Utilities::checkAssocArrayRules($mentry,
 				array('entityid', 'AssertionConsumerService'),
-				array('SingleLogoutService', 'NameIDFormat', 'SPNameQualifier', 'base64attributes', 'simplesaml.nameidattribute', 'attributemap', 'attributealter', 'simplesaml.attributes', 'attributes', 'name', 'description','request.signing','certificate', 'ForceAuthn')
+				array('SingleLogoutService', 'NameIDFormat', 'SPNameQualifier', 'base64attributes', 'simplesaml.nameidattribute', 'attributemap', 'attributealter', 'simplesaml.attributes', 'attributes', 'name', 'description','request.signing','certificate', 'ForceAuthn', 'sharedkey', 'assertion.encryption')
 			);
 		}
 		$et->data['metadata.saml20-sp-remote'] = $results;