summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaime Pérez <jaime.perez@uninett.no>2016-07-02 19:43:25 +0200
committerJaime Pérez <jaime.perez@uninett.no>2016-07-02 19:43:25 +0200
commite86e40f496001f6334f96c75e78075f77d1ec558 (patch)
treeda8950fe7de682c8c59abf6daba322214f42b92b
parent4056af12443d44bd5289c7c6f40cb334a3e99b38 (diff)
downloadsimplesamlphp-e86e40f496001f6334f96c75e78075f77d1ec558.zip
simplesamlphp-e86e40f496001f6334f96c75e78075f77d1ec558.tar.gz
simplesamlphp-e86e40f496001f6334f96c75e78075f77d1ec558.tar.bz2
metadata: Add support for SHA2 digests when signing self metadata.
The hash algorithm to use to calculate signature digests for self metadata was not configurable. Add the 'metadata.sign.algorithm' configuration option to fix that. This resolves #411.
-rw-r--r--docs/simplesamlphp-advancedfeatures.md7
-rw-r--r--lib/SimpleSAML/Metadata/Signer.php70
2 files changed, 75 insertions, 2 deletions
diff --git a/docs/simplesamlphp-advancedfeatures.md b/docs/simplesamlphp-advancedfeatures.md
index afeef27..71abf8f 100644
--- a/docs/simplesamlphp-advancedfeatures.md
+++ b/docs/simplesamlphp-advancedfeatures.md
@@ -93,6 +93,13 @@ SimpleSAMLphp supports signing of the metadata it generates. Metadata signing is
- `metadata.sign.privatekey`: Name of the file with the private key which should be used to sign the metadata. This file must exist in in the `cert` directory.
- `metadata.sign.privatekey_pass`: Passphrase which should be used to open the private key. This parameter is optional, and should be left out if the private key is unencrypted.
- `metadata.sign.certificate`: Name of the file with the certificate which matches the private key. This file must exist in in the `cert` directory.
+- `metadata.sign.algorithm`: The algorithm to use when signing metadata for this entity. Defaults to RSA-SHA1. Possible values:
+
+ * `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
+ *Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
+ * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`
+ * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384`
+ * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
These options can be configured globally in the `config/config.php`-file, or per SP/IdP by adding them to the hosted metadata for the SP/IdP. The configuration in the metadata for the SP/IdP takes precedence over the global configuration.
diff --git a/lib/SimpleSAML/Metadata/Signer.php b/lib/SimpleSAML/Metadata/Signer.php
index 7ed7167..f737b92 100644
--- a/lib/SimpleSAML/Metadata/Signer.php
+++ b/lib/SimpleSAML/Metadata/Signer.php
@@ -143,6 +143,70 @@ class SimpleSAML_Metadata_Signer
/**
+ * Determine the signature and digest algorithms to use when signing metadata.
+ *
+ * This method will look for the 'metadata.sign.algorithm' key in the $entityMetadata array, or look for such
+ * a configuration option in the $config object.
+ *
+ * @param SimpleSAML_Configuration $config The global configuration.
+ * @param array $entityMetadata An array containing the metadata related to this entity.
+ * @param string $type A string describing the type of entity. E.g. 'SAML 2 IdP' or 'Shib 1.3 SP'.
+ *
+ * @return array An array with two keys, 'algorithm' and 'digest', corresponding to the signature and digest
+ * algorithms to use, respectively.
+ *
+ * @throws \SimpleSAML\Error\CriticalConfigurationError
+ *
+ * @todo change to SHA256 by default.
+ */
+ private static function getMetadataSigningAlgorithm($config, $entityMetadata, $type)
+ {
+ // configure the algorithm to use
+ if (array_key_exists('metadata.sign.algorithm', $entityMetadata)) {
+ if (!is_string($entityMetadata['metadata.sign.algorithm'])) {
+ throw new \SimpleSAML\Error\CriticalConfigurationError(
+ "Invalid value for the 'metadata.sign.algorithm' configuration option for the ".$type.
+ "'".$entityMetadata['entityid']."'. This option has restricted values"
+ );
+ }
+ $alg = $entityMetadata['metadata.sign.algorithm'];
+ } else {
+ $alg = $config->getString('metadata.sign.algorithm', XMLSecurityKey::RSA_SHA1);
+ }
+
+ $supported_algs = array(
+ XMLSecurityKey::RSA_SHA1,
+ XMLSecurityKey::RSA_SHA256,
+ XMLSecurityKey::RSA_SHA384,
+ XMLSecurityKey::RSA_SHA512,
+ );
+
+ if (!in_array($alg, $supported_algs)) {
+ throw new \SimpleSAML\Error\CriticalConfigurationError("Unknown signature algorithm '$alg'");
+ }
+
+ switch ($alg) {
+ case XMLSecurityKey::RSA_SHA256:
+ $digest = XMLSecurityDSig::SHA256;
+ break;
+ case XMLSecurityKey::RSA_SHA384:
+ $digest = XMLSecurityDSig::SHA384;
+ break;
+ case XMLSecurityKey::RSA_SHA512:
+ $digest = XMLSecurityDSig::SHA512;
+ break;
+ default:
+ $digest = XMLSecurityDSig::SHA1;
+ }
+
+ return array(
+ 'algorithm' => $alg,
+ 'digest' => $digest,
+ );
+ }
+
+
+ /**
* Signs the given metadata if metadata signing is enabled.
*
* @param string $metadataString A string with the metadata.
@@ -186,8 +250,10 @@ class SimpleSAML_Metadata_Signer
throw new Exception('Error parsing self-generated metadata.');
}
+ $signature_cf = self::getMetadataSigningAlgorithm($config, $entityMetadata, $type);
+
// load the private key
- $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private'));
+ $objKey = new XMLSecurityKey($signature_cf['algorithm'], array('type' => 'private'));
if (array_key_exists('privatekey_pass', $keyCertFiles)) {
$objKey->passphrase = $keyCertFiles['privatekey_pass'];
}
@@ -207,7 +273,7 @@ class SimpleSAML_Metadata_Signer
$objXMLSecDSig->addReferenceList(
array($rootNode),
- XMLSecurityDSig::SHA1,
+ $signature_cf['digest'],
array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),
array('id_name' => 'ID')
);