• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List

E:/E/GEAMP/www/openbiz/openbiz/others/Zend/InfoCard.php

00001 <?php
00025 require_once 'Zend/InfoCard/Xml/EncryptedData.php';
00026 
00030 require_once 'Zend/InfoCard/Xml/Assertion.php';
00031 
00035 require_once 'Zend/InfoCard/Cipher.php';
00036 
00040 require_once 'Zend/InfoCard/Xml/Security.php';
00041 
00045 require_once 'Zend/InfoCard/Adapter/Interface.php';
00046 
00050 require_once 'Zend/InfoCard/Claims.php';
00051 
00058 class Zend_InfoCard
00059 {
00063     const DIGEST_SHA1        = 'http://www.w3.org/2000/09/xmldsig#sha1';
00064 
00071     protected $_keyPairs;
00072 
00078     protected $_pkiCipherObj;
00079 
00085     protected $_symCipherObj;
00086 
00093     protected $_adapter;
00094 
00095 
00101     public function __construct()
00102     {
00103         $this->_keyPairs = array();
00104 
00105         if(!extension_loaded('mcrypt')) {
00106             require_once 'Zend/InfoCard/Exception.php';
00107             throw new Zend_InfoCard_Exception("Use of the Zend_InfoCard component requires the mcrypt extension to be enabled in PHP");
00108         }
00109 
00110         if(!extension_loaded('openssl')) {
00111             require_once 'Zend/InfoCard/Exception.php';
00112             throw new Zend_InfoCard_Exception("Use of the Zend_InfoCard component requires the openssl extension to be enabled in PHP");
00113         }
00114     }
00115 
00123     public function setAdapter(Zend_InfoCard_Adapter_Interface $a)
00124     {
00125         $this->_adapter = $a;
00126         return $this;
00127     }
00128 
00135     public function getAdapter()
00136     {
00137         if($this->_adapter === null) {
00138             require_once 'Zend/InfoCard/Adapter/Default.php';
00139             $this->setAdapter(new Zend_InfoCard_Adapter_Default());
00140         }
00141 
00142         return $this->_adapter;
00143     }
00144 
00150     public function getPkiCipherObject()
00151     {
00152         return $this->_pkiCipherObj;
00153     }
00154 
00161     public function setPkiCipherObject(Zend_InfoCard_Cipher_Pki_Interface $cipherObj)
00162     {
00163         $this->_pkiCipherObj = $cipherObj;
00164         return $this;
00165     }
00166 
00172     public function getSymCipherObject()
00173     {
00174         return $this->_symCipherObj;
00175     }
00176 
00183     public function setSymCipherObject($cipherObj)
00184     {
00185         $this->_symCipherObj = $cipherObj;
00186         return $this;
00187     }
00188 
00196     public function removeCertificatePair($key_id)
00197     {
00198 
00199         if(!key_exists($key_id, $this->_keyPairs)) {
00200             require_once 'Zend/InfoCard/Exception.php';
00201             throw new Zend_InfoCard_Exception("Attempted to remove unknown key id: $key_id");
00202         }
00203 
00204         unset($this->_keyPairs[$key_id]);
00205         return $this;
00206     }
00207 
00218     public function addCertificatePair($private_key_file, $public_key_file, $type = Zend_InfoCard_Cipher::ENC_RSA_OAEP_MGF1P, $password = null)
00219     {
00220         if(!file_exists($private_key_file) ||
00221            !file_exists($public_key_file)) {
00222             require_once 'Zend/InfoCard/Exception.php';
00223             throw new Zend_InfoCard_Exception("Could not locate the public and private certificate pair files: $private_key_file, $public_key_file");
00224         }
00225 
00226         if(!is_readable($private_key_file) ||
00227            !is_readable($public_key_file)) {
00228             require_once 'Zend/InfoCard/Exception.php';
00229             throw new Zend_InfoCard_Exception("Could not read the public and private certificate pair files (check permissions): $private_key_file, $public_key_file");
00230         }
00231 
00232         $key_id = md5($private_key_file.$public_key_file);
00233 
00234         if(key_exists($key_id, $this->_keyPairs)) {
00235             require_once 'Zend/InfoCard/Exception.php';
00236             throw new Zend_InfoCard_Exception("Attempted to add previously existing certificate pair: $private_key_file, $public_key_file");
00237         }
00238 
00239         switch($type) {
00240             case Zend_InfoCard_Cipher::ENC_RSA:
00241             case Zend_InfoCard_Cipher::ENC_RSA_OAEP_MGF1P:
00242                 $this->_keyPairs[$key_id] = array('private' => $private_key_file,
00243                                 'public'      => $public_key_file,
00244                                 'type_uri'    => $type);
00245 
00246                 if($password !== null) {
00247                     $this->_keyPairs[$key_id]['password'] = $password;
00248                 } else {
00249                     $this->_keyPairs[$key_id]['password'] = null;
00250                 }
00251 
00252                 return $key_id;
00253                 break;
00254             default:
00255                 require_once 'Zend/InfoCard/Exception.php';
00256                 throw new Zend_InfoCard_Exception("Invalid Certificate Pair Type specified: $type");
00257         }
00258     }
00259 
00268     public function getCertificatePair($key_id)
00269     {
00270         if(key_exists($key_id, $this->_keyPairs)) {
00271             return $this->_keyPairs[$key_id];
00272         }
00273 
00274         require_once 'Zend/InfoCard/Exception.php';
00275         throw new Zend_InfoCard_Exception("Invalid Certificate Pair ID provided: $key_id");
00276     }
00277 
00287     protected function _getPublicKeyDigest($key_id, $digestMethod = self::DIGEST_SHA1)
00288     {
00289         $certificatePair = $this->getCertificatePair($key_id);
00290 
00291         $temp = file($certificatePair['public']);
00292         unset($temp[count($temp)-1]);
00293         unset($temp[0]);
00294         $certificateData = base64_decode(implode("\n", $temp));
00295 
00296         switch($digestMethod) {
00297             case self::DIGEST_SHA1:
00298                 $digest_retval = sha1($certificateData, true);
00299                 break;
00300             default:
00301                 require_once 'Zend/InfoCard/Exception.php';
00302                 throw new Zend_InfoCard_Exception("Invalid Digest Type Provided: $digestMethod");
00303         }
00304 
00305         return $digest_retval;
00306     }
00307 
00315     protected function _findCertifiatePairByDigest($digest, $digestMethod = self::DIGEST_SHA1)
00316     {
00317 
00318         foreach($this->_keyPairs as $key_id => $certificate_data) {
00319 
00320             $cert_digest = $this->_getPublicKeyDigest($key_id, $digestMethod);
00321 
00322             if($cert_digest == $digest) {
00323                 return $key_id;
00324             }
00325         }
00326 
00327         return false;
00328     }
00329 
00337     protected function _extractSignedToken($strXmlToken)
00338     {
00339         $encryptedData = Zend_InfoCard_Xml_EncryptedData::getInstance($strXmlToken);
00340 
00341         // Determine the Encryption Method used to encrypt the token
00342 
00343         switch($encryptedData->getEncryptionMethod()) {
00344             case Zend_InfoCard_Cipher::ENC_AES128CBC:
00345             case Zend_InfoCard_Cipher::ENC_AES256CBC:
00346                 break;
00347             default:
00348                 require_once 'Zend/InfoCard/Exception.php';
00349                 throw new Zend_InfoCard_Exception("Unknown Encryption Method used in the secure token");
00350         }
00351 
00352         // Figure out the Key we are using to decrypt the token
00353 
00354         $keyinfo = $encryptedData->getKeyInfo();
00355 
00356         if(!($keyinfo instanceof Zend_InfoCard_Xml_KeyInfo_XmlDSig)) {
00357             require_once 'Zend/InfoCard/Exception.php';
00358             throw new Zend_InfoCard_Exception("Expected a XML digital signature KeyInfo, but was not found");
00359         }
00360 
00361 
00362         $encryptedKey = $keyinfo->getEncryptedKey();
00363 
00364         switch($encryptedKey->getEncryptionMethod()) {
00365             case Zend_InfoCard_Cipher::ENC_RSA:
00366             case Zend_InfoCard_Cipher::ENC_RSA_OAEP_MGF1P:
00367                 break;
00368             default:
00369                 require_once 'Zend/InfoCard/Exception.php';
00370                 throw new Zend_InfoCard_Exception("Unknown Key Encryption Method used in secure token");
00371         }
00372 
00373         $securityTokenRef = $encryptedKey->getKeyInfo()->getSecurityTokenReference();
00374 
00375         $key_id = $this->_findCertifiatePairByDigest($securityTokenRef->getKeyReference());
00376 
00377         if(!$key_id) {
00378             require_once 'Zend/InfoCard/Exception.php';
00379             throw new Zend_InfoCard_Exception("Unable to find key pair used to encrypt symmetric InfoCard Key");
00380         }
00381 
00382         $certificate_pair = $this->getCertificatePair($key_id);
00383 
00384         // Santity Check
00385 
00386         if($certificate_pair['type_uri'] != $encryptedKey->getEncryptionMethod()) {
00387             require_once 'Zend/InfoCard/Exception.php';
00388             throw new Zend_InfoCard_Exception("Certificate Pair which matches digest is not of same algorithm type as document, check addCertificate()");
00389         }
00390 
00391         $PKcipher = Zend_InfoCard_Cipher::getInstanceByURI($encryptedKey->getEncryptionMethod());
00392 
00393         $base64DecodeSupportsStrictParam = version_compare(PHP_VERSION, '5.2.0', '>=');
00394 
00395         if ($base64DecodeSupportsStrictParam) {
00396             $keyCipherValueBase64Decoded = base64_decode($encryptedKey->getCipherValue(), true);
00397         } else {
00398             $keyCipherValueBase64Decoded = base64_decode($encryptedKey->getCipherValue());
00399         }
00400 
00401         $symmetricKey = $PKcipher->decrypt(
00402             $keyCipherValueBase64Decoded,
00403             file_get_contents($certificate_pair['private']),
00404             $certificate_pair['password']
00405             );
00406 
00407         $symCipher = Zend_InfoCard_Cipher::getInstanceByURI($encryptedData->getEncryptionMethod());
00408 
00409         if ($base64DecodeSupportsStrictParam) {
00410             $dataCipherValueBase64Decoded = base64_decode($encryptedData->getCipherValue(), true);
00411         } else {
00412             $dataCipherValueBase64Decoded = base64_decode($encryptedData->getCipherValue());
00413         }
00414 
00415         $signedToken = $symCipher->decrypt($dataCipherValueBase64Decoded, $symmetricKey);
00416 
00417         return $signedToken;
00418     }
00419 
00427     public function process($strXmlToken)
00428     {
00429 
00430         $retval = new Zend_InfoCard_Claims();
00431 
00432         require_once 'Zend/InfoCard/Exception.php';
00433         try {
00434             $signedAssertionsXml = $this->_extractSignedToken($strXmlToken);
00435         } catch(Zend_InfoCard_Exception $e) {
00436             $retval->setError('Failed to extract assertion document');
00437             $retval->setCode(Zend_InfoCard_Claims::RESULT_PROCESSING_FAILURE);
00438             return $retval;
00439         }
00440 
00441         try {
00442             $assertions = Zend_InfoCard_Xml_Assertion::getInstance($signedAssertionsXml);
00443         } catch(Zend_InfoCard_Exception $e) {
00444             $retval->setError('Failure processing assertion document');
00445             $retval->setCode(Zend_InfoCard_Claims::RESULT_PROCESSING_FAILURE);
00446             return $retval;
00447         }
00448 
00449         if(!($assertions instanceof Zend_InfoCard_Xml_Assertion_Interface)) {
00450             throw new Zend_InfoCard_Exception("Invalid Assertion Object returned");
00451         }
00452 
00453         if(!($reference_id = Zend_InfoCard_Xml_Security::validateXMLSignature($assertions->asXML()))) {
00454             $retval->setError("Failure Validating the Signature of the assertion document");
00455             $retval->setCode(Zend_InfoCard_Claims::RESULT_VALIDATION_FAILURE);
00456             return $retval;
00457         }
00458 
00459         // The reference id should be locally scoped as far as I know
00460         if($reference_id[0] == '#') {
00461             $reference_id = substr($reference_id, 1);
00462         } else {
00463             $retval->setError("Reference of document signature does not reference the local document");
00464             $retval->setCode(Zend_InfoCard_Claims::RESULT_VALIDATION_FAILURE);
00465             return $retval;
00466         }
00467 
00468         // Make sure the signature is in reference to the same document as the assertions
00469         if($reference_id != $assertions->getAssertionID()) {
00470             $retval->setError("Reference of document signature does not reference the local document");
00471             $retval->setCode(Zend_InfoCard_Claims::RESULT_VALIDATION_FAILURE);
00472         }
00473 
00474         // Validate we haven't seen this before and the conditions are acceptable
00475         $conditions = $this->getAdapter()->retrieveAssertion($assertions->getAssertionURI(), $assertions->getAssertionID());
00476 
00477         if($conditions === false) {
00478             $conditions = $assertions->getConditions();
00479         }
00480 
00481 
00482         if(is_array($condition_error = $assertions->validateConditions($conditions))) {
00483             $retval->setError("Conditions of assertion document are not met: {$condition_error[1]} ({$condition_error[0]})");
00484             $retval->setCode(Zend_InfoCard_Claims::RESULT_VALIDATION_FAILURE);
00485         }
00486 
00487         $attributes = $assertions->getAttributes();
00488 
00489         $retval->setClaims($attributes);
00490 
00491         if($retval->getCode() == 0) {
00492             $retval->setCode(Zend_InfoCard_Claims::RESULT_SUCCESS);
00493         }
00494 
00495         return $retval;
00496     }
00497 }

Generated on Thu Apr 19 2012 17:01:17 for openbiz by  doxygen 1.7.2