From 14ce744179cda0f299afe43c17d9c9c2df374147 Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Thu, 27 Oct 2011 09:14:05 +0000 Subject: [PATCH] Update xmlseclibs.php to version 1.3.0. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2952 44740490-163a-0410-bde0-09ae8108e29a --- lib/xmlseclibs.php | 106 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 26 deletions(-) diff --git a/lib/xmlseclibs.php b/lib/xmlseclibs.php index c74b3b2b7..fc328d4a0 100644 --- a/lib/xmlseclibs.php +++ b/lib/xmlseclibs.php @@ -35,9 +35,9 @@ * POSSIBILITY OF SUCH DAMAGE. * * @author Robert Richards <rrichards@cdatazone.org> - * @copyright 2007-2010 Robert Richards <rrichards@cdatazone.org> + * @copyright 2007-2011 Robert Richards <rrichards@cdatazone.org> * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @version 1.3.0-dev + * @version 1.3.0 */ /* @@ -209,24 +209,28 @@ class XMLSecurityKey { $this->cryptParams['cipher'] = MCRYPT_TRIPLEDES; $this->cryptParams['mode'] = MCRYPT_MODE_CBC; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'; + $this->cryptParams['keysize'] = 24; break; case (XMLSecurityKey::AES128_CBC): $this->cryptParams['library'] = 'mcrypt'; $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128; $this->cryptParams['mode'] = MCRYPT_MODE_CBC; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'; + $this->cryptParams['keysize'] = 16; break; case (XMLSecurityKey::AES192_CBC): $this->cryptParams['library'] = 'mcrypt'; $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128; $this->cryptParams['mode'] = MCRYPT_MODE_CBC; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc'; + $this->cryptParams['keysize'] = 24; break; case (XMLSecurityKey::AES256_CBC): $this->cryptParams['library'] = 'mcrypt'; $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128; $this->cryptParams['mode'] = MCRYPT_MODE_CBC; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'; + $this->cryptParams['keysize'] = 32; break; case (XMLSecurityKey::RSA_1_5): $this->cryptParams['library'] = 'openssl'; @@ -285,28 +289,51 @@ class XMLSecurityKey { $this->type = $type; } + /** + * Retrieve the key size for the symmetric encryption algorithm.. + * + * If the key size is unknown, or this isn't a symmetric encryption algorithm, + * NULL is returned. + * + * @return int|NULL The number of bytes in the key. + */ + public function getSymmetricKeySize() { + if (! isset($this->cryptParams['keysize'])) { + return NULL; + } + return $this->cryptParams['keysize']; + } + public function generateSessionKey() { - $key = ''; - if (! empty($this->cryptParams['cipher']) && ! empty($this->cryptParams['mode'])) { - $keysize = mcrypt_module_get_algo_key_size($this->cryptParams['cipher']); + if (!isset($this->cryptParams['keysize'])) { + throw new Exception('Unknown key size for type "' . $this->type . '".'); + } + $keysize = $this->cryptParams['keysize']; + + if (function_exists('openssl_random_pseudo_bytes')) { + /* We have PHP >= 5.3 - use openssl to generate session key. */ + $key = openssl_random_pseudo_bytes($keysize); + } else { /* Generating random key using iv generation routines */ - if (($keysize > 0) && ($td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '',$this->cryptParams['mode'], ''))) { - if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) { - $keysize = 16; - if ($this->type == XMLSecurityKey::AES256_CBC) { - $keysize = 32; - } elseif ($this->type == XMLSecurityKey::AES192_CBC) { - $keysize = 24; - } - } - while (strlen($key) < $keysize) { - $key .= mcrypt_create_iv(mcrypt_enc_get_iv_size ($td),MCRYPT_RAND); + $key = mcrypt_create_iv($keysize, MCRYPT_RAND); + } + + if ($this->type === XMLSecurityKey::TRIPLEDES_CBC) { + /* Make sure that the generated key has the proper parity bits set. + * Mcrypt doesn't care about the parity bits, but others may care. + */ + for ($i = 0; $i < strlen($key); $i++) { + $byte = ord($key[$i]) & 0xfe; + $parity = 1; + for ($j = 1; $j < 8; $j++) { + $parity ^= ($byte >> $j) & 1; } - mcrypt_module_close($td); - $key = substr($key, 0, $keysize); - $this->key = $key; + $byte |= $parity; + $key[$i] = chr($byte); } } + + $this->key = $key; return $key; } @@ -1454,23 +1481,50 @@ class XMLSecEnc { $this->type = $curType; } - public function decryptNode($objKey, $replace=TRUE) { - $data = ''; + /** + * Retrieve the CipherValue text from this encrypted node. + * + * @return string|NULL The Ciphervalue text, or NULL if no CipherValue is found. + */ + public function getCipherValue() { if (empty($this->rawNode)) { throw new Exception('Node to decrypt has not been set'); } - if (! $objKey instanceof XMLSecurityKey) { - throw new Exception('Invalid Key'); - } + $doc = $this->rawNode->ownerDocument; $xPath = new DOMXPath($doc); $xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS); /* Only handles embedded content right now and not a reference */ $query = "./xmlencr:CipherData/xmlencr:CipherValue"; $nodeset = $xPath->query($query, $this->rawNode); + $node = $nodeset->item(0); + + if (!$node) { + return NULL; + } + + return base64_decode($node->nodeValue); + } + + /** + * Decrypt this encrypted node. + * + * The behaviour of this function depends on the value of $replace. + * If $replace is FALSE, we will return the decrypted data as a string. + * If $replace is TRUE, we will insert the decrypted element(s) into the + * document, and return the decrypted element(s). + * + * @params XMLSecurityKey $objKey The decryption key that should be used when decrypting the node. + * @params boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is TRUE. + * @return string|DOMElement The decrypted data. + */ + public function decryptNode($objKey, $replace=TRUE) { + if (! $objKey instanceof XMLSecurityKey) { + throw new Exception('Invalid Key'); + } - if ($node = $nodeset->item(0)) { - $encryptedData = base64_decode($node->nodeValue); + $encryptedData = $this->getCipherValue(); + if ($encryptedData) { $decrypted = $objKey->decryptData($encryptedData); if ($replace) { switch ($this->type) { -- GitLab