From d7356580a6545563eaf7cc00e3e00714579d82de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20P=C3=A9rez=20Crespo?= <jaime.perez@uninett.no> Date: Mon, 1 Oct 2012 14:17:09 +0000 Subject: [PATCH] Support for RSA_SHA256, RSA_SHA384 and RSA_SHA512 in HTTP Redirect binding. Signature algorithm can now be set also in the remote IdP metadata, with more priority than the one specified in hosted SP metadata. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3181 44740490-163a-0410-bde0-09ae8108e29a --- lib/SAML2/HTTPRedirect.php | 22 ++++++++++------------ lib/SAML2/Utils.php | 25 +++++++++++-------------- modules/saml/lib/Message.php | 6 +++++- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/lib/SAML2/HTTPRedirect.php b/lib/SAML2/HTTPRedirect.php index 6b001de18..6033389a0 100644 --- a/lib/SAML2/HTTPRedirect.php +++ b/lib/SAML2/HTTPRedirect.php @@ -51,7 +51,7 @@ class SAML2_HTTPRedirect extends SAML2_Binding { if ($key !== NULL) { /* Add the signature. */ - $msg .= '&SigAlg=' . urlencode(XMLSecurityKey::RSA_SHA1); + $msg .= '&SigAlg=' . urlencode($key->type); $signature = $key->signData($msg); $msg .= '&Signature=' . urlencode(base64_encode($signature)); @@ -216,17 +216,15 @@ class SAML2_HTTPRedirect extends SAML2_Binding { $signature = base64_decode($signature); - switch ($sigAlg) { - case XMLSecurityKey::RSA_SHA1: - if ($key->type !== XMLSecurityKey::RSA_SHA1) { - throw new Exception('Invalid key type for validating signature on query string.'); - } - if (!$key->verifySignature($query,$signature)) { - throw new Exception('Unable to validate signature on query string.'); - } - break; - default: - throw new Exception('Unknown signature algorithm: ' . var_export($sigAlg, TRUE)); + if ($key->type !== XMLSecurityKey::RSA_SHA1) { + throw new Exception('Invalid key type for validating signature on query string.'); + } + if ($key->type !== $sigAlg) { + $key = SAML2_Utils::castKey($key, $sigAlg); + } + + if (!$key->verifySignature($query,$signature)) { + throw new Exception('Unable to validate signature on query string.'); } } diff --git a/lib/SAML2/Utils.php b/lib/SAML2/Utils.php index 79576a2b6..5120639cc 100644 --- a/lib/SAML2/Utils.php +++ b/lib/SAML2/Utils.php @@ -91,10 +91,17 @@ class SAML2_Utils { * * @param XMLSecurityKey $key The key. * @param string $algorithm The desired algorithm. + * @param string $types Public or private key, defaults to public. * @return XMLSecurityKey The new key. */ - private static function castKey(XMLSecurityKey $key, $algorithm) { + public static function castKey(XMLSecurityKey $key, $algorithm, $type = 'public') { assert('is_string($algorithm)'); + assert('$type === "public" || $type === "private"'); + + // do nothing if algorithm is already the type of the key + if ($key->type === $algorithm) { + return $key; + } $keyInfo = openssl_pkey_get_details($key->key); if ($keyInfo === FALSE) { @@ -104,7 +111,7 @@ class SAML2_Utils { throw new Exception('Missing key in public key details.'); } - $newKey = new XMLSecurityKey($algorithm, array('type'=>'public')); + $newKey = new XMLSecurityKey($algorithm, array('type'=>$type)); $newKey->loadKey($keyInfo['key']); return $newKey; } @@ -133,18 +140,8 @@ class SAML2_Utils { } $algo = $sigMethod->getAttribute('Algorithm'); - if ($key->type === XMLSecurityKey::RSA_SHA1) { - switch ($algo) { - case XMLSecurityKey::RSA_SHA256: - $key = self::castKey($key, XMLSecurityKey::RSA_SHA256); - break; - case XMLSecurityKey::RSA_SHA384: - $key = self::castKey($key, XMLSecurityKey::RSA_SHA384); - break; - case XMLSecurityKey::RSA_SHA512: - $key = self::castKey($key, XMLSecurityKey::RSA_SHA512); - break; - } + if ($key->type === XMLSecurityKey::RSA_SHA1 && $algo !== $key->type) { + $key = self::castKey($key, $algo); } /* Check the signature. */ diff --git a/modules/saml/lib/Message.php b/modules/saml/lib/Message.php index 6e90d65ce..64c06da13 100644 --- a/modules/saml/lib/Message.php +++ b/modules/saml/lib/Message.php @@ -21,7 +21,11 @@ class sspmod_saml_Message { $keyArray = SimpleSAML_Utilities::loadPrivateKey($srcMetadata, TRUE); $certArray = SimpleSAML_Utilities::loadPublicKey($srcMetadata, FALSE); - $algo = $srcMetadata->getString('signature.algorithm', XMLSecurityKey::RSA_SHA1); + + $algo = $dstMetadata->getString('signature.algorithm', NULL); + if ($algo === NULL) { + $algo = $srcMetadata->getString('signature.algorithm', XMLSecurityKey::RSA_SHA1); + } $privateKey = new XMLSecurityKey($algo, array('type' => 'private')); if (array_key_exists('password', $keyArray)) { -- GitLab