diff --git a/bin/parseMetadata.php b/bin/parseMetadata.php
index d21ae978a7ee3031832d417565ebf978624b6ab6..d74511a94bc6e1367fde2b17644117ba80638698 100755
--- a/bin/parseMetadata.php
+++ b/bin/parseMetadata.php
@@ -130,7 +130,9 @@ function processFile($filename) {
 
 	foreach($entities as $entity) {
 		addMetadata($filename, $entity->getMetadata1xSP(), 'shib13-sp-remote');
+		addMetadata($filename, $entity->getMetadata1xIdP(), 'shib13-idp-remote');
 		addMetadata($filename, $entity->getMetadata20SP(), 'saml20-sp-remote');
+		addMetadata($filename, $entity->getMetadata20IdP(), 'saml20-idp-remote');
 	}
 }
 
diff --git a/lib/SimpleSAML/Metadata/SAMLParser.php b/lib/SimpleSAML/Metadata/SAMLParser.php
index 8056490d0cc4ff57293d1e4aa8a4f07e4c60f43a..898d1284ecf636170fe50b5a47c9603dc5949362 100644
--- a/lib/SimpleSAML/Metadata/SAMLParser.php
+++ b/lib/SimpleSAML/Metadata/SAMLParser.php
@@ -32,6 +32,11 @@ class SimpleSAML_Metadata_SAMLParser {
 		);
 
 
+	/**
+	 * This is the binding used to send authentication requests in SAML 1.x.
+	 */
+	const SAML_1x_AUTHN_REQUEST = 'urn:mace:shibboleth:1.0:profiles:AuthnRequest';
+
 	/**
 	 * This is the binding used for browser post in SAML 1.x.
 	 */
@@ -59,18 +64,22 @@ class SimpleSAML_Metadata_SAMLParser {
 	/**
 	 * This is an array with the processed SPSSODescriptor elements we have found in this
 	 * metadata file.
-	 * Each element in the array is an associative array with the following elements:
-	 * - 'protocols': Array with the protocols this SPSSODescriptor supports.
+	 * Each element in the array is an associative array with the elements from parseSSODescriptor and:
 	 * - 'assertionConsumerServices': Array with the SP's assertion consumer services.
 	 *   Each assertion consumer service is stored as an associative array with the
 	 *   elements that parseGenericEndpoint returns.
-	 * - 'singleLogoutServices': Array with the SP's single logout service endpoints. Each endpoint is stored
-	 *   as an associative array with the elements that parseGenericEndpoint returns.
-	 * - 'nameIDFormats': The NameIDFormats that the SP accepts. This may be an empty array.
 	 */
 	private $spDescriptors;
 
 
+	/**
+	 * This is an array with the processed IDPSSODescriptor elements we have found.
+	 * Each element in the array is an associative array with the elements from parseSSODescriptor and:
+	 * - 'singleSignOnServices': Array with the IdP's single signon service endpoints. Each endpoint is stored
+	 *   as an associative array with the elements that parseGenericEndpoint returns.
+	 */
+	private $idpDescriptors;
+
 
 	/**
 	 * This is the constructor for the SAMLParser class.
@@ -79,6 +88,7 @@ class SimpleSAML_Metadata_SAMLParser {
 	 */
 	private function __construct($entityElement) {
 		$this->spDescriptors = array();
+		$this->idpDescriptors = array();
 
 
 		assert('$entityElement instanceof DOMElement');
@@ -104,6 +114,10 @@ class SimpleSAML_Metadata_SAMLParser {
 			if(SimpleSAML_Utilities::isDOMElementOfType($child, 'SPSSODescriptor', '@md') === TRUE) {
 				$this->processSPSSODescriptor($child);
 			}
+
+			if(SimpleSAML_Utilities::isDOMElementOfType($child, 'IDPSSODescriptor', '@md') === TRUE) {
+				$this->processIDPSSODescriptor($child);
+			}
 		}
 	}
 
@@ -290,6 +304,62 @@ class SimpleSAML_Metadata_SAMLParser {
 	}
 
 
+	/**
+	 * This function returns the metadata for SAML 2.0 IdPs in the format simpleSAMLphp expects.
+	 * This is an associative array with the following fields:
+	 * - 'entityID': The entity id of the entity described in the metadata.
+	 * - 'name': Autogenerated name for this entity. Currently set to the entityID.
+	 * - 'SingleSignOnService': String with the url of the SSO service which supports the redirect binding.
+	 * - 'SingleLogoutService': String with the url where we should send logout requests/responses.
+	 * - 'certFingerprint': Fingerprint of the X509Certificate from the metadata.
+	 *
+	 * Metadata must be loaded with one of the parse functions before this function can be called.
+	 *
+	 * @return Associative array with metadata or NULL if we are unable to generate metadata for a SAML 1.x IdP.
+	 */
+	public function getMetadata1xIdP() {
+
+		$ret = array();
+
+		$ret['entityID'] = $this->entityID;
+
+		$ret['name'] = $this->entityID;
+
+		/* Find IdP information which supports the SAML 1.x protocol. */
+		$idp = $this->getIdPDescriptors(self::$SAML1xProtocols);
+		if(count($idp) === 0) {
+			return NULL;
+		}
+
+		/* We currently only look at the first IDP descriptor which supports SAML 1.x. */
+		$idp = $idp[0];
+
+		/* Find the SSO service endpoint. */
+		$sso = $this->getDefaultEndpoint($idp['singleSignOnServices'], array(self::SAML_1x_AUTHN_REQUEST));
+		if($sso === NULL) {
+			throw new Exception('Could not find any valid SingleSignOnService endpoint.');
+		}
+		$ret['SingleSignOnService'] = $sso['location'];
+
+		/* Find the certificate fingerprint. */
+		foreach($idp['keys'] as $key) {
+			if($key['type'] !== 'X509Certificate') {
+				continue;
+			}
+
+			$certData = base64_decode($key['X509Certificate']);
+			if($certData === FALSE) {
+				throw new Exception('Unable to parse base64 encoded certificate data.');
+			}
+
+			$ret['certFingerprint'] = sha1($certData);
+			break;
+		}
+
+		return $ret;
+	}
+
+
 	/**
 	 * This function returns the metadata for SAML 2.0 SPs in the format simpleSAMLphp expects.
 	 * This is an associative array with the following fields:
@@ -301,7 +371,7 @@ class SimpleSAML_Metadata_SAMLParser {
 	 *
 	 * Metadata must be loaded with one of the parse functions before this function can be called.
 	 *
-	 * @return Associative array with metadata or NULL if we are unable to generate metadata for a SAML 1.x SP.
+	 * @return Associative array with metadata or NULL if we are unable to generate metadata for a SAML 2.x SP.
 	 */
 	public function getMetadata20SP() {
 
@@ -330,13 +400,13 @@ class SimpleSAML_Metadata_SAMLParser {
 
 
 		/* Find the single logout service endpoint. */
-		$acs = $this->getDefaultEndpoint($spd['singleLogoutServices'], array(self::SAML_20_REDIRECT_BINDING));
-		if($acs === NULL) {
+		$slo = $this->getDefaultEndpoint($spd['singleLogoutServices'], array(self::SAML_20_REDIRECT_BINDING));
+		if($slo === NULL) {
 			throw new Exception('Could not find any valid SingleLogoutService.' .
-				' simpleSAMLphp currently supports only the http-redirect binding for SAML 1.0 logout.');
+				' simpleSAMLphp currently supports only the http-redirect binding for SAML 2.0 logout.');
 		}
 
-		$ret['SingleLogoutService'] = $acs['location'];
+		$ret['SingleLogoutService'] = $slo['location'];
 
 
 		/* Find the NameIDFormat. This may not exists. */
@@ -350,36 +420,136 @@ class SimpleSAML_Metadata_SAMLParser {
 
 
 	/**
-	 * This function extracts metadata from a SPSSODescriptor element.
+	 * This function returns the metadata for SAML 2.0 IdPs in the format simpleSAMLphp expects.
+	 * This is an associative array with the following fields:
+	 * - 'entityID': The entity id of the entity described in the metadata.
+	 * - 'name': Autogenerated name for this entity. Currently set to the entityID.
+	 * - 'SingleSignOnService': String with the url of the SSO service which supports the redirect binding.
+	 * - 'SingleLogoutService': String with the url where we should send logout requests/responses.
+	 * - 'certFingerprint': Fingerprint of the X509Certificate from the metadata.
 	 *
-	 * @param $element The element which should be parsed.
+	 * Metadata must be loaded with one of the parse functions before this function can be called.
+	 *
+	 * @return Associative array with metadata or NULL if we are unable to generate metadata for a SAML 2.0 IdP.
 	 */
-	private function processSPSSODescriptor($element) {
-		assert('$element instanceof DOMElement');
+	public function getMetadata20IdP() {
 
-		$sp = array();
+		$ret = array();
 
-		$sp['protocols'] = self::getSupportedProtocols($element);
+		$ret['entityID'] = $this->entityID;
 
-		/* Find all AssertionConsumerService elements. */
-		$sp['assertionConsumerServices'] = array();
-		$acs = SimpleSAML_Utilities::getDOMChildren($element, 'AssertionConsumerService', '@md');
-		foreach($acs as $child) {
-			$sp['assertionConsumerServices'][] = self::parseAssertionConsumerService($child);
+		$ret['name'] = $this->entityID;
+
+		/* Find IdP information which supports the SAML 2.0 protocol. */
+		$idp = $this->getIdPDescriptors(self::$SAML20Protocols);
+		if(count($idp) === 0) {
+			return NULL;
+		}
+
+		/* We currently only look at the first IDP descriptor which supports SAML 2.0. */
+		$idp = $idp[0];
+
+		/* Find the SSO service endpoint. */
+		$sso = $this->getDefaultEndpoint($idp['singleSignOnServices'], array(self::SAML_20_REDIRECT_BINDING));
+		if($sso === NULL) {
+			throw new Exception('Could not find any valid SingleSignOnService endpoint.');
+		}
+		$ret['SingleSignOnService'] = $sso['location'];
+
+
+		/* Find the single logout service endpoint. */
+		$slo = $this->getDefaultEndpoint($idp['singleLogoutServices'], array(self::SAML_20_REDIRECT_BINDING));
+		if($slo === NULL) {
+			throw new Exception('Could not find any valid SingleLogoutService.' .
+				' simpleSAMLphp currently supports only the http-redirect binding for SAML 2.0 logout.');
 		}
+		$ret['SingleLogoutService'] = $slo['location'];
+
+
+		/* Find the certificate fingerprint. */
+		foreach($idp['keys'] as $key) {
+			if($key['type'] !== 'X509Certificate') {
+				continue;
+			}
+
+			$certData = base64_decode($key['X509Certificate']);
+			if($certData === FALSE) {
+				throw new Exception('Unable to parse base64 encoded certificate data.');
+			}
+
+			$ret['certFingerprint'] = sha1($certData);
+			break;
+		}
+
+		return $ret;
+	}
+
+
+	/**
+	 * This function extracts metadata from a SSODescriptor element.
+	 *
+	 * The returned associative array has the following elements:
+	 * - 'protocols': Array with the protocols this SSODescriptor supports.
+	 * - 'singleLogoutServices': Array with the single logout service endpoints. Each endpoint is stored
+	 *   as an associative array with the elements that parseGenericEndpoint returns.
+	 * - 'nameIDFormats': The NameIDFormats supported by this SSODescriptor. This may be an empty array.
+	 * - 'keys': Array of associative arrays with the elements from parseKeyDescriptor:
+	 *
+	 * @param $element The element we should extract metadata from.
+	 * @return Associative array with metadata we have extracted from this element.
+	 */
+	private static function parseSSODescriptor($element) {
+
+		assert('$element instanceof DOMElement');
+
+		$sd = array();
+
+		$sd['protocols'] = self::getSupportedProtocols($element);
 
 		/* Find all SingleLogoutService elements. */
-		$sp['singleLogoutServices'] = array();
+		$sd['singleLogoutServices'] = array();
 		$sls = SimpleSAML_Utilities::getDOMChildren($element, 'SingleLogoutService', '@md');
 		foreach($sls as $child) {
-			$sp['singleLogoutServices'][] = self::parseSingleLogoutService($child);
+			$sd['singleLogoutServices'][] = self::parseSingleLogoutService($child);
 		}
 
 		/* Process NameIDFormat elements. */
-		$sp['nameIDFormats'] = array();
+		$sd['nameIDFormats'] = array();
 		$nif = SimpleSAML_Utilities::getDOMChildren($element, 'NameIDFormat', '@md');
 		if(count($nif) > 0) {
-			$sp['nameIDFormats'][] = self::parseNameIDFormat($nif[0]);
+			$sd['nameIDFormats'][] = self::parseNameIDFormat($nif[0]);
+		}
+
+		/* Process KeyDescriptor elements. */
+		$sd['keys'] = array();
+		$keys = SimpleSAML_Utilities::getDOMChildren($element, 'KeyDescriptor', '@md');
+		foreach($keys as $kd) {
+			$key = self::parseKeyDescriptor($kd);
+			if($key !== NULL) {
+				$sd['keys'][] = $key;
+			}
+		}
+
+
+		return $sd;
+	}
+
+
+	/**
+	 * This function extracts metadata from a SPSSODescriptor element.
+	 *
+	 * @param $element The element which should be parsed.
+	 */
+	private function processSPSSODescriptor($element) {
+		assert('$element instanceof DOMElement');
+
+		$sp = self::parseSSODescriptor($element);
+
+		/* Find all AssertionConsumerService elements. */
+		$sp['assertionConsumerServices'] = array();
+		$acs = SimpleSAML_Utilities::getDOMChildren($element, 'AssertionConsumerService', '@md');
+		foreach($acs as $child) {
+			$sp['assertionConsumerServices'][] = self::parseAssertionConsumerService($child);
 		}
 
 
@@ -387,6 +557,28 @@ class SimpleSAML_Metadata_SAMLParser {
 	}
 
 
+	/**
+	 * This function extracts metadata from a IDPSSODescriptor element.
+	 *
+	 * @param $element The element which should be parsed.
+	 */
+	private function processIDPSSODescriptor($element) {
+		assert('$element instanceof DOMElement');
+
+		$idp = self::parseSSODescriptor($element);
+
+		/* Find all SingleSignOnService elements. */
+		$idp['singleSignOnServices'] = array();
+		$acs = SimpleSAML_Utilities::getDOMChildren($element, 'SingleSignOnService', '@md');
+		foreach($acs as $child) {
+			$idp['singleSignOnServices'][] = self::parseSingleSignOnService($child);
+		}
+
+
+		$this->idpDescriptors[] = $idp;
+	}
+
+
 	/**
 	 * This function parses AssertionConsumerService elements.
 	 *
@@ -414,27 +606,28 @@ class SimpleSAML_Metadata_SAMLParser {
 
 
 	/**
-	 * This function parses NameIDFormat elements.
+	 * This function parses SingleSignOnService elements.
 	 *
 	 * @param $element The element which should be parsed.
-	 * @return URN with the supported NameIDFormat.
+	 * @return Associative array with the data we have extracted from the SingleLogoutService element.
 	 */
-	private static function parseNameIDFormat($element) {
+	private static function parseSingleSignOnService($element) {
 		assert('$element instanceof DOMElement');
 
-		$fmt = '';
+		return self::parseGenericEndpoint($element, FALSE);
+	}
 
-		for($i = 0; $i < $element->childNodes->length; $i++) {
-			$child = $element->childNodes->item($i);
-			if(!($child instanceof DOMText)) {
-				throw new Exception('NameIDFormat contained a non-text child node.');
-			}
 
-			$fmt .= $child->wholeText;
-		}
+	/**
+	 * This function parses NameIDFormat elements.
+	 *
+	 * @param $element The element which should be parsed.
+	 * @return URN with the supported NameIDFormat.
+	 */
+	private static function parseNameIDFormat($element) {
+		assert('$element instanceof DOMElement');
 
-		$fmt = trim($fmt);
-		return $fmt;
+		return SimpleSAML_Utilities::getDOMText($element);
 	}
 
 
@@ -497,6 +690,65 @@ class SimpleSAML_Metadata_SAMLParser {
 	}
 
 
+	/**
+	 * This function parses a KeyDescriptor element. It currently only supports keys with a single
+	 * X509 certificate.
+	 *
+	 * The associative array for a key can contain:
+	 * - 'encryption': Indicates wheter this key can be used for encryption.
+	 * - 'signing': Indicates wheter this key can be used for signing.
+	 * - 'type: The type of the key. 'X509Certificate' is the only key type we support.
+	 * - 'X509Certificate': The contents of the first X509Certificate element (if the type is 'X509Certificate ').
+	 *
+	 * @param $kd  The KeyDescriptor element.
+	 * @return Associative array describing the key, or NULL if this is an unsupported key.
+	 */
+	private static function parseKeyDescriptor($kd) {
+		assert('$kd instanceof DOMElement');
+
+		$r = array();
+
+		if($kd->hasAttribute('use')) {
+			$use = $kd->getAttribute('use');
+			if($use === 'encryption') {
+				$r['encryption'] = TRUE;
+				$r['signing'] = FALSE;
+			} elseif($use === 'signing') {
+				$r['encryption'] = FALSE;
+				$r['signing'] = TRUE;
+			} else {
+				throw new Exception('Invalid use-value for KeyDescriptor: ' . $use);
+			}
+		} else {
+			$r['encryption'] = TRUE;
+			$r['signing'] = TRUE;
+		}
+
+		$keyInfo = SimpleSAML_Utilities::getDOMChildren($kd, 'KeyInfo', '@ds');
+		if(count($keyInfo) === 0) {
+			throw new Exception('Missing required KeyInfo field for KeyDescriptor.');
+		}
+		$keyInfo = $keyInfo[0];
+
+		$X509Data = SimpleSAML_Utilities::getDOMChildren($keyInfo, 'X509Data', '@ds');
+		if(count($X509Data) === 0) {
+			return NULL;
+		}
+		$X509Data = $X509Data[0];
+
+		$X509Certificate = SimpleSAML_Utilities::getDOMChildren($X509Data, 'X509Certificate', '@ds');
+		if(count($X509Certificate) === 0) {
+			return NULL;
+		}
+		$X509Certificate = $X509Certificate[0];
+
+		$r['type'] = 'X509Certificate';
+		$r['X509Certificate'] = SimpleSAML_Utilities::getDOMText($X509Certificate);
+
+		return $r;
+	}
+
+
 	/**
 	 * This function attempts to locate the default endpoint which supports one of the given bindings.
 	 *
@@ -572,6 +824,28 @@ class SimpleSAML_Metadata_SAMLParser {
 	}
 
 
+	/**
+	 * This function finds IdP descriptors which supports one of the given protocols.
+	 *
+	 * @param $protocols Array with the protocols we accept.
+	 * @return Array with IdP descriptors which supports one of the given protocols.
+	 */
+	private function getIdPDescriptors($protocols) {
+		assert('is_array($protocols)');
+
+		$ret = array();
+
+		foreach($this->idpDescriptors as $idpd) {
+			$sharedProtocols = array_intersect($protocols, $idpd['protocols']);
+			if(count($sharedProtocols) > 0) {
+				$ret[] = $idpd;
+			}
+		}
+
+		return $ret;
+	}
+
+
 	/**
 	 * This function locates the EntityDescriptor node in a DOMDocument. This node should
 	 * be the first (and only) node in the document.