| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Pure-PHP X.509 Parser | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * PHP versions 4 and 5 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Encode and decode X.509 certificates. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The extensions are from {@link http://tools.ietf.org/html/rfc5280 RFC5280} and | 
					
						
							|  |  |  |  * {@link http://web.archive.org/web/19961027104704/http://www3.netscape.com/eng/security/cert-exts.html Netscape Certificate Extensions}. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Note that loading an X.509 certificate and resaving it may invalidate the signature.  The reason being that the signature is based on a | 
					
						
							|  |  |  |  * portion of the certificate that contains optional parameters with default values.  ie. if the parameter isn't there the default value is | 
					
						
							|  |  |  |  * used.  Problem is, if the parameter is there and it just so happens to have the default value there are two ways that that parameter can | 
					
						
							|  |  |  |  * be encoded.  It can be encoded explicitly or left out all together.  This would effect the signature value and thus may invalidate the | 
					
						
							|  |  |  |  * the certificate all together unless the certificate is re-signed. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy | 
					
						
							|  |  |  |  * of this software and associated documentation files (the "Software"), to deal | 
					
						
							|  |  |  |  * in the Software without restriction, including without limitation the rights | 
					
						
							|  |  |  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
					
						
							|  |  |  |  * copies of the Software, and to permit persons to whom the Software is | 
					
						
							|  |  |  |  * furnished to do so, subject to the following conditions: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The above copyright notice and this permission notice shall be included in | 
					
						
							|  |  |  |  * all copies or substantial portions of the Software. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
					
						
							|  |  |  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
					
						
							|  |  |  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
					
						
							|  |  |  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
					
						
							|  |  |  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
					
						
							|  |  |  |  * THE SOFTWARE. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @category  File | 
					
						
							|  |  |  |  * @package   File_X509 | 
					
						
							|  |  |  |  * @author    Jim Wigginton <terrafrost@php.net> | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |  * @copyright 2012 Jim Wigginton | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |  * @license   http://www.opensource.org/licenses/mit-license.html  MIT License | 
					
						
							|  |  |  |  * @link      http://phpseclib.sourceforge.net | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Include File_ASN1 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | if (!class_exists('File_ASN1')) { | 
					
						
							|  |  |  |     include_once 'ASN1.php'; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Flag to only accept signatures signed by certificate authorities | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Not really used anymore but retained all the same to suppress E_NOTICEs from old installs | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @access public | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_VALIDATE_SIGNATURE_BY_CA', 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**#@+
 | 
					
						
							|  |  |  |  * @access public | 
					
						
							|  |  |  |  * @see File_X509::getDN() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Return internal array representation | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_DN_ARRAY', 0); | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Return string | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_DN_STRING', 1); | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Return ASN.1 name string | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_DN_ASN1', 2); | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Return OpenSSL compatible array | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_DN_OPENSSL', 3); | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Return canonical ASN.1 RDNs string | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_DN_CANON', 4); | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Return name hash for file indexing | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_DN_HASH', 5); | 
					
						
							|  |  |  | /**#@-*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**#@+
 | 
					
						
							|  |  |  |  * @access public | 
					
						
							|  |  |  |  * @see File_X509::saveX509() | 
					
						
							|  |  |  |  * @see File_X509::saveCSR() | 
					
						
							|  |  |  |  * @see File_X509::saveCRL() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Save as PEM | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ie. a base64-encoded PEM with a header and a footer | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_FORMAT_PEM', 0); | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Save as DER | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_FORMAT_DER', 1); | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Save as a SPKAC | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Only works on CSRs. Not currently supported. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_FORMAT_SPKAC', 2); | 
					
						
							|  |  |  | /**#@-*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Attribute value disposition. | 
					
						
							|  |  |  |  * If disposition is >= 0, this is the index of the target value. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | define('FILE_X509_ATTR_ALL', -1); // All attribute values (array).
 | 
					
						
							|  |  |  | define('FILE_X509_ATTR_APPEND', -2); // Add a value.
 | 
					
						
							|  |  |  | define('FILE_X509_ATTR_REPLACE', -3); // Clear first, then add a value.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Pure-PHP X.509 Parser | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @package File_X509 | 
					
						
							|  |  |  |  * @author  Jim Wigginton <terrafrost@php.net> | 
					
						
							|  |  |  |  * @access  public | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class File_X509 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * ASN.1 syntax for X.509 certificates | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var Array | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $Certificate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**#@+
 | 
					
						
							|  |  |  |      * ASN.1 syntax for various extensions | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $DirectoryString; | 
					
						
							|  |  |  |     var $PKCS9String; | 
					
						
							|  |  |  |     var $AttributeValue; | 
					
						
							|  |  |  |     var $Extensions; | 
					
						
							|  |  |  |     var $KeyUsage; | 
					
						
							|  |  |  |     var $ExtKeyUsageSyntax; | 
					
						
							|  |  |  |     var $BasicConstraints; | 
					
						
							|  |  |  |     var $KeyIdentifier; | 
					
						
							|  |  |  |     var $CRLDistributionPoints; | 
					
						
							|  |  |  |     var $AuthorityKeyIdentifier; | 
					
						
							|  |  |  |     var $CertificatePolicies; | 
					
						
							|  |  |  |     var $AuthorityInfoAccessSyntax; | 
					
						
							|  |  |  |     var $SubjectAltName; | 
					
						
							|  |  |  |     var $PrivateKeyUsagePeriod; | 
					
						
							|  |  |  |     var $IssuerAltName; | 
					
						
							|  |  |  |     var $PolicyMappings; | 
					
						
							|  |  |  |     var $NameConstraints; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var $CPSuri; | 
					
						
							|  |  |  |     var $UserNotice; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var $netscape_cert_type; | 
					
						
							|  |  |  |     var $netscape_comment; | 
					
						
							|  |  |  |     var $netscape_ca_policy_url; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var $Name; | 
					
						
							|  |  |  |     var $RelativeDistinguishedName; | 
					
						
							|  |  |  |     var $CRLNumber; | 
					
						
							|  |  |  |     var $CRLReason; | 
					
						
							|  |  |  |     var $IssuingDistributionPoint; | 
					
						
							|  |  |  |     var $InvalidityDate; | 
					
						
							|  |  |  |     var $CertificateIssuer; | 
					
						
							|  |  |  |     var $HoldInstructionCode; | 
					
						
							|  |  |  |     var $SignedPublicKeyAndChallenge; | 
					
						
							|  |  |  |     /**#@-*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * ASN.1 syntax for Certificate Signing Requests (RFC2986) | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var Array | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $CertificationRequest; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * ASN.1 syntax for Certificate Revocation Lists (RFC5280) | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var Array | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $CertificateList; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Distinguished Name | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var Array | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $dn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Public key | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var String | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $publicKey; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Private key | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var String | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $privateKey; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Object identifiers for X.509 certificates | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var Array | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @link http://en.wikipedia.org/wiki/Object_identifier | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $oids; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * The certificate authorities | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var Array | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $CAs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * The currently loaded certificate | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var Array | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $currentCert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * The signature subject | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * There's no guarantee File_X509 is going to reencode an X.509 cert in the same way it was originally | 
					
						
							|  |  |  |      * encoded so we take save the portion of the original cert that the signature would have made for. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var String | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $signatureSubject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Certificate Start Date | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var String | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $startDate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Certificate End Date | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var String | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $endDate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Serial Number | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var String | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $serialNumber; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Key Identifier | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and
 | 
					
						
							|  |  |  |      * {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}.
 | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var String | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $currentKeyIdentifier; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * CA Flag | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var Boolean | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $caFlag = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * SPKAC Challenge | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var String | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var $challenge; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Default Constructor. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return File_X509 | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function File_X509() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!class_exists('Math_BigInteger')) { | 
					
						
							|  |  |  |             include_once 'Math/BigInteger.php'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Explicitly Tagged Module, 1988 Syntax
 | 
					
						
							|  |  |  |         // http://tools.ietf.org/html/rfc5280#appendix-A.1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->DirectoryString = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'teletexString'   => array('type' => FILE_ASN1_TYPE_TELETEX_STRING), | 
					
						
							|  |  |  |                 'printableString' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING), | 
					
						
							|  |  |  |                 'universalString' => array('type' => FILE_ASN1_TYPE_UNIVERSAL_STRING), | 
					
						
							|  |  |  |                 'utf8String'      => array('type' => FILE_ASN1_TYPE_UTF8_STRING), | 
					
						
							|  |  |  |                 'bmpString'       => array('type' => FILE_ASN1_TYPE_BMP_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->PKCS9String = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'ia5String'       => array('type' => FILE_ASN1_TYPE_IA5_STRING), | 
					
						
							|  |  |  |                 'directoryString' => $this->DirectoryString | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->AttributeValue = array('type' => FILE_ASN1_TYPE_ANY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $AttributeType = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $AttributeTypeAndValue = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'type' => $AttributeType, | 
					
						
							|  |  |  |                 'value'=> $this->AttributeValue | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* | 
					
						
							|  |  |  |         In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare, | 
					
						
							|  |  |  |         but they can be useful at times when either there is no unique attribute in the entry or you | 
					
						
							|  |  |  |         want to ensure that the entry's DN contains some useful identifying information. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |         $this->RelativeDistinguishedName = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SET, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => $AttributeTypeAndValue | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // http://tools.ietf.org/html/rfc5280#section-4.1.2.4
 | 
					
						
							|  |  |  |         $RDNSequence = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             // RDNSequence does not define a min or a max, which means it doesn't have one
 | 
					
						
							|  |  |  |             'min'      => 0, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => $this->RelativeDistinguishedName | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->Name = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'rdnSequence' => $RDNSequence | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // http://tools.ietf.org/html/rfc5280#section-4.1.1.2
 | 
					
						
							|  |  |  |         $AlgorithmIdentifier = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'algorithm'  => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER), | 
					
						
							|  |  |  |                 'parameters' => array( | 
					
						
							|  |  |  |                                     'type'     => FILE_ASN1_TYPE_ANY, | 
					
						
							|  |  |  |                                     'optional' => true | 
					
						
							|  |  |  |                                 ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* | 
					
						
							|  |  |  |            A certificate using system MUST reject the certificate if it encounters | 
					
						
							|  |  |  |            a critical extension it does not recognize; however, a non-critical | 
					
						
							|  |  |  |            extension may be ignored if it is not recognized. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            http://tools.ietf.org/html/rfc5280#section-4.2
 | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |         $Extension = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'extnId'   => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER), | 
					
						
							|  |  |  |                 'critical' => array( | 
					
						
							|  |  |  |                                   'type'     => FILE_ASN1_TYPE_BOOLEAN, | 
					
						
							|  |  |  |                                   'optional' => true, | 
					
						
							|  |  |  |                                   'default'  => false | 
					
						
							|  |  |  |                               ), | 
					
						
							|  |  |  |                 'extnValue' => array('type' => FILE_ASN1_TYPE_OCTET_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->Extensions = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             // technically, it's MAX, but we'll assume anything < 0 is MAX
 | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             // if 'children' isn't an array then 'min' and 'max' must be defined
 | 
					
						
							|  |  |  |             'children' => $Extension | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $SubjectPublicKeyInfo = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'algorithm'        => $AlgorithmIdentifier, | 
					
						
							|  |  |  |                 'subjectPublicKey' => array('type' => FILE_ASN1_TYPE_BIT_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $UniqueIdentifier = array('type' => FILE_ASN1_TYPE_BIT_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $Time = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'utcTime'     => array('type' => FILE_ASN1_TYPE_UTC_TIME), | 
					
						
							|  |  |  |                 'generalTime' => array('type' => FILE_ASN1_TYPE_GENERALIZED_TIME) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // http://tools.ietf.org/html/rfc5280#section-4.1.2.5
 | 
					
						
							|  |  |  |         $Validity = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'notBefore' => $Time, | 
					
						
							|  |  |  |                 'notAfter'  => $Time | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $CertificateSerialNumber = array('type' => FILE_ASN1_TYPE_INTEGER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $Version = array( | 
					
						
							|  |  |  |             'type'    => FILE_ASN1_TYPE_INTEGER, | 
					
						
							|  |  |  |             'mapping' => array('v1', 'v2', 'v3') | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // assert($TBSCertificate['children']['signature'] == $Certificate['children']['signatureAlgorithm'])
 | 
					
						
							|  |  |  |         $TBSCertificate = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 // technically, default implies optional, but we'll define it as being optional, none-the-less, just to
 | 
					
						
							|  |  |  |                 // reenforce that fact
 | 
					
						
							|  |  |  |                 'version'             => array( | 
					
						
							|  |  |  |                                              'constant' => 0, | 
					
						
							|  |  |  |                                              'optional' => true, | 
					
						
							|  |  |  |                                              'explicit' => true, | 
					
						
							|  |  |  |                                              'default'  => 'v1' | 
					
						
							|  |  |  |                                          ) + $Version, | 
					
						
							|  |  |  |                 'serialNumber'         => $CertificateSerialNumber, | 
					
						
							|  |  |  |                 'signature'            => $AlgorithmIdentifier, | 
					
						
							|  |  |  |                 'issuer'               => $this->Name, | 
					
						
							|  |  |  |                 'validity'             => $Validity, | 
					
						
							|  |  |  |                 'subject'              => $this->Name, | 
					
						
							|  |  |  |                 'subjectPublicKeyInfo' => $SubjectPublicKeyInfo, | 
					
						
							|  |  |  |                 // implicit means that the T in the TLV structure is to be rewritten, regardless of the type
 | 
					
						
							|  |  |  |                 'issuerUniqueID'       => array( | 
					
						
							|  |  |  |                                                'constant' => 1, | 
					
						
							|  |  |  |                                                'optional' => true, | 
					
						
							|  |  |  |                                                'implicit' => true | 
					
						
							|  |  |  |                                            ) + $UniqueIdentifier, | 
					
						
							|  |  |  |                 'subjectUniqueID'       => array( | 
					
						
							|  |  |  |                                                'constant' => 2, | 
					
						
							|  |  |  |                                                'optional' => true, | 
					
						
							|  |  |  |                                                'implicit' => true | 
					
						
							|  |  |  |                                            ) + $UniqueIdentifier, | 
					
						
							|  |  |  |                 // <http://tools.ietf.org/html/rfc2459#page-74> doesn't use the EXPLICIT keyword but if
 | 
					
						
							|  |  |  |                 // it's not IMPLICIT, it's EXPLICIT
 | 
					
						
							|  |  |  |                 'extensions'            => array( | 
					
						
							|  |  |  |                                                'constant' => 3, | 
					
						
							|  |  |  |                                                'optional' => true, | 
					
						
							|  |  |  |                                                'explicit' => true | 
					
						
							|  |  |  |                                            ) + $this->Extensions | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->Certificate = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                  'tbsCertificate'     => $TBSCertificate, | 
					
						
							|  |  |  |                  'signatureAlgorithm' => $AlgorithmIdentifier, | 
					
						
							|  |  |  |                  'signature'          => array('type' => FILE_ASN1_TYPE_BIT_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->KeyUsage = array( | 
					
						
							|  |  |  |             'type'    => FILE_ASN1_TYPE_BIT_STRING, | 
					
						
							|  |  |  |             'mapping' => array( | 
					
						
							|  |  |  |                 'digitalSignature', | 
					
						
							|  |  |  |                 'nonRepudiation', | 
					
						
							|  |  |  |                 'keyEncipherment', | 
					
						
							|  |  |  |                 'dataEncipherment', | 
					
						
							|  |  |  |                 'keyAgreement', | 
					
						
							|  |  |  |                 'keyCertSign', | 
					
						
							|  |  |  |                 'cRLSign', | 
					
						
							|  |  |  |                 'encipherOnly', | 
					
						
							|  |  |  |                 'decipherOnly' | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->BasicConstraints = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'cA'                => array( | 
					
						
							|  |  |  |                                                  'type'     => FILE_ASN1_TYPE_BOOLEAN, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'default'  => false | 
					
						
							|  |  |  |                                        ), | 
					
						
							|  |  |  |                 'pathLenConstraint' => array( | 
					
						
							|  |  |  |                                                  'type' => FILE_ASN1_TYPE_INTEGER, | 
					
						
							|  |  |  |                                                  'optional' => true | 
					
						
							|  |  |  |                                        ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->KeyIdentifier = array('type' => FILE_ASN1_TYPE_OCTET_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $OrganizationalUnitNames = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => 4, // ub-organizational-units
 | 
					
						
							|  |  |  |             'children' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $PersonalName = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SET, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'surname'              => array( | 
					
						
							|  |  |  |                                            'type' => FILE_ASN1_TYPE_PRINTABLE_STRING, | 
					
						
							|  |  |  |                                            'constant' => 0, | 
					
						
							|  |  |  |                                            'optional' => true, | 
					
						
							|  |  |  |                                            'implicit' => true | 
					
						
							|  |  |  |                                          ), | 
					
						
							|  |  |  |                 'given-name'           => array( | 
					
						
							|  |  |  |                                            'type' => FILE_ASN1_TYPE_PRINTABLE_STRING, | 
					
						
							|  |  |  |                                            'constant' => 1, | 
					
						
							|  |  |  |                                            'optional' => true, | 
					
						
							|  |  |  |                                            'implicit' => true | 
					
						
							|  |  |  |                                          ), | 
					
						
							|  |  |  |                 'initials'             => array( | 
					
						
							|  |  |  |                                            'type' => FILE_ASN1_TYPE_PRINTABLE_STRING, | 
					
						
							|  |  |  |                                            'constant' => 2, | 
					
						
							|  |  |  |                                            'optional' => true, | 
					
						
							|  |  |  |                                            'implicit' => true | 
					
						
							|  |  |  |                                          ), | 
					
						
							|  |  |  |                 'generation-qualifier' => array( | 
					
						
							|  |  |  |                                            'type' => FILE_ASN1_TYPE_PRINTABLE_STRING, | 
					
						
							|  |  |  |                                            'constant' => 3, | 
					
						
							|  |  |  |                                            'optional' => true, | 
					
						
							|  |  |  |                                            'implicit' => true | 
					
						
							|  |  |  |                                          ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $NumericUserIdentifier = array('type' => FILE_ASN1_TYPE_NUMERIC_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $OrganizationName = array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $PrivateDomainName = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'numeric'   => array('type' => FILE_ASN1_TYPE_NUMERIC_STRING), | 
					
						
							|  |  |  |                 'printable' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $TerminalIdentifier = array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $NetworkAddress = array('type' => FILE_ASN1_TYPE_NUMERIC_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $AdministrationDomainName = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             // if class isn't present it's assumed to be FILE_ASN1_CLASS_UNIVERSAL or
 | 
					
						
							|  |  |  |             // (if constant is present) FILE_ASN1_CLASS_CONTEXT_SPECIFIC
 | 
					
						
							|  |  |  |             'class'    => FILE_ASN1_CLASS_APPLICATION, | 
					
						
							|  |  |  |             'cast'     => 2, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'numeric'   => array('type' => FILE_ASN1_TYPE_NUMERIC_STRING), | 
					
						
							|  |  |  |                 'printable' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $CountryName = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             // if class isn't present it's assumed to be FILE_ASN1_CLASS_UNIVERSAL or
 | 
					
						
							|  |  |  |             // (if constant is present) FILE_ASN1_CLASS_CONTEXT_SPECIFIC
 | 
					
						
							|  |  |  |             'class'    => FILE_ASN1_CLASS_APPLICATION, | 
					
						
							|  |  |  |             'cast'     => 1, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'x121-dcc-code'        => array('type' => FILE_ASN1_TYPE_NUMERIC_STRING), | 
					
						
							|  |  |  |                 'iso-3166-alpha2-code' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $AnotherName = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                  'type-id' => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER), | 
					
						
							|  |  |  |                  'value'   => array( | 
					
						
							|  |  |  |                                   'type' => FILE_ASN1_TYPE_ANY, | 
					
						
							|  |  |  |                                   'constant' => 0, | 
					
						
							|  |  |  |                                   'optional' => true, | 
					
						
							|  |  |  |                                   'explicit' => true | 
					
						
							|  |  |  |                               ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $ExtensionAttribute = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                  'extension-attribute-type'  => array( | 
					
						
							|  |  |  |                                                     'type' => FILE_ASN1_TYPE_PRINTABLE_STRING, | 
					
						
							|  |  |  |                                                     'constant' => 0, | 
					
						
							|  |  |  |                                                     'optional' => true, | 
					
						
							|  |  |  |                                                     'implicit' => true | 
					
						
							|  |  |  |                                                 ), | 
					
						
							|  |  |  |                  'extension-attribute-value' => array( | 
					
						
							|  |  |  |                                                     'type' => FILE_ASN1_TYPE_ANY, | 
					
						
							|  |  |  |                                                     'constant' => 1, | 
					
						
							|  |  |  |                                                     'optional' => true, | 
					
						
							|  |  |  |                                                     'explicit' => true | 
					
						
							|  |  |  |                                                 ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $ExtensionAttributes = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SET, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => 256, // ub-extension-attributes
 | 
					
						
							|  |  |  |             'children' => $ExtensionAttribute | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $BuiltInDomainDefinedAttribute = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                  'type'  => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING), | 
					
						
							|  |  |  |                  'value' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $BuiltInDomainDefinedAttributes = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => 4, // ub-domain-defined-attributes
 | 
					
						
							|  |  |  |             'children' => $BuiltInDomainDefinedAttribute | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $BuiltInStandardAttributes =  array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'country-name'               => array('optional' => true) + $CountryName, | 
					
						
							|  |  |  |                 'administration-domain-name' => array('optional' => true) + $AdministrationDomainName, | 
					
						
							|  |  |  |                 'network-address'            => array( | 
					
						
							|  |  |  |                                                  'constant' => 0, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $NetworkAddress, | 
					
						
							|  |  |  |                 'terminal-identifier'        => array( | 
					
						
							|  |  |  |                                                  'constant' => 1, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $TerminalIdentifier, | 
					
						
							|  |  |  |                 'private-domain-name'        => array( | 
					
						
							|  |  |  |                                                  'constant' => 2, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'explicit' => true | 
					
						
							|  |  |  |                                                ) + $PrivateDomainName, | 
					
						
							|  |  |  |                 'organization-name'          => array( | 
					
						
							|  |  |  |                                                  'constant' => 3, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $OrganizationName, | 
					
						
							|  |  |  |                 'numeric-user-identifier'    => array( | 
					
						
							|  |  |  |                                                  'constant' => 4, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $NumericUserIdentifier, | 
					
						
							|  |  |  |                 'personal-name'              => array( | 
					
						
							|  |  |  |                                                  'constant' => 5, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $PersonalName, | 
					
						
							|  |  |  |                 'organizational-unit-names'  => array( | 
					
						
							|  |  |  |                                                  'constant' => 6, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $OrganizationalUnitNames | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $ORAddress = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                  'built-in-standard-attributes'       => $BuiltInStandardAttributes, | 
					
						
							|  |  |  |                  'built-in-domain-defined-attributes' => array('optional' => true) + $BuiltInDomainDefinedAttributes, | 
					
						
							|  |  |  |                  'extension-attributes'               => array('optional' => true) + $ExtensionAttributes | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $EDIPartyName = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                  'nameAssigner' => array( | 
					
						
							|  |  |  |                                     'constant' => 0, | 
					
						
							|  |  |  |                                     'optional' => true, | 
					
						
							|  |  |  |                                     'implicit' => true | 
					
						
							|  |  |  |                                 ) + $this->DirectoryString, | 
					
						
							|  |  |  |                  // partyName is technically required but File_ASN1 doesn't currently support non-optional constants and
 | 
					
						
							|  |  |  |                  // setting it to optional gets the job done in any event.
 | 
					
						
							|  |  |  |                  'partyName'    => array( | 
					
						
							|  |  |  |                                     'constant' => 1, | 
					
						
							|  |  |  |                                     'optional' => true, | 
					
						
							|  |  |  |                                     'implicit' => true | 
					
						
							|  |  |  |                                 ) + $this->DirectoryString | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $GeneralName = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'otherName'                 => array( | 
					
						
							|  |  |  |                                                  'constant' => 0, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $AnotherName, | 
					
						
							|  |  |  |                 'rfc822Name'                => array( | 
					
						
							|  |  |  |                                                  'type' => FILE_ASN1_TYPE_IA5_STRING, | 
					
						
							|  |  |  |                                                  'constant' => 1, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ), | 
					
						
							|  |  |  |                 'dNSName'                   => array( | 
					
						
							|  |  |  |                                                  'type' => FILE_ASN1_TYPE_IA5_STRING, | 
					
						
							|  |  |  |                                                  'constant' => 2, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ), | 
					
						
							|  |  |  |                 'x400Address'               => array( | 
					
						
							|  |  |  |                                                  'constant' => 3, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $ORAddress, | 
					
						
							|  |  |  |                 'directoryName'             => array( | 
					
						
							|  |  |  |                                                  'constant' => 4, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'explicit' => true | 
					
						
							|  |  |  |                                                ) + $this->Name, | 
					
						
							|  |  |  |                 'ediPartyName'              => array( | 
					
						
							|  |  |  |                                                  'constant' => 5, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $EDIPartyName, | 
					
						
							|  |  |  |                 'uniformResourceIdentifier' => array( | 
					
						
							|  |  |  |                                                  'type' => FILE_ASN1_TYPE_IA5_STRING, | 
					
						
							|  |  |  |                                                  'constant' => 6, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ), | 
					
						
							|  |  |  |                 'iPAddress'                 => array( | 
					
						
							|  |  |  |                                                  'type' => FILE_ASN1_TYPE_OCTET_STRING, | 
					
						
							|  |  |  |                                                  'constant' => 7, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ), | 
					
						
							|  |  |  |                 'registeredID'              => array( | 
					
						
							|  |  |  |                                                  'type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER, | 
					
						
							|  |  |  |                                                  'constant' => 8, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $GeneralNames = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => $GeneralName | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->IssuerAltName = $GeneralNames; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $ReasonFlags = array( | 
					
						
							|  |  |  |             'type'    => FILE_ASN1_TYPE_BIT_STRING, | 
					
						
							|  |  |  |             'mapping' => array( | 
					
						
							|  |  |  |                 'unused', | 
					
						
							|  |  |  |                 'keyCompromise', | 
					
						
							|  |  |  |                 'cACompromise', | 
					
						
							|  |  |  |                 'affiliationChanged', | 
					
						
							|  |  |  |                 'superseded', | 
					
						
							|  |  |  |                 'cessationOfOperation', | 
					
						
							|  |  |  |                 'certificateHold', | 
					
						
							|  |  |  |                 'privilegeWithdrawn', | 
					
						
							|  |  |  |                 'aACompromise' | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $DistributionPointName = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'fullName'                => array( | 
					
						
							|  |  |  |                                                  'constant' => 0, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                        ) + $GeneralNames, | 
					
						
							|  |  |  |                 'nameRelativeToCRLIssuer' => array( | 
					
						
							|  |  |  |                                                  'constant' => 1, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                        ) + $this->RelativeDistinguishedName | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $DistributionPoint = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'distributionPoint' => array( | 
					
						
							|  |  |  |                                                  'constant' => 0, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'explicit' => true | 
					
						
							|  |  |  |                                        ) + $DistributionPointName, | 
					
						
							|  |  |  |                 'reasons'           => array( | 
					
						
							|  |  |  |                                                  'constant' => 1, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                        ) + $ReasonFlags, | 
					
						
							|  |  |  |                 'cRLIssuer'         => array( | 
					
						
							|  |  |  |                                                  'constant' => 2, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                        ) + $GeneralNames | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->CRLDistributionPoints = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => $DistributionPoint | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->AuthorityKeyIdentifier = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'keyIdentifier'             => array( | 
					
						
							|  |  |  |                                                  'constant' => 0, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $this->KeyIdentifier, | 
					
						
							|  |  |  |                 'authorityCertIssuer'       => array( | 
					
						
							|  |  |  |                                                  'constant' => 1, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $GeneralNames, | 
					
						
							|  |  |  |                 'authorityCertSerialNumber' => array( | 
					
						
							|  |  |  |                                                  'constant' => 2, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true | 
					
						
							|  |  |  |                                                ) + $CertificateSerialNumber | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $PolicyQualifierId = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $PolicyQualifierInfo = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'policyQualifierId' => $PolicyQualifierId, | 
					
						
							|  |  |  |                 'qualifier'         => array('type' => FILE_ASN1_TYPE_ANY) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $CertPolicyId = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $PolicyInformation = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'policyIdentifier' => $CertPolicyId, | 
					
						
							|  |  |  |                 'policyQualifiers' => array( | 
					
						
							|  |  |  |                                           'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |                                           'min'      => 0, | 
					
						
							|  |  |  |                                           'max'      => -1, | 
					
						
							|  |  |  |                                           'optional' => true, | 
					
						
							|  |  |  |                                           'children' => $PolicyQualifierInfo | 
					
						
							|  |  |  |                                       ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->CertificatePolicies = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => $PolicyInformation | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->PolicyMappings = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                               'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |                               'children' => array( | 
					
						
							|  |  |  |                                   'issuerDomainPolicy' => $CertPolicyId, | 
					
						
							|  |  |  |                                   'subjectDomainPolicy' => $CertPolicyId | 
					
						
							|  |  |  |                               ) | 
					
						
							|  |  |  |                        ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $KeyPurposeId = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->ExtKeyUsageSyntax = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => $KeyPurposeId | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $AccessDescription = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'accessMethod'   => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER), | 
					
						
							|  |  |  |                 'accessLocation' => $GeneralName | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->AuthorityInfoAccessSyntax = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => $AccessDescription | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->SubjectAltName = $GeneralNames; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->PrivateKeyUsagePeriod = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'notBefore' => array( | 
					
						
							|  |  |  |                                                  'constant' => 0, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true, | 
					
						
							|  |  |  |                                                  'type' => FILE_ASN1_TYPE_GENERALIZED_TIME), | 
					
						
							|  |  |  |                 'notAfter'  => array( | 
					
						
							|  |  |  |                                                  'constant' => 1, | 
					
						
							|  |  |  |                                                  'optional' => true, | 
					
						
							|  |  |  |                                                  'implicit' => true, | 
					
						
							|  |  |  |                                                  'type' => FILE_ASN1_TYPE_GENERALIZED_TIME) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $BaseDistance = array('type' => FILE_ASN1_TYPE_INTEGER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $GeneralSubtree = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'base'    => $GeneralName, | 
					
						
							|  |  |  |                 'minimum' => array( | 
					
						
							|  |  |  |                                  'constant' => 0, | 
					
						
							|  |  |  |                                  'optional' => true, | 
					
						
							|  |  |  |                                  'implicit' => true, | 
					
						
							|  |  |  |                                  'default' => new Math_BigInteger(0) | 
					
						
							|  |  |  |                              ) + $BaseDistance, | 
					
						
							|  |  |  |                 'maximum' => array( | 
					
						
							|  |  |  |                                  'constant' => 1, | 
					
						
							|  |  |  |                                  'optional' => true, | 
					
						
							|  |  |  |                                  'implicit' => true, | 
					
						
							|  |  |  |                              ) + $BaseDistance | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $GeneralSubtrees = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => $GeneralSubtree | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->NameConstraints = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'permittedSubtrees' => array( | 
					
						
							|  |  |  |                                            'constant' => 0, | 
					
						
							|  |  |  |                                            'optional' => true, | 
					
						
							|  |  |  |                                            'implicit' => true | 
					
						
							|  |  |  |                                        ) + $GeneralSubtrees, | 
					
						
							|  |  |  |                 'excludedSubtrees'  => array( | 
					
						
							|  |  |  |                                            'constant' => 1, | 
					
						
							|  |  |  |                                            'optional' => true, | 
					
						
							|  |  |  |                                            'implicit' => true | 
					
						
							|  |  |  |                                        ) + $GeneralSubtrees | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->CPSuri = array('type' => FILE_ASN1_TYPE_IA5_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $DisplayText = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_CHOICE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'ia5String'     => array('type' => FILE_ASN1_TYPE_IA5_STRING), | 
					
						
							|  |  |  |                 'visibleString' => array('type' => FILE_ASN1_TYPE_VISIBLE_STRING), | 
					
						
							|  |  |  |                 'bmpString'     => array('type' => FILE_ASN1_TYPE_BMP_STRING), | 
					
						
							|  |  |  |                 'utf8String'    => array('type' => FILE_ASN1_TYPE_UTF8_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $NoticeReference = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'organization'  => $DisplayText, | 
					
						
							|  |  |  |                 'noticeNumbers' => array( | 
					
						
							|  |  |  |                                        'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |                                        'min'      => 1, | 
					
						
							|  |  |  |                                        'max'      => 200, | 
					
						
							|  |  |  |                                        'children' => array('type' => FILE_ASN1_TYPE_INTEGER) | 
					
						
							|  |  |  |                                    ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->UserNotice = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'noticeRef' => array( | 
					
						
							|  |  |  |                                            'optional' => true, | 
					
						
							|  |  |  |                                            'implicit' => true | 
					
						
							|  |  |  |                                        ) + $NoticeReference, | 
					
						
							|  |  |  |                 'explicitText'  => array( | 
					
						
							|  |  |  |                                            'optional' => true, | 
					
						
							|  |  |  |                                            'implicit' => true | 
					
						
							|  |  |  |                                        ) + $DisplayText | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // mapping is from <http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html>
 | 
					
						
							|  |  |  |         $this->netscape_cert_type = array( | 
					
						
							|  |  |  |             'type'    => FILE_ASN1_TYPE_BIT_STRING, | 
					
						
							|  |  |  |             'mapping' => array( | 
					
						
							|  |  |  |                 'SSLClient', | 
					
						
							|  |  |  |                 'SSLServer', | 
					
						
							|  |  |  |                 'Email', | 
					
						
							|  |  |  |                 'ObjectSigning', | 
					
						
							|  |  |  |                 'Reserved', | 
					
						
							|  |  |  |                 'SSLCA', | 
					
						
							|  |  |  |                 'EmailCA', | 
					
						
							|  |  |  |                 'ObjectSigningCA' | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->netscape_comment = array('type' => FILE_ASN1_TYPE_IA5_STRING); | 
					
						
							|  |  |  |         $this->netscape_ca_policy_url = array('type' => FILE_ASN1_TYPE_IA5_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // attribute is used in RFC2986 but we're using the RFC5280 definition
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $Attribute = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'type' => $AttributeType, | 
					
						
							|  |  |  |                 'value'=> array( | 
					
						
							|  |  |  |                               'type'     => FILE_ASN1_TYPE_SET, | 
					
						
							|  |  |  |                               'min'      => 1, | 
					
						
							|  |  |  |                               'max'      => -1, | 
					
						
							|  |  |  |                               'children' => $this->AttributeValue | 
					
						
							|  |  |  |                           ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // adapted from <http://tools.ietf.org/html/rfc2986>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $Attributes = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SET, | 
					
						
							|  |  |  |             'min'      => 1, | 
					
						
							|  |  |  |             'max'      => -1, | 
					
						
							|  |  |  |             'children' => $Attribute | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $CertificationRequestInfo = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'version'       => array( | 
					
						
							|  |  |  |                                        'type' => FILE_ASN1_TYPE_INTEGER, | 
					
						
							|  |  |  |                                        'mapping' => array('v1') | 
					
						
							|  |  |  |                                    ), | 
					
						
							|  |  |  |                 'subject'       => $this->Name, | 
					
						
							|  |  |  |                 'subjectPKInfo' => $SubjectPublicKeyInfo, | 
					
						
							|  |  |  |                 'attributes'    => array( | 
					
						
							|  |  |  |                                        'constant' => 0, | 
					
						
							|  |  |  |                                        'optional' => true, | 
					
						
							|  |  |  |                                        'implicit' => true | 
					
						
							|  |  |  |                                    ) + $Attributes, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->CertificationRequest = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'certificationRequestInfo' => $CertificationRequestInfo, | 
					
						
							|  |  |  |                 'signatureAlgorithm'       => $AlgorithmIdentifier, | 
					
						
							|  |  |  |                 'signature'                => array('type' => FILE_ASN1_TYPE_BIT_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $RevokedCertificate = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                               'userCertificate'    => $CertificateSerialNumber, | 
					
						
							|  |  |  |                               'revocationDate'     => $Time, | 
					
						
							|  |  |  |                               'crlEntryExtensions' => array( | 
					
						
							|  |  |  |                                                           'optional' => true | 
					
						
							|  |  |  |                                                       ) + $this->Extensions | 
					
						
							|  |  |  |                           ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $TBSCertList = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'version'             => array( | 
					
						
							|  |  |  |                                              'optional' => true, | 
					
						
							|  |  |  |                                              'default'  => 'v1' | 
					
						
							|  |  |  |                                          ) + $Version, | 
					
						
							|  |  |  |                 'signature'           => $AlgorithmIdentifier, | 
					
						
							|  |  |  |                 'issuer'              => $this->Name, | 
					
						
							|  |  |  |                 'thisUpdate'          => $Time, | 
					
						
							|  |  |  |                 'nextUpdate'          => array( | 
					
						
							|  |  |  |                                              'optional' => true | 
					
						
							|  |  |  |                                          ) + $Time, | 
					
						
							|  |  |  |                 'revokedCertificates' => array( | 
					
						
							|  |  |  |                                              'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |                                              'optional' => true, | 
					
						
							|  |  |  |                                              'min'      => 0, | 
					
						
							|  |  |  |                                              'max'      => -1, | 
					
						
							|  |  |  |                                              'children' => $RevokedCertificate | 
					
						
							|  |  |  |                                          ), | 
					
						
							|  |  |  |                 'crlExtensions'       => array( | 
					
						
							|  |  |  |                                              'constant' => 0, | 
					
						
							|  |  |  |                                              'optional' => true, | 
					
						
							|  |  |  |                                              'explicit' => true | 
					
						
							|  |  |  |                                          ) + $this->Extensions | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->CertificateList = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'tbsCertList'        => $TBSCertList, | 
					
						
							|  |  |  |                 'signatureAlgorithm' => $AlgorithmIdentifier, | 
					
						
							|  |  |  |                 'signature'          => array('type' => FILE_ASN1_TYPE_BIT_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->CRLNumber = array('type' => FILE_ASN1_TYPE_INTEGER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->CRLReason = array('type' => FILE_ASN1_TYPE_ENUMERATED, | 
					
						
							|  |  |  |            'mapping' => array( | 
					
						
							|  |  |  |                             'unspecified', | 
					
						
							|  |  |  |                             'keyCompromise', | 
					
						
							|  |  |  |                             'cACompromise', | 
					
						
							|  |  |  |                             'affiliationChanged', | 
					
						
							|  |  |  |                             'superseded', | 
					
						
							|  |  |  |                             'cessationOfOperation', | 
					
						
							|  |  |  |                             'certificateHold', | 
					
						
							|  |  |  |                             // Value 7 is not used.
 | 
					
						
							|  |  |  |                             8 => 'removeFromCRL', | 
					
						
							|  |  |  |                             'privilegeWithdrawn', | 
					
						
							|  |  |  |                             'aACompromise' | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->IssuingDistributionPoint = array('type' => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'distributionPoint'          => array( | 
					
						
							|  |  |  |                                                     'constant' => 0, | 
					
						
							|  |  |  |                                                     'optional' => true, | 
					
						
							|  |  |  |                                                     'explicit' => true | 
					
						
							|  |  |  |                                                 ) + $DistributionPointName, | 
					
						
							|  |  |  |                 'onlyContainsUserCerts'      => array( | 
					
						
							|  |  |  |                                                     'type'     => FILE_ASN1_TYPE_BOOLEAN, | 
					
						
							|  |  |  |                                                     'constant' => 1, | 
					
						
							|  |  |  |                                                     'optional' => true, | 
					
						
							|  |  |  |                                                     'default'  => false, | 
					
						
							|  |  |  |                                                     'implicit' => true | 
					
						
							|  |  |  |                                                 ), | 
					
						
							|  |  |  |                 'onlyContainsCACerts'        => array( | 
					
						
							|  |  |  |                                                     'type'     => FILE_ASN1_TYPE_BOOLEAN, | 
					
						
							|  |  |  |                                                     'constant' => 2, | 
					
						
							|  |  |  |                                                     'optional' => true, | 
					
						
							|  |  |  |                                                     'default'  => false, | 
					
						
							|  |  |  |                                                     'implicit' => true | 
					
						
							|  |  |  |                                                 ), | 
					
						
							|  |  |  |                 'onlySomeReasons'           => array( | 
					
						
							|  |  |  |                                                     'constant' => 3, | 
					
						
							|  |  |  |                                                     'optional' => true, | 
					
						
							|  |  |  |                                                     'implicit' => true | 
					
						
							|  |  |  |                                                 ) + $ReasonFlags, | 
					
						
							|  |  |  |                 'indirectCRL'               => array( | 
					
						
							|  |  |  |                                                     'type'     => FILE_ASN1_TYPE_BOOLEAN, | 
					
						
							|  |  |  |                                                     'constant' => 4, | 
					
						
							|  |  |  |                                                     'optional' => true, | 
					
						
							|  |  |  |                                                     'default'  => false, | 
					
						
							|  |  |  |                                                     'implicit' => true | 
					
						
							|  |  |  |                                                 ), | 
					
						
							|  |  |  |                 'onlyContainsAttributeCerts' => array( | 
					
						
							|  |  |  |                                                     'type'     => FILE_ASN1_TYPE_BOOLEAN, | 
					
						
							|  |  |  |                                                     'constant' => 5, | 
					
						
							|  |  |  |                                                     'optional' => true, | 
					
						
							|  |  |  |                                                     'default'  => false, | 
					
						
							|  |  |  |                                                     'implicit' => true | 
					
						
							|  |  |  |                                                 ) | 
					
						
							|  |  |  |                           ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->InvalidityDate = array('type' => FILE_ASN1_TYPE_GENERALIZED_TIME); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->CertificateIssuer = $GeneralNames; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->HoldInstructionCode = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $PublicKeyAndChallenge = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'spki'      => $SubjectPublicKeyInfo, | 
					
						
							|  |  |  |                 'challenge' => array('type' => FILE_ASN1_TYPE_IA5_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->SignedPublicKeyAndChallenge = array( | 
					
						
							|  |  |  |             'type'     => FILE_ASN1_TYPE_SEQUENCE, | 
					
						
							|  |  |  |             'children' => array( | 
					
						
							|  |  |  |                 'publicKeyAndChallenge' => $PublicKeyAndChallenge, | 
					
						
							|  |  |  |                 'signatureAlgorithm'    => $AlgorithmIdentifier, | 
					
						
							|  |  |  |                 'signature'             => array('type' => FILE_ASN1_TYPE_BIT_STRING) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2
 | 
					
						
							|  |  |  |         $this->oids = array( | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7' => 'id-pkix', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.1' => 'id-pe', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.2' => 'id-qt', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.3' => 'id-kp', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.48' => 'id-ad', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.2.1' => 'id-qt-cps', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.2.2' => 'id-qt-unotice', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.48.1' =>'id-ad-ocsp', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.48.2' => 'id-ad-caIssuers', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.48.3' => 'id-ad-timeStamping', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.48.5' => 'id-ad-caRepository', | 
					
						
							|  |  |  |             '2.5.4' => 'id-at', | 
					
						
							|  |  |  |             '2.5.4.41' => 'id-at-name', | 
					
						
							|  |  |  |             '2.5.4.4' => 'id-at-surname', | 
					
						
							|  |  |  |             '2.5.4.42' => 'id-at-givenName', | 
					
						
							|  |  |  |             '2.5.4.43' => 'id-at-initials', | 
					
						
							|  |  |  |             '2.5.4.44' => 'id-at-generationQualifier', | 
					
						
							|  |  |  |             '2.5.4.3' => 'id-at-commonName', | 
					
						
							|  |  |  |             '2.5.4.7' => 'id-at-localityName', | 
					
						
							|  |  |  |             '2.5.4.8' => 'id-at-stateOrProvinceName', | 
					
						
							|  |  |  |             '2.5.4.10' => 'id-at-organizationName', | 
					
						
							|  |  |  |             '2.5.4.11' => 'id-at-organizationalUnitName', | 
					
						
							|  |  |  |             '2.5.4.12' => 'id-at-title', | 
					
						
							|  |  |  |             '2.5.4.13' => 'id-at-description', | 
					
						
							|  |  |  |             '2.5.4.46' => 'id-at-dnQualifier', | 
					
						
							|  |  |  |             '2.5.4.6' => 'id-at-countryName', | 
					
						
							|  |  |  |             '2.5.4.5' => 'id-at-serialNumber', | 
					
						
							|  |  |  |             '2.5.4.65' => 'id-at-pseudonym', | 
					
						
							|  |  |  |             '2.5.4.17' => 'id-at-postalCode', | 
					
						
							|  |  |  |             '2.5.4.9' => 'id-at-streetAddress', | 
					
						
							|  |  |  |             '2.5.4.45' => 'id-at-uniqueIdentifier', | 
					
						
							|  |  |  |             '2.5.4.72' => 'id-at-role', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             '0.9.2342.19200300.100.1.25' => 'id-domainComponent', | 
					
						
							|  |  |  |             '1.2.840.113549.1.9' => 'pkcs-9', | 
					
						
							|  |  |  |             '1.2.840.113549.1.9.1' => 'pkcs-9-at-emailAddress', | 
					
						
							|  |  |  |             '2.5.29' => 'id-ce', | 
					
						
							|  |  |  |             '2.5.29.35' => 'id-ce-authorityKeyIdentifier', | 
					
						
							|  |  |  |             '2.5.29.14' => 'id-ce-subjectKeyIdentifier', | 
					
						
							|  |  |  |             '2.5.29.15' => 'id-ce-keyUsage', | 
					
						
							|  |  |  |             '2.5.29.16' => 'id-ce-privateKeyUsagePeriod', | 
					
						
							|  |  |  |             '2.5.29.32' => 'id-ce-certificatePolicies', | 
					
						
							|  |  |  |             '2.5.29.32.0' => 'anyPolicy', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             '2.5.29.33' => 'id-ce-policyMappings', | 
					
						
							|  |  |  |             '2.5.29.17' => 'id-ce-subjectAltName', | 
					
						
							|  |  |  |             '2.5.29.18' => 'id-ce-issuerAltName', | 
					
						
							|  |  |  |             '2.5.29.9' => 'id-ce-subjectDirectoryAttributes', | 
					
						
							|  |  |  |             '2.5.29.19' => 'id-ce-basicConstraints', | 
					
						
							|  |  |  |             '2.5.29.30' => 'id-ce-nameConstraints', | 
					
						
							|  |  |  |             '2.5.29.36' => 'id-ce-policyConstraints', | 
					
						
							|  |  |  |             '2.5.29.31' => 'id-ce-cRLDistributionPoints', | 
					
						
							|  |  |  |             '2.5.29.37' => 'id-ce-extKeyUsage', | 
					
						
							|  |  |  |             '2.5.29.37.0' => 'anyExtendedKeyUsage', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.3.1' => 'id-kp-serverAuth', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.3.2' => 'id-kp-clientAuth', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.3.3' => 'id-kp-codeSigning', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.3.4' => 'id-kp-emailProtection', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.3.8' => 'id-kp-timeStamping', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.3.9' => 'id-kp-OCSPSigning', | 
					
						
							|  |  |  |             '2.5.29.54' => 'id-ce-inhibitAnyPolicy', | 
					
						
							|  |  |  |             '2.5.29.46' => 'id-ce-freshestCRL', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.1.1' => 'id-pe-authorityInfoAccess', | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.1.11' => 'id-pe-subjectInfoAccess', | 
					
						
							|  |  |  |             '2.5.29.20' => 'id-ce-cRLNumber', | 
					
						
							|  |  |  |             '2.5.29.28' => 'id-ce-issuingDistributionPoint', | 
					
						
							|  |  |  |             '2.5.29.27' => 'id-ce-deltaCRLIndicator', | 
					
						
							|  |  |  |             '2.5.29.21' => 'id-ce-cRLReasons', | 
					
						
							|  |  |  |             '2.5.29.29' => 'id-ce-certificateIssuer', | 
					
						
							|  |  |  |             '2.5.29.23' => 'id-ce-holdInstructionCode', | 
					
						
							|  |  |  |             '1.2.840.10040.2' => 'holdInstruction', | 
					
						
							|  |  |  |             '1.2.840.10040.2.1' => 'id-holdinstruction-none', | 
					
						
							|  |  |  |             '1.2.840.10040.2.2' => 'id-holdinstruction-callissuer', | 
					
						
							|  |  |  |             '1.2.840.10040.2.3' => 'id-holdinstruction-reject', | 
					
						
							|  |  |  |             '2.5.29.24' => 'id-ce-invalidityDate', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             '1.2.840.113549.2.2' => 'md2', | 
					
						
							|  |  |  |             '1.2.840.113549.2.5' => 'md5', | 
					
						
							|  |  |  |             '1.3.14.3.2.26' => 'id-sha1', | 
					
						
							|  |  |  |             '1.2.840.10040.4.1' => 'id-dsa', | 
					
						
							|  |  |  |             '1.2.840.10040.4.3' => 'id-dsa-with-sha1', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1' => 'pkcs-1', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.1' => 'rsaEncryption', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.2' => 'md2WithRSAEncryption', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.4' => 'md5WithRSAEncryption', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.5' => 'sha1WithRSAEncryption', | 
					
						
							|  |  |  |             '1.2.840.10046.2.1' => 'dhpublicnumber', | 
					
						
							|  |  |  |             '2.16.840.1.101.2.1.1.22' => 'id-keyExchangeAlgorithm', | 
					
						
							|  |  |  |             '1.2.840.10045' => 'ansi-X9-62', | 
					
						
							|  |  |  |             '1.2.840.10045.4' => 'id-ecSigType', | 
					
						
							|  |  |  |             '1.2.840.10045.4.1' => 'ecdsa-with-SHA1', | 
					
						
							|  |  |  |             '1.2.840.10045.1' => 'id-fieldType', | 
					
						
							|  |  |  |             '1.2.840.10045.1.1' => 'prime-field', | 
					
						
							|  |  |  |             '1.2.840.10045.1.2' => 'characteristic-two-field', | 
					
						
							|  |  |  |             '1.2.840.10045.1.2.3' => 'id-characteristic-two-basis', | 
					
						
							|  |  |  |             '1.2.840.10045.1.2.3.1' => 'gnBasis', | 
					
						
							|  |  |  |             '1.2.840.10045.1.2.3.2' => 'tpBasis', | 
					
						
							|  |  |  |             '1.2.840.10045.1.2.3.3' => 'ppBasis', | 
					
						
							|  |  |  |             '1.2.840.10045.2' => 'id-publicKeyType', | 
					
						
							|  |  |  |             '1.2.840.10045.2.1' => 'id-ecPublicKey', | 
					
						
							|  |  |  |             '1.2.840.10045.3' => 'ellipticCurve', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0' => 'c-TwoCurve', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.1' => 'c2pnb163v1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.2' => 'c2pnb163v2', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.3' => 'c2pnb163v3', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.4' => 'c2pnb176w1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.5' => 'c2pnb191v1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.6' => 'c2pnb191v2', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.7' => 'c2pnb191v3', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.8' => 'c2pnb191v4', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.9' => 'c2pnb191v5', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.10' => 'c2pnb208w1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.11' => 'c2pnb239v1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.12' => 'c2pnb239v2', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.13' => 'c2pnb239v3', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.14' => 'c2pnb239v4', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.15' => 'c2pnb239v5', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.16' => 'c2pnb272w1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.17' => 'c2pnb304w1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.18' => 'c2pnb359v1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.19' => 'c2pnb368w1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.0.20' => 'c2pnb431r1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.1' => 'primeCurve', | 
					
						
							|  |  |  |             '1.2.840.10045.3.1.1' => 'prime192v1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.1.2' => 'prime192v2', | 
					
						
							|  |  |  |             '1.2.840.10045.3.1.3' => 'prime192v3', | 
					
						
							|  |  |  |             '1.2.840.10045.3.1.4' => 'prime239v1', | 
					
						
							|  |  |  |             '1.2.840.10045.3.1.5' => 'prime239v2', | 
					
						
							|  |  |  |             '1.2.840.10045.3.1.6' => 'prime239v3', | 
					
						
							|  |  |  |             '1.2.840.10045.3.1.7' => 'prime256v1', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.7' => 'id-RSAES-OAEP', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.9' => 'id-pSpecified', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.10' => 'id-RSASSA-PSS', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.8' => 'id-mgf1', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.14' => 'sha224WithRSAEncryption', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.11' => 'sha256WithRSAEncryption', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.12' => 'sha384WithRSAEncryption', | 
					
						
							|  |  |  |             '1.2.840.113549.1.1.13' => 'sha512WithRSAEncryption', | 
					
						
							|  |  |  |             '2.16.840.1.101.3.4.2.4' => 'id-sha224', | 
					
						
							|  |  |  |             '2.16.840.1.101.3.4.2.1' => 'id-sha256', | 
					
						
							|  |  |  |             '2.16.840.1.101.3.4.2.2' => 'id-sha384', | 
					
						
							|  |  |  |             '2.16.840.1.101.3.4.2.3' => 'id-sha512', | 
					
						
							|  |  |  |             '1.2.643.2.2.4' => 'id-GostR3411-94-with-GostR3410-94', | 
					
						
							|  |  |  |             '1.2.643.2.2.3' => 'id-GostR3411-94-with-GostR3410-2001', | 
					
						
							|  |  |  |             '1.2.643.2.2.20' => 'id-GostR3410-2001', | 
					
						
							|  |  |  |             '1.2.643.2.2.19' => 'id-GostR3410-94', | 
					
						
							|  |  |  |             // Netscape Object Identifiers from "Netscape Certificate Extensions"
 | 
					
						
							|  |  |  |             '2.16.840.1.113730' => 'netscape', | 
					
						
							|  |  |  |             '2.16.840.1.113730.1' => 'netscape-cert-extension', | 
					
						
							|  |  |  |             '2.16.840.1.113730.1.1' => 'netscape-cert-type', | 
					
						
							|  |  |  |             '2.16.840.1.113730.1.13' => 'netscape-comment', | 
					
						
							|  |  |  |             '2.16.840.1.113730.1.8' => 'netscape-ca-policy-url', | 
					
						
							|  |  |  |             // the following are X.509 extensions not supported by phpseclib
 | 
					
						
							|  |  |  |             '1.3.6.1.5.5.7.1.12' => 'id-pe-logotype', | 
					
						
							|  |  |  |             '1.2.840.113533.7.65.0' => 'entrustVersInfo', | 
					
						
							|  |  |  |             '2.16.840.1.113733.1.6.9' => 'verisignPrivate', | 
					
						
							|  |  |  |             // for Certificate Signing Requests
 | 
					
						
							|  |  |  |             // see http://tools.ietf.org/html/rfc2985
 | 
					
						
							|  |  |  |             '1.2.840.113549.1.9.2' => 'pkcs-9-at-unstructuredName', // PKCS #9 unstructured name
 | 
					
						
							|  |  |  |             '1.2.840.113549.1.9.7' => 'pkcs-9-at-challengePassword', // Challenge password for certificate revocations
 | 
					
						
							|  |  |  |             '1.2.840.113549.1.9.14' => 'pkcs-9-at-extensionRequest' // Certificate extension request
 | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Load X.509 certificate | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Returns an associative array describing the X.509 cert or a false if the cert failed to load | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $cert | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function loadX509($cert) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_array($cert) && isset($cert['tbsCertificate'])) { | 
					
						
							|  |  |  |             unset($this->currentCert); | 
					
						
							|  |  |  |             unset($this->currentKeyIdentifier); | 
					
						
							|  |  |  |             $this->dn = $cert['tbsCertificate']['subject']; | 
					
						
							|  |  |  |             if (!isset($this->dn)) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $this->currentCert = $cert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier'); | 
					
						
							|  |  |  |             $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             unset($this->signatureSubject); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return $cert; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $cert = $this->_extractBER($cert); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($cert === false) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  |         $decoded = $asn1->decodeBER($cert); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($decoded)) { | 
					
						
							|  |  |  |             $x509 = $asn1->asn1map($decoded[0], $this->Certificate); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!isset($x509) || $x509 === false) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $key = &$x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']; | 
					
						
							|  |  |  |         $key = $this->_reformatKey($x509['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->currentCert = $x509; | 
					
						
							|  |  |  |         $this->dn = $x509['tbsCertificate']['subject']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier'); | 
					
						
							|  |  |  |         $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $x509; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Save X.509 certificate | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Array $cert | 
					
						
							|  |  |  |      * @param Integer $format optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return String | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function saveX509($cert, $format = FILE_X509_FORMAT_PEM) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_array($cert) || !isset($cert['tbsCertificate'])) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             // "case !$a: case !$b: break; default: whatever();" is the same thing as "if ($a && $b) whatever()"
 | 
					
						
							|  |  |  |             case !($algorithm = $this->_subArray($cert, 'tbsCertificate/subjectPublicKeyInfo/algorithm/algorithm')): | 
					
						
							|  |  |  |             case is_object($cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']): | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 switch ($algorithm) { | 
					
						
							|  |  |  |                     case 'rsaEncryption': | 
					
						
							|  |  |  |                         $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'] | 
					
						
							|  |  |  |                             = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']))); | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                         /* "[For RSA keys] the parameters field MUST have ASN.1 type NULL for this algorithm identifier." | 
					
						
							|  |  |  |                            -- https://tools.ietf.org/html/rfc3279#section-2.3.1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                            given that and the fact that RSA keys appear ot be the only key type for which the parameters field can be blank, | 
					
						
							|  |  |  |                            it seems like perhaps the ASN.1 description ought not say the parameters field is OPTIONAL, but whatever. | 
					
						
							|  |  |  |                          */ | 
					
						
							|  |  |  |                         $cert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = null; | 
					
						
							|  |  |  |                         // https://tools.ietf.org/html/rfc3279#section-2.2.1
 | 
					
						
							|  |  |  |                         $cert['signatureAlgorithm']['parameters'] = null; | 
					
						
							|  |  |  |                         $cert['tbsCertificate']['signature']['parameters'] = null; | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  |         $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $filters = array(); | 
					
						
							|  |  |  |         $type_utf8_string = array('type' => FILE_ASN1_TYPE_UTF8_STRING); | 
					
						
							|  |  |  |         $filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string; | 
					
						
							|  |  |  |         $filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string; | 
					
						
							|  |  |  |         $filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string; | 
					
						
							|  |  |  |         $filters['tbsCertificate']['subject']['rdnSequence']['value'] = $type_utf8_string; | 
					
						
							|  |  |  |         $filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = $type_utf8_string; | 
					
						
							|  |  |  |         $filters['signatureAlgorithm']['parameters'] = $type_utf8_string; | 
					
						
							|  |  |  |         $filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = $type_utf8_string; | 
					
						
							|  |  |  |         //$filters['policyQualifiers']['qualifier'] = $type_utf8_string;
 | 
					
						
							|  |  |  |         $filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string; | 
					
						
							|  |  |  |         $filters['directoryName']['rdnSequence']['value'] = $type_utf8_string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* in the case of policyQualifiers/qualifier, the type has to be FILE_ASN1_TYPE_IA5_STRING. | 
					
						
							|  |  |  |            FILE_ASN1_TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random | 
					
						
							|  |  |  |            characters. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         $filters['policyQualifiers']['qualifier'] | 
					
						
							|  |  |  |             = array('type' => FILE_ASN1_TYPE_IA5_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadFilters($filters); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->_mapOutExtensions($cert, 'tbsCertificate/extensions', $asn1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $cert = $asn1->encodeDER($cert, $this->Certificate); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($format) { | 
					
						
							|  |  |  |             case FILE_X509_FORMAT_DER: | 
					
						
							|  |  |  |                 return $cert; | 
					
						
							|  |  |  |             // case FILE_X509_FORMAT_PEM:
 | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(base64_encode($cert), 64) . '-----END CERTIFICATE-----'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Map extension values from octet string to extension-specific internal | 
					
						
							|  |  |  |      *   format. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Array ref $root | 
					
						
							|  |  |  |      * @param String $path | 
					
						
							|  |  |  |      * @param Object $asn1 | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _mapInExtensions(&$root, $path, $asn1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $extensions = &$this->_subArray($root, $path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($extensions)) { | 
					
						
							|  |  |  |             for ($i = 0; $i < count($extensions); $i++) { | 
					
						
							|  |  |  |                 $id = $extensions[$i]['extnId']; | 
					
						
							|  |  |  |                 $value = &$extensions[$i]['extnValue']; | 
					
						
							|  |  |  |                 $value = base64_decode($value); | 
					
						
							|  |  |  |                 $decoded = $asn1->decodeBER($value); | 
					
						
							|  |  |  |                 /* [extnValue] contains the DER encoding of an ASN.1 value | 
					
						
							|  |  |  |                    corresponding to the extension type identified by extnID */ | 
					
						
							|  |  |  |                 $map = $this->_getMapping($id); | 
					
						
							|  |  |  |                 if (!is_bool($map)) { | 
					
						
							|  |  |  |                     $mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => array($this, '_decodeIP'))); | 
					
						
							|  |  |  |                     $value = $mapped === false ? $decoded[0] : $mapped; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if ($id == 'id-ce-certificatePolicies') { | 
					
						
							|  |  |  |                         for ($j = 0; $j < count($value); $j++) { | 
					
						
							|  |  |  |                             if (!isset($value[$j]['policyQualifiers'])) { | 
					
						
							|  |  |  |                                 continue; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                             for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) { | 
					
						
							|  |  |  |                                 $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId']; | 
					
						
							|  |  |  |                                 $map = $this->_getMapping($subid); | 
					
						
							|  |  |  |                                 $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier']; | 
					
						
							|  |  |  |                                 if ($map !== false) { | 
					
						
							|  |  |  |                                     $decoded = $asn1->decodeBER($subvalue); | 
					
						
							|  |  |  |                                     $mapped = $asn1->asn1map($decoded[0], $map); | 
					
						
							|  |  |  |                                     $subvalue = $mapped === false ? $decoded[0] : $mapped; | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                     $value = base64_encode($value); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Map extension values from extension-specific internal format to | 
					
						
							|  |  |  |      *   octet string. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Array ref $root | 
					
						
							|  |  |  |      * @param String $path | 
					
						
							|  |  |  |      * @param Object $asn1 | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _mapOutExtensions(&$root, $path, $asn1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $extensions = &$this->_subArray($root, $path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($extensions)) { | 
					
						
							|  |  |  |             $size = count($extensions); | 
					
						
							|  |  |  |             for ($i = 0; $i < $size; $i++) { | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                 if (is_object($extensions[$i]) && strtolower(get_class($extensions[$i])) == 'file_asn1_element') { | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                 $id = $extensions[$i]['extnId']; | 
					
						
							|  |  |  |                 $value = &$extensions[$i]['extnValue']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 switch ($id) { | 
					
						
							|  |  |  |                     case 'id-ce-certificatePolicies': | 
					
						
							|  |  |  |                         for ($j = 0; $j < count($value); $j++) { | 
					
						
							|  |  |  |                             if (!isset($value[$j]['policyQualifiers'])) { | 
					
						
							|  |  |  |                                 continue; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                             for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) { | 
					
						
							|  |  |  |                                 $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId']; | 
					
						
							|  |  |  |                                 $map = $this->_getMapping($subid); | 
					
						
							|  |  |  |                                 $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier']; | 
					
						
							|  |  |  |                                 if ($map !== false) { | 
					
						
							|  |  |  |                                     // by default File_ASN1 will try to render qualifier as a FILE_ASN1_TYPE_IA5_STRING since it's
 | 
					
						
							|  |  |  |                                     // actual type is FILE_ASN1_TYPE_ANY
 | 
					
						
							|  |  |  |                                     $subvalue = new File_ASN1_Element($asn1->encodeDER($subvalue, $map)); | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 'id-ce-authorityKeyIdentifier': // use 00 as the serial number instead of an empty string
 | 
					
						
							|  |  |  |                         if (isset($value['authorityCertSerialNumber'])) { | 
					
						
							|  |  |  |                             if ($value['authorityCertSerialNumber']->toBytes() == '') { | 
					
						
							|  |  |  |                                 $temp = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | 2) . "\1\0"; | 
					
						
							|  |  |  |                                 $value['authorityCertSerialNumber'] = new File_ASN1_Element($temp); | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 /* [extnValue] contains the DER encoding of an ASN.1 value | 
					
						
							|  |  |  |                    corresponding to the extension type identified by extnID */ | 
					
						
							|  |  |  |                 $map = $this->_getMapping($id); | 
					
						
							|  |  |  |                 if (is_bool($map)) { | 
					
						
							|  |  |  |                     if (!$map) { | 
					
						
							|  |  |  |                         user_error($id . ' is not a currently supported extension'); | 
					
						
							|  |  |  |                         unset($extensions[$i]); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     $temp = $asn1->encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP'))); | 
					
						
							|  |  |  |                     $value = base64_encode($temp); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Map attribute values from ANY type to attribute-specific internal | 
					
						
							|  |  |  |      *   format. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Array ref $root | 
					
						
							|  |  |  |      * @param String $path | 
					
						
							|  |  |  |      * @param Object $asn1 | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _mapInAttributes(&$root, $path, $asn1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $attributes = &$this->_subArray($root, $path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($attributes)) { | 
					
						
							|  |  |  |             for ($i = 0; $i < count($attributes); $i++) { | 
					
						
							|  |  |  |                 $id = $attributes[$i]['type']; | 
					
						
							|  |  |  |                 /* $value contains the DER encoding of an ASN.1 value | 
					
						
							|  |  |  |                    corresponding to the attribute type identified by type */ | 
					
						
							|  |  |  |                 $map = $this->_getMapping($id); | 
					
						
							|  |  |  |                 if (is_array($attributes[$i]['value'])) { | 
					
						
							|  |  |  |                     $values = &$attributes[$i]['value']; | 
					
						
							|  |  |  |                     for ($j = 0; $j < count($values); $j++) { | 
					
						
							|  |  |  |                         $value = $asn1->encodeDER($values[$j], $this->AttributeValue); | 
					
						
							|  |  |  |                         $decoded = $asn1->decodeBER($value); | 
					
						
							|  |  |  |                         if (!is_bool($map)) { | 
					
						
							|  |  |  |                             $mapped = $asn1->asn1map($decoded[0], $map); | 
					
						
							|  |  |  |                             if ($mapped !== false) { | 
					
						
							|  |  |  |                                 $values[$j] = $mapped; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                             if ($id == 'pkcs-9-at-extensionRequest') { | 
					
						
							|  |  |  |                                 $this->_mapInExtensions($values, $j, $asn1); | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } elseif ($map) { | 
					
						
							|  |  |  |                             $values[$j] = base64_encode($value); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Map attribute values from attribute-specific internal format to | 
					
						
							|  |  |  |      *   ANY type. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Array ref $root | 
					
						
							|  |  |  |      * @param String $path | 
					
						
							|  |  |  |      * @param Object $asn1 | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _mapOutAttributes(&$root, $path, $asn1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $attributes = &$this->_subArray($root, $path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($attributes)) { | 
					
						
							|  |  |  |             $size = count($attributes); | 
					
						
							|  |  |  |             for ($i = 0; $i < $size; $i++) { | 
					
						
							|  |  |  |                 /* [value] contains the DER encoding of an ASN.1 value | 
					
						
							|  |  |  |                    corresponding to the attribute type identified by type */ | 
					
						
							|  |  |  |                 $id = $attributes[$i]['type']; | 
					
						
							|  |  |  |                 $map = $this->_getMapping($id); | 
					
						
							|  |  |  |                 if ($map === false) { | 
					
						
							|  |  |  |                     user_error($id . ' is not a currently supported attribute', E_USER_NOTICE); | 
					
						
							|  |  |  |                     unset($attributes[$i]); | 
					
						
							|  |  |  |                 } elseif (is_array($attributes[$i]['value'])) { | 
					
						
							|  |  |  |                     $values = &$attributes[$i]['value']; | 
					
						
							|  |  |  |                     for ($j = 0; $j < count($values); $j++) { | 
					
						
							|  |  |  |                         switch ($id) { | 
					
						
							|  |  |  |                             case 'pkcs-9-at-extensionRequest': | 
					
						
							|  |  |  |                                 $this->_mapOutExtensions($values, $j, $asn1); | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if (!is_bool($map)) { | 
					
						
							|  |  |  |                             $temp = $asn1->encodeDER($values[$j], $map); | 
					
						
							|  |  |  |                             $decoded = $asn1->decodeBER($temp); | 
					
						
							|  |  |  |                             $values[$j] = $asn1->asn1map($decoded[0], $this->AttributeValue); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Associate an extension ID to an extension mapping | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $extnId | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _getMapping($extnId) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_string($extnId)) { // eg. if it's a File_ASN1_Element object
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($extnId) { | 
					
						
							|  |  |  |             case 'id-ce-keyUsage': | 
					
						
							|  |  |  |                 return $this->KeyUsage; | 
					
						
							|  |  |  |             case 'id-ce-basicConstraints': | 
					
						
							|  |  |  |                 return $this->BasicConstraints; | 
					
						
							|  |  |  |             case 'id-ce-subjectKeyIdentifier': | 
					
						
							|  |  |  |                 return $this->KeyIdentifier; | 
					
						
							|  |  |  |             case 'id-ce-cRLDistributionPoints': | 
					
						
							|  |  |  |                 return $this->CRLDistributionPoints; | 
					
						
							|  |  |  |             case 'id-ce-authorityKeyIdentifier': | 
					
						
							|  |  |  |                 return $this->AuthorityKeyIdentifier; | 
					
						
							|  |  |  |             case 'id-ce-certificatePolicies': | 
					
						
							|  |  |  |                 return $this->CertificatePolicies; | 
					
						
							|  |  |  |             case 'id-ce-extKeyUsage': | 
					
						
							|  |  |  |                 return $this->ExtKeyUsageSyntax; | 
					
						
							|  |  |  |             case 'id-pe-authorityInfoAccess': | 
					
						
							|  |  |  |                 return $this->AuthorityInfoAccessSyntax; | 
					
						
							|  |  |  |             case 'id-ce-subjectAltName': | 
					
						
							|  |  |  |                 return $this->SubjectAltName; | 
					
						
							|  |  |  |             case 'id-ce-privateKeyUsagePeriod': | 
					
						
							|  |  |  |                 return $this->PrivateKeyUsagePeriod; | 
					
						
							|  |  |  |             case 'id-ce-issuerAltName': | 
					
						
							|  |  |  |                 return $this->IssuerAltName; | 
					
						
							|  |  |  |             case 'id-ce-policyMappings': | 
					
						
							|  |  |  |                 return $this->PolicyMappings; | 
					
						
							|  |  |  |             case 'id-ce-nameConstraints': | 
					
						
							|  |  |  |                 return $this->NameConstraints; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case 'netscape-cert-type': | 
					
						
							|  |  |  |                 return $this->netscape_cert_type; | 
					
						
							|  |  |  |             case 'netscape-comment': | 
					
						
							|  |  |  |                 return $this->netscape_comment; | 
					
						
							|  |  |  |             case 'netscape-ca-policy-url': | 
					
						
							|  |  |  |                 return $this->netscape_ca_policy_url; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // since id-qt-cps isn't a constructed type it will have already been decoded as a string by the time it gets
 | 
					
						
							|  |  |  |             // back around to asn1map() and we don't want it decoded again.
 | 
					
						
							|  |  |  |             //case 'id-qt-cps':
 | 
					
						
							|  |  |  |             //    return $this->CPSuri;
 | 
					
						
							|  |  |  |             case 'id-qt-unotice': | 
					
						
							|  |  |  |                 return $this->UserNotice; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // the following OIDs are unsupported but we don't want them to give notices when calling saveX509().
 | 
					
						
							|  |  |  |             case 'id-pe-logotype': // http://www.ietf.org/rfc/rfc3709.txt
 | 
					
						
							|  |  |  |             case 'entrustVersInfo': | 
					
						
							|  |  |  |             // http://support.microsoft.com/kb/287547
 | 
					
						
							|  |  |  |             case '1.3.6.1.4.1.311.20.2': // szOID_ENROLL_CERTTYPE_EXTENSION
 | 
					
						
							|  |  |  |             case '1.3.6.1.4.1.311.21.1': // szOID_CERTSRV_CA_VERSION
 | 
					
						
							|  |  |  |             // "SET Secure Electronic Transaction Specification"
 | 
					
						
							|  |  |  |             // http://www.maithean.com/docs/set_bk3.pdf
 | 
					
						
							|  |  |  |             case '2.23.42.7.0': // id-set-hashedRootKey
 | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // CSR attributes
 | 
					
						
							|  |  |  |             case 'pkcs-9-at-unstructuredName': | 
					
						
							|  |  |  |                 return $this->PKCS9String; | 
					
						
							|  |  |  |             case 'pkcs-9-at-challengePassword': | 
					
						
							|  |  |  |                 return $this->DirectoryString; | 
					
						
							|  |  |  |             case 'pkcs-9-at-extensionRequest': | 
					
						
							|  |  |  |                 return $this->Extensions; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // CRL extensions.
 | 
					
						
							|  |  |  |             case 'id-ce-cRLNumber': | 
					
						
							|  |  |  |                 return $this->CRLNumber; | 
					
						
							|  |  |  |             case 'id-ce-deltaCRLIndicator': | 
					
						
							|  |  |  |                 return $this->CRLNumber; | 
					
						
							|  |  |  |             case 'id-ce-issuingDistributionPoint': | 
					
						
							|  |  |  |                 return $this->IssuingDistributionPoint; | 
					
						
							|  |  |  |             case 'id-ce-freshestCRL': | 
					
						
							|  |  |  |                 return $this->CRLDistributionPoints; | 
					
						
							|  |  |  |             case 'id-ce-cRLReasons': | 
					
						
							|  |  |  |                 return $this->CRLReason; | 
					
						
							|  |  |  |             case 'id-ce-invalidityDate': | 
					
						
							|  |  |  |                 return $this->InvalidityDate; | 
					
						
							|  |  |  |             case 'id-ce-certificateIssuer': | 
					
						
							|  |  |  |                 return $this->CertificateIssuer; | 
					
						
							|  |  |  |             case 'id-ce-holdInstructionCode': | 
					
						
							|  |  |  |                 return $this->HoldInstructionCode; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Load an X.509 certificate as a certificate authority | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $cert | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function loadCA($cert) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $olddn = $this->dn; | 
					
						
							|  |  |  |         $oldcert = $this->currentCert; | 
					
						
							|  |  |  |         $oldsigsubj = $this->signatureSubject; | 
					
						
							|  |  |  |         $oldkeyid = $this->currentKeyIdentifier; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $cert = $this->loadX509($cert); | 
					
						
							|  |  |  |         if (!$cert) { | 
					
						
							|  |  |  |             $this->dn = $olddn; | 
					
						
							|  |  |  |             $this->currentCert = $oldcert; | 
					
						
							|  |  |  |             $this->signatureSubject = $oldsigsubj; | 
					
						
							|  |  |  |             $this->currentKeyIdentifier = $oldkeyid; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* From RFC5280 "PKIX Certificate and CRL Profile": | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            If the keyUsage extension is present, then the subject public key | 
					
						
							|  |  |  |            MUST NOT be used to verify signatures on certificates or CRLs unless | 
					
						
							|  |  |  |            the corresponding keyCertSign or cRLSign bit is set. */ | 
					
						
							|  |  |  |         //$keyUsage = $this->getExtension('id-ce-keyUsage');
 | 
					
						
							|  |  |  |         //if ($keyUsage && !in_array('keyCertSign', $keyUsage)) {
 | 
					
						
							|  |  |  |         //    return false;
 | 
					
						
							|  |  |  |         //}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* From RFC5280 "PKIX Certificate and CRL Profile": | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            The cA boolean indicates whether the certified public key may be used | 
					
						
							|  |  |  |            to verify certificate signatures.  If the cA boolean is not asserted, | 
					
						
							|  |  |  |            then the keyCertSign bit in the key usage extension MUST NOT be | 
					
						
							|  |  |  |            asserted.  If the basic constraints extension is not present in a | 
					
						
							|  |  |  |            version 3 certificate, or the extension is present but the cA boolean | 
					
						
							|  |  |  |            is not asserted, then the certified public key MUST NOT be used to | 
					
						
							|  |  |  |            verify certificate signatures. */ | 
					
						
							|  |  |  |         //$basicConstraints = $this->getExtension('id-ce-basicConstraints');
 | 
					
						
							|  |  |  |         //if (!$basicConstraints || !$basicConstraints['cA']) {
 | 
					
						
							|  |  |  |         //    return false;
 | 
					
						
							|  |  |  |         //}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->CAs[] = $cert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->dn = $olddn; | 
					
						
							|  |  |  |         $this->currentCert = $oldcert; | 
					
						
							|  |  |  |         $this->signatureSubject = $oldsigsubj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Validate an X.509 certificate against a URL | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * From RFC2818 "HTTP over TLS": | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Matching is performed using the matching rules specified by | 
					
						
							|  |  |  |      * [RFC2459].  If more than one identity of a given type is present in | 
					
						
							|  |  |  |      * the certificate (e.g., more than one dNSName name, a match in any one | 
					
						
							|  |  |  |      * of the set is considered acceptable.) Names may contain the wildcard | 
					
						
							|  |  |  |      * character * which is considered to match any single domain name | 
					
						
							|  |  |  |      * component or component fragment. E.g., *.a.com matches foo.a.com but | 
					
						
							|  |  |  |      * not bar.foo.a.com. f*.com matches foo.com but not bar.com. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $url | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function validateURL($url) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $components = parse_url($url); | 
					
						
							|  |  |  |         if (!isset($components['host'])) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($names = $this->getExtension('id-ce-subjectAltName')) { | 
					
						
							|  |  |  |             foreach ($names as $key => $value) { | 
					
						
							|  |  |  |                 $value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value); | 
					
						
							|  |  |  |                 switch ($key) { | 
					
						
							|  |  |  |                     case 'dNSName': | 
					
						
							|  |  |  |                         /* From RFC2818 "HTTP over TLS": | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                            If a subjectAltName extension of type dNSName is present, that MUST | 
					
						
							|  |  |  |                            be used as the identity. Otherwise, the (most specific) Common Name | 
					
						
							|  |  |  |                            field in the Subject field of the certificate MUST be used. Although | 
					
						
							|  |  |  |                            the use of the Common Name is existing practice, it is deprecated and | 
					
						
							|  |  |  |                            Certification Authorities are encouraged to use the dNSName instead. */ | 
					
						
							|  |  |  |                         if (preg_match('#^' . $value . '$#', $components['host'])) { | 
					
						
							|  |  |  |                             return true; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 'iPAddress': | 
					
						
							|  |  |  |                         /* From RFC2818 "HTTP over TLS": | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                            In some cases, the URI is specified as an IP address rather than a | 
					
						
							|  |  |  |                            hostname. In this case, the iPAddress subjectAltName must be present | 
					
						
							|  |  |  |                            in the certificate and must exactly match the IP in the URI. */ | 
					
						
							|  |  |  |                         if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) { | 
					
						
							|  |  |  |                             return true; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($value = $this->getDNProp('id-at-commonName')) { | 
					
						
							|  |  |  |             $value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value[0]); | 
					
						
							|  |  |  |             return preg_match('#^' . $value . '$#', $components['host']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Validate a date | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * If $date isn't defined it is assumed to be the current date. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Integer $date optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function validateDate($date = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!isset($date)) { | 
					
						
							|  |  |  |             $date = time(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore']; | 
					
						
							|  |  |  |         $notBefore = isset($notBefore['generalTime']) ? $notBefore['generalTime'] : $notBefore['utcTime']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter']; | 
					
						
							|  |  |  |         $notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case $date < @strtotime($notBefore): | 
					
						
							|  |  |  |             case $date > @strtotime($notAfter): | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Validate a signature | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Works on X.509 certs, CSR's and CRL's. | 
					
						
							|  |  |  |      * Returns true if the signature is verified, false if it is not correct or null on error | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * By default returns false for self-signed certs. Call validateSignature(false) to make this support | 
					
						
							|  |  |  |      * self-signed. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Boolean $caonly optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function validateSignature($caonly = true) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_array($this->currentCert) || !isset($this->signatureSubject)) { | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* TODO: | 
					
						
							|  |  |  |            "emailAddress attribute values are not case-sensitive (e.g., "subscriber@example.com" is the same as "SUBSCRIBER@EXAMPLE.COM")." | 
					
						
							|  |  |  |             -- http://tools.ietf.org/html/rfc5280#section-4.1.2.6
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            implement pathLenConstraint in the id-ce-basicConstraints extension */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case isset($this->currentCert['tbsCertificate']): | 
					
						
							|  |  |  |                 // self-signed cert
 | 
					
						
							|  |  |  |                 if ($this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']) { | 
					
						
							|  |  |  |                     $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); | 
					
						
							|  |  |  |                     $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier'); | 
					
						
							|  |  |  |                     switch (true) { | 
					
						
							|  |  |  |                         case !is_array($authorityKey): | 
					
						
							|  |  |  |                         case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: | 
					
						
							|  |  |  |                             $signingCert = $this->currentCert; // working cert
 | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (!empty($this->CAs)) { | 
					
						
							|  |  |  |                     for ($i = 0; $i < count($this->CAs); $i++) { | 
					
						
							|  |  |  |                         // even if the cert is a self-signed one we still want to see if it's a CA;
 | 
					
						
							|  |  |  |                         // if not, we'll conditionally return an error
 | 
					
						
							|  |  |  |                         $ca = $this->CAs[$i]; | 
					
						
							|  |  |  |                         if ($this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) { | 
					
						
							|  |  |  |                             $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); | 
					
						
							|  |  |  |                             $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); | 
					
						
							|  |  |  |                             switch (true) { | 
					
						
							|  |  |  |                                 case !is_array($authorityKey): | 
					
						
							|  |  |  |                                 case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: | 
					
						
							|  |  |  |                                     $signingCert = $ca; // working cert
 | 
					
						
							|  |  |  |                                     break 2; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (count($this->CAs) == $i && $caonly) { | 
					
						
							|  |  |  |                         return false; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } elseif (!isset($signingCert) || $caonly) { | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return $this->_validateSignature( | 
					
						
							|  |  |  |                     $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], | 
					
						
							|  |  |  |                     $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], | 
					
						
							|  |  |  |                     $this->currentCert['signatureAlgorithm']['algorithm'], | 
					
						
							|  |  |  |                     substr(base64_decode($this->currentCert['signature']), 1), | 
					
						
							|  |  |  |                     $this->signatureSubject | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             case isset($this->currentCert['certificationRequestInfo']): | 
					
						
							|  |  |  |                 return $this->_validateSignature( | 
					
						
							|  |  |  |                     $this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'], | 
					
						
							|  |  |  |                     $this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], | 
					
						
							|  |  |  |                     $this->currentCert['signatureAlgorithm']['algorithm'], | 
					
						
							|  |  |  |                     substr(base64_decode($this->currentCert['signature']), 1), | 
					
						
							|  |  |  |                     $this->signatureSubject | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             case isset($this->currentCert['publicKeyAndChallenge']): | 
					
						
							|  |  |  |                 return $this->_validateSignature( | 
					
						
							|  |  |  |                     $this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'], | 
					
						
							|  |  |  |                     $this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'], | 
					
						
							|  |  |  |                     $this->currentCert['signatureAlgorithm']['algorithm'], | 
					
						
							|  |  |  |                     substr(base64_decode($this->currentCert['signature']), 1), | 
					
						
							|  |  |  |                     $this->signatureSubject | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             case isset($this->currentCert['tbsCertList']): | 
					
						
							|  |  |  |                 if (!empty($this->CAs)) { | 
					
						
							|  |  |  |                     for ($i = 0; $i < count($this->CAs); $i++) { | 
					
						
							|  |  |  |                         $ca = $this->CAs[$i]; | 
					
						
							|  |  |  |                         if ($this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']) { | 
					
						
							|  |  |  |                             $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); | 
					
						
							|  |  |  |                             $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); | 
					
						
							|  |  |  |                             switch (true) { | 
					
						
							|  |  |  |                                 case !is_array($authorityKey): | 
					
						
							|  |  |  |                                 case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: | 
					
						
							|  |  |  |                                     $signingCert = $ca; // working cert
 | 
					
						
							|  |  |  |                                     break 2; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (!isset($signingCert)) { | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return $this->_validateSignature( | 
					
						
							|  |  |  |                     $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], | 
					
						
							|  |  |  |                     $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], | 
					
						
							|  |  |  |                     $this->currentCert['signatureAlgorithm']['algorithm'], | 
					
						
							|  |  |  |                     substr(base64_decode($this->currentCert['signature']), 1), | 
					
						
							|  |  |  |                     $this->signatureSubject | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Validates a signature | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Returns true if the signature is verified, false if it is not correct or null on error | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $publicKeyAlgorithm | 
					
						
							|  |  |  |      * @param String $publicKey | 
					
						
							|  |  |  |      * @param String $signatureAlgorithm | 
					
						
							|  |  |  |      * @param String $signature | 
					
						
							|  |  |  |      * @param String $signatureSubject | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Integer | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch ($publicKeyAlgorithm) { | 
					
						
							|  |  |  |             case 'rsaEncryption': | 
					
						
							|  |  |  |                 if (!class_exists('Crypt_RSA')) { | 
					
						
							|  |  |  |                     include_once 'Crypt/RSA.php'; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $rsa = new Crypt_RSA(); | 
					
						
							|  |  |  |                 $rsa->loadKey($publicKey); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 switch ($signatureAlgorithm) { | 
					
						
							|  |  |  |                     case 'md2WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'md5WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha1WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha224WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha256WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha384WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha512WithRSAEncryption': | 
					
						
							|  |  |  |                         $rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm)); | 
					
						
							|  |  |  |                         $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1); | 
					
						
							|  |  |  |                         if (!@$rsa->verify($signatureSubject, $signature)) { | 
					
						
							|  |  |  |                             return false; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     default: | 
					
						
							|  |  |  |                         return null; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Reformat public keys | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Reformats a public key to a format supported by phpseclib (if applicable) | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $algorithm | 
					
						
							|  |  |  |      * @param String $key | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return String | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _reformatKey($algorithm, $key) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch ($algorithm) { | 
					
						
							|  |  |  |             case 'rsaEncryption': | 
					
						
							|  |  |  |                 return | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                     "-----BEGIN RSA PUBLIC KEY-----\r\n" . | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                     // subjectPublicKey is stored as a bit string in X.509 certs.  the first byte of a bit string represents how many bits
 | 
					
						
							|  |  |  |                     // in the last byte should be ignored.  the following only supports non-zero stuff but as none of the X.509 certs Firefox
 | 
					
						
							|  |  |  |                     // uses as a cert authority actually use a non-zero bit I think it's safe to assume that none do.
 | 
					
						
							|  |  |  |                     chunk_split(base64_encode(substr(base64_decode($key), 1)), 64) . | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                     '-----END RSA PUBLIC KEY-----'; | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             default: | 
					
						
							|  |  |  |                 return $key; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Decodes an IP address | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Takes in a base64 encoded "blob" and returns a human readable IP address | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $ip | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return String | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _decodeIP($ip) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $ip = base64_decode($ip); | 
					
						
							|  |  |  |         list(, $ip) = unpack('N', $ip); | 
					
						
							|  |  |  |         return long2ip($ip); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Encodes an IP address | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Takes a human readable IP address into a base64-encoded "blob" | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $ip | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return String | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _encodeIP($ip) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return base64_encode(pack('N', ip2long($ip))); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * "Normalizes" a Distinguished Name property | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $propName | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _translateDNProp($propName) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (strtolower($propName)) { | 
					
						
							|  |  |  |             case 'id-at-countryname': | 
					
						
							|  |  |  |             case 'countryname': | 
					
						
							|  |  |  |             case 'c': | 
					
						
							|  |  |  |                 return 'id-at-countryName'; | 
					
						
							|  |  |  |             case 'id-at-organizationname': | 
					
						
							|  |  |  |             case 'organizationname': | 
					
						
							|  |  |  |             case 'o': | 
					
						
							|  |  |  |                 return 'id-at-organizationName'; | 
					
						
							|  |  |  |             case 'id-at-dnqualifier': | 
					
						
							|  |  |  |             case 'dnqualifier': | 
					
						
							|  |  |  |                 return 'id-at-dnQualifier'; | 
					
						
							|  |  |  |             case 'id-at-commonname': | 
					
						
							|  |  |  |             case 'commonname': | 
					
						
							|  |  |  |             case 'cn': | 
					
						
							|  |  |  |                 return 'id-at-commonName'; | 
					
						
							|  |  |  |             case 'id-at-stateorprovincename': | 
					
						
							|  |  |  |             case 'stateorprovincename': | 
					
						
							|  |  |  |             case 'state': | 
					
						
							|  |  |  |             case 'province': | 
					
						
							|  |  |  |             case 'provincename': | 
					
						
							|  |  |  |             case 'st': | 
					
						
							|  |  |  |                 return 'id-at-stateOrProvinceName'; | 
					
						
							|  |  |  |             case 'id-at-localityname': | 
					
						
							|  |  |  |             case 'localityname': | 
					
						
							|  |  |  |             case 'l': | 
					
						
							|  |  |  |                 return 'id-at-localityName'; | 
					
						
							|  |  |  |             case 'id-emailaddress': | 
					
						
							|  |  |  |             case 'emailaddress': | 
					
						
							|  |  |  |                 return 'pkcs-9-at-emailAddress'; | 
					
						
							|  |  |  |             case 'id-at-serialnumber': | 
					
						
							|  |  |  |             case 'serialnumber': | 
					
						
							|  |  |  |                 return 'id-at-serialNumber'; | 
					
						
							|  |  |  |             case 'id-at-postalcode': | 
					
						
							|  |  |  |             case 'postalcode': | 
					
						
							|  |  |  |                 return 'id-at-postalCode'; | 
					
						
							|  |  |  |             case 'id-at-streetaddress': | 
					
						
							|  |  |  |             case 'streetaddress': | 
					
						
							|  |  |  |                 return 'id-at-streetAddress'; | 
					
						
							|  |  |  |             case 'id-at-name': | 
					
						
							|  |  |  |             case 'name': | 
					
						
							|  |  |  |                 return 'id-at-name'; | 
					
						
							|  |  |  |             case 'id-at-givenname': | 
					
						
							|  |  |  |             case 'givenname': | 
					
						
							|  |  |  |                 return 'id-at-givenName'; | 
					
						
							|  |  |  |             case 'id-at-surname': | 
					
						
							|  |  |  |             case 'surname': | 
					
						
							|  |  |  |             case 'sn': | 
					
						
							|  |  |  |                 return 'id-at-surname'; | 
					
						
							|  |  |  |             case 'id-at-initials': | 
					
						
							|  |  |  |             case 'initials': | 
					
						
							|  |  |  |                 return 'id-at-initials'; | 
					
						
							|  |  |  |             case 'id-at-generationqualifier': | 
					
						
							|  |  |  |             case 'generationqualifier': | 
					
						
							|  |  |  |                 return 'id-at-generationQualifier'; | 
					
						
							|  |  |  |             case 'id-at-organizationalunitname': | 
					
						
							|  |  |  |             case 'organizationalunitname': | 
					
						
							|  |  |  |             case 'ou': | 
					
						
							|  |  |  |                 return 'id-at-organizationalUnitName'; | 
					
						
							|  |  |  |             case 'id-at-pseudonym': | 
					
						
							|  |  |  |             case 'pseudonym': | 
					
						
							|  |  |  |                 return 'id-at-pseudonym'; | 
					
						
							|  |  |  |             case 'id-at-title': | 
					
						
							|  |  |  |             case 'title': | 
					
						
							|  |  |  |                 return 'id-at-title'; | 
					
						
							|  |  |  |             case 'id-at-description': | 
					
						
							|  |  |  |             case 'description': | 
					
						
							|  |  |  |                 return 'id-at-description'; | 
					
						
							|  |  |  |             case 'id-at-role': | 
					
						
							|  |  |  |             case 'role': | 
					
						
							|  |  |  |                 return 'id-at-role'; | 
					
						
							|  |  |  |             case 'id-at-uniqueidentifier': | 
					
						
							|  |  |  |             case 'uniqueidentifier': | 
					
						
							|  |  |  |             case 'x500uniqueidentifier': | 
					
						
							|  |  |  |                 return 'id-at-uniqueIdentifier'; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set a Distinguished Name property | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $propName | 
					
						
							|  |  |  |      * @param Mixed $propValue | 
					
						
							|  |  |  |      * @param String $type optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setDNProp($propName, $propValue, $type = 'utf8String') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (empty($this->dn)) { | 
					
						
							|  |  |  |             $this->dn = array('rdnSequence' => array()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (($propName = $this->_translateDNProp($propName)) === false) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ((array) $propValue as $v) { | 
					
						
							|  |  |  |             if (!is_array($v) && isset($type)) { | 
					
						
							|  |  |  |                 $v = array($type => $v); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $this->dn['rdnSequence'][] = array( | 
					
						
							|  |  |  |                 array( | 
					
						
							|  |  |  |                     'type' => $propName, | 
					
						
							|  |  |  |                     'value'=> $v | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Remove Distinguished Name properties | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $propName | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function removeDNProp($propName) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (empty($this->dn)) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (($propName = $this->_translateDNProp($propName)) === false) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $dn = &$this->dn['rdnSequence']; | 
					
						
							|  |  |  |         $size = count($dn); | 
					
						
							|  |  |  |         for ($i = 0; $i < $size; $i++) { | 
					
						
							|  |  |  |             if ($dn[$i][0]['type'] == $propName) { | 
					
						
							|  |  |  |                 unset($dn[$i]); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $dn = array_values($dn); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get Distinguished Name properties | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $propName | 
					
						
							|  |  |  |      * @param Array $dn optional | 
					
						
							|  |  |  |      * @param Boolean $withType optional | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getDNProp($propName, $dn = null, $withType = false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!isset($dn)) { | 
					
						
							|  |  |  |             $dn = $this->dn; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (empty($dn)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (($propName = $this->_translateDNProp($propName)) === false) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $dn = $dn['rdnSequence']; | 
					
						
							|  |  |  |         $result = array(); | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  |         for ($i = 0; $i < count($dn); $i++) { | 
					
						
							|  |  |  |             if ($dn[$i][0]['type'] == $propName) { | 
					
						
							|  |  |  |                 $v = $dn[$i][0]['value']; | 
					
						
							|  |  |  |                 if (!$withType && is_array($v)) { | 
					
						
							|  |  |  |                     foreach ($v as $type => $s) { | 
					
						
							|  |  |  |                         $type = array_search($type, $asn1->ANYmap, true); | 
					
						
							|  |  |  |                         if ($type !== false && isset($asn1->stringTypeSize[$type])) { | 
					
						
							|  |  |  |                             $s = $asn1->convert($s, $type); | 
					
						
							|  |  |  |                             if ($s !== false) { | 
					
						
							|  |  |  |                                 $v = $s; | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (is_array($v)) { | 
					
						
							|  |  |  |                         $v = array_pop($v); // Always strip data type.
 | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $result[] = $v; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set a Distinguished Name | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Mixed $dn | 
					
						
							|  |  |  |      * @param Boolean $merge optional | 
					
						
							|  |  |  |      * @param String $type optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setDN($dn, $merge = false, $type = 'utf8String') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!$merge) { | 
					
						
							|  |  |  |             $this->dn = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($dn)) { | 
					
						
							|  |  |  |             if (isset($dn['rdnSequence'])) { | 
					
						
							|  |  |  |                 $this->dn = $dn; // No merge here.
 | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // handles stuff generated by openssl_x509_parse()
 | 
					
						
							|  |  |  |             foreach ($dn as $prop => $value) { | 
					
						
							|  |  |  |                 if (!$this->setDNProp($prop, $value, $type)) { | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // handles everything else
 | 
					
						
							|  |  |  |         $results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE); | 
					
						
							|  |  |  |         for ($i = 1; $i < count($results); $i+=2) { | 
					
						
							|  |  |  |             $prop = trim($results[$i], ', =/'); | 
					
						
							|  |  |  |             $value = $results[$i + 1]; | 
					
						
							|  |  |  |             if (!$this->setDNProp($prop, $value, $type)) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the Distinguished Name for a certificates subject | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Mixed $format optional | 
					
						
							|  |  |  |      * @param Array $dn optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getDN($format = FILE_X509_DN_ARRAY, $dn = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!isset($dn)) { | 
					
						
							|  |  |  |             $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ((int) $format) { | 
					
						
							|  |  |  |             case FILE_X509_DN_ARRAY: | 
					
						
							|  |  |  |                 return $dn; | 
					
						
							|  |  |  |             case FILE_X509_DN_ASN1: | 
					
						
							|  |  |  |                 $asn1 = new File_ASN1(); | 
					
						
							|  |  |  |                 $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  |                 $filters = array(); | 
					
						
							|  |  |  |                 $filters['rdnSequence']['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING); | 
					
						
							|  |  |  |                 $asn1->loadFilters($filters); | 
					
						
							|  |  |  |                 return $asn1->encodeDER($dn, $this->Name); | 
					
						
							|  |  |  |             case FILE_X509_DN_OPENSSL: | 
					
						
							|  |  |  |                 $dn = $this->getDN(FILE_X509_DN_STRING, $dn); | 
					
						
							|  |  |  |                 if ($dn === false) { | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $attrs = preg_split('#((?:^|, *|/)[a-z][a-z0-9]*=)#i', $dn, -1, PREG_SPLIT_DELIM_CAPTURE); | 
					
						
							|  |  |  |                 $dn = array(); | 
					
						
							|  |  |  |                 for ($i = 1; $i < count($attrs); $i += 2) { | 
					
						
							|  |  |  |                     $prop = trim($attrs[$i], ', =/'); | 
					
						
							|  |  |  |                     $value = $attrs[$i + 1]; | 
					
						
							|  |  |  |                     if (!isset($dn[$prop])) { | 
					
						
							|  |  |  |                         $dn[$prop] = $value; | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         $dn[$prop] = array_merge((array) $dn[$prop], array($value)); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return $dn; | 
					
						
							|  |  |  |             case FILE_X509_DN_CANON: | 
					
						
							|  |  |  |                 //  No SEQUENCE around RDNs and all string values normalized as
 | 
					
						
							|  |  |  |                 // trimmed lowercase UTF-8 with all spacing  as one blank.
 | 
					
						
							|  |  |  |                 $asn1 = new File_ASN1(); | 
					
						
							|  |  |  |                 $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  |                 $filters = array(); | 
					
						
							|  |  |  |                 $filters['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING); | 
					
						
							|  |  |  |                 $asn1->loadFilters($filters); | 
					
						
							|  |  |  |                 $result = ''; | 
					
						
							|  |  |  |                 foreach ($dn['rdnSequence'] as $rdn) { | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                     foreach ($rdn as $i => $attr) { | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                         $attr = &$rdn[$i]; | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                         if (is_array($attr['value'])) { | 
					
						
							|  |  |  |                             foreach ($attr['value'] as $type => $v) { | 
					
						
							|  |  |  |                                 $type = array_search($type, $asn1->ANYmap, true); | 
					
						
							|  |  |  |                                 if ($type !== false && isset($asn1->stringTypeSize[$type])) { | 
					
						
							|  |  |  |                                     $v = $asn1->convert($v, $type); | 
					
						
							|  |  |  |                                     if ($v !== false) { | 
					
						
							|  |  |  |                                         $v = preg_replace('/\s+/', ' ', $v); | 
					
						
							|  |  |  |                                         $attr['value'] = strtolower(trim($v)); | 
					
						
							|  |  |  |                                         break; | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     $result .= $asn1->encodeDER($rdn, $this->RelativeDistinguishedName); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return $result; | 
					
						
							|  |  |  |             case FILE_X509_DN_HASH: | 
					
						
							|  |  |  |                 $dn = $this->getDN(FILE_X509_DN_CANON, $dn); | 
					
						
							|  |  |  |                 if (!class_exists('Crypt_Hash')) { | 
					
						
							|  |  |  |                     include_once 'Crypt/Hash.php'; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $hash = new Crypt_Hash('sha1'); | 
					
						
							|  |  |  |                 $hash = $hash->hash($dn); | 
					
						
							|  |  |  |                 extract(unpack('Vhash', $hash)); | 
					
						
							|  |  |  |                 return strtolower(bin2hex(pack('N', $hash))); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |         // Default is to return a string.
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |         $start = true; | 
					
						
							|  |  |  |         $output = ''; | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  |         foreach ($dn['rdnSequence'] as $field) { | 
					
						
							|  |  |  |             $prop = $field[0]['type']; | 
					
						
							|  |  |  |             $value = $field[0]['value']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $delim = ', '; | 
					
						
							|  |  |  |             switch ($prop) { | 
					
						
							|  |  |  |                 case 'id-at-countryName': | 
					
						
							|  |  |  |                     $desc = 'C='; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'id-at-stateOrProvinceName': | 
					
						
							|  |  |  |                     $desc = 'ST='; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'id-at-organizationName': | 
					
						
							|  |  |  |                     $desc = 'O='; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'id-at-organizationalUnitName': | 
					
						
							|  |  |  |                     $desc = 'OU='; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'id-at-commonName': | 
					
						
							|  |  |  |                     $desc = 'CN='; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'id-at-localityName': | 
					
						
							|  |  |  |                     $desc = 'L='; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'id-at-surname': | 
					
						
							|  |  |  |                     $desc = 'SN='; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'id-at-uniqueIdentifier': | 
					
						
							|  |  |  |                     $delim = '/'; | 
					
						
							|  |  |  |                     $desc = 'x500UniqueIdentifier='; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     $delim = '/'; | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                     $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop) . '='; | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!$start) { | 
					
						
							|  |  |  |                 $output.= $delim; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (is_array($value)) { | 
					
						
							|  |  |  |                 foreach ($value as $type => $v) { | 
					
						
							|  |  |  |                     $type = array_search($type, $asn1->ANYmap, true); | 
					
						
							|  |  |  |                     if ($type !== false && isset($asn1->stringTypeSize[$type])) { | 
					
						
							|  |  |  |                         $v = $asn1->convert($v, $type); | 
					
						
							|  |  |  |                         if ($v !== false) { | 
					
						
							|  |  |  |                             $value = $v; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (is_array($value)) { | 
					
						
							|  |  |  |                     $value = array_pop($value); // Always strip data type.
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $output.= $desc . $value; | 
					
						
							|  |  |  |             $start = false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $output; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the Distinguished Name for a certificate/crl issuer | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Integer $format optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getIssuerDN($format = FILE_X509_DN_ARRAY) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case !isset($this->currentCert) || !is_array($this->currentCert): | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case isset($this->currentCert['tbsCertificate']): | 
					
						
							|  |  |  |                 return $this->getDN($format, $this->currentCert['tbsCertificate']['issuer']); | 
					
						
							|  |  |  |             case isset($this->currentCert['tbsCertList']): | 
					
						
							|  |  |  |                 return $this->getDN($format, $this->currentCert['tbsCertList']['issuer']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the Distinguished Name for a certificate/csr subject | 
					
						
							|  |  |  |      * Alias of getDN() | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Integer $format optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getSubjectDN($format = FILE_X509_DN_ARRAY) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case !empty($this->dn): | 
					
						
							|  |  |  |                 return $this->getDN($format); | 
					
						
							|  |  |  |             case !isset($this->currentCert) || !is_array($this->currentCert): | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case isset($this->currentCert['tbsCertificate']): | 
					
						
							|  |  |  |                 return $this->getDN($format, $this->currentCert['tbsCertificate']['subject']); | 
					
						
							|  |  |  |             case isset($this->currentCert['certificationRequestInfo']): | 
					
						
							|  |  |  |                 return $this->getDN($format, $this->currentCert['certificationRequestInfo']['subject']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get an individual Distinguished Name property for a certificate/crl issuer | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $propName | 
					
						
							|  |  |  |      * @param Boolean $withType optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getIssuerDNProp($propName, $withType = false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case !isset($this->currentCert) || !is_array($this->currentCert): | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case isset($this->currentCert['tbsCertificate']): | 
					
						
							|  |  |  |                 return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType); | 
					
						
							|  |  |  |             case isset($this->currentCert['tbsCertList']): | 
					
						
							|  |  |  |                 return $this->getDNProp($propName, $this->currentCert['tbsCertList']['issuer'], $withType); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get an individual Distinguished Name property for a certificate/csr subject | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $propName | 
					
						
							|  |  |  |      * @param Boolean $withType optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getSubjectDNProp($propName, $withType = false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case !empty($this->dn): | 
					
						
							|  |  |  |                 return $this->getDNProp($propName, null, $withType); | 
					
						
							|  |  |  |             case !isset($this->currentCert) || !is_array($this->currentCert): | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case isset($this->currentCert['tbsCertificate']): | 
					
						
							|  |  |  |                 return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType); | 
					
						
							|  |  |  |             case isset($this->currentCert['certificationRequestInfo']): | 
					
						
							|  |  |  |                 return $this->getDNProp($propName, $this->currentCert['certificationRequestInfo']['subject'], $withType); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the certificate chain for the current cert | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getChain() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $chain = array($this->currentCert); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (empty($this->CAs)) { | 
					
						
							|  |  |  |             return $chain; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         while (true) { | 
					
						
							|  |  |  |             $currentCert = $chain[count($chain) - 1]; | 
					
						
							|  |  |  |             for ($i = 0; $i < count($this->CAs); $i++) { | 
					
						
							|  |  |  |                 $ca = $this->CAs[$i]; | 
					
						
							|  |  |  |                 if ($currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) { | 
					
						
							|  |  |  |                     $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier', $currentCert); | 
					
						
							|  |  |  |                     $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); | 
					
						
							|  |  |  |                     switch (true) { | 
					
						
							|  |  |  |                         case !is_array($authorityKey): | 
					
						
							|  |  |  |                         case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: | 
					
						
							|  |  |  |                             if ($currentCert === $ca) { | 
					
						
							|  |  |  |                                 break 3; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                             $chain[] = $ca; | 
					
						
							|  |  |  |                             break 2; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if ($i == count($this->CAs)) { | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |         foreach ($chain as $key => $value) { | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             $chain[$key] = new File_X509(); | 
					
						
							|  |  |  |             $chain[$key]->loadX509($value); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $chain; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set public key | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Key needs to be a Crypt_RSA object | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Object $key | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setPublicKey($key) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $key->setPublicKey(); | 
					
						
							|  |  |  |         $this->publicKey = $key; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set private key | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Key needs to be a Crypt_RSA object | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Object $key | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setPrivateKey($key) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->privateKey = $key; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Set challenge | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Used for SPKAC CSR's | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $challenge | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setChallenge($challenge) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->challenge = $challenge; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Gets the public key | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Returns a Crypt_RSA object or a false. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getPublicKey() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (isset($this->publicKey)) { | 
					
						
							|  |  |  |             return $this->publicKey; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($this->currentCert) && is_array($this->currentCert)) { | 
					
						
							|  |  |  |             foreach (array('tbsCertificate/subjectPublicKeyInfo', 'certificationRequestInfo/subjectPKInfo') as $path) { | 
					
						
							|  |  |  |                 $keyinfo = $this->_subArray($this->currentCert, $path); | 
					
						
							|  |  |  |                 if (!empty($keyinfo)) { | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (empty($keyinfo)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $key = $keyinfo['subjectPublicKey']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($keyinfo['algorithm']['algorithm']) { | 
					
						
							|  |  |  |             case 'rsaEncryption': | 
					
						
							|  |  |  |                 if (!class_exists('Crypt_RSA')) { | 
					
						
							|  |  |  |                     include_once 'Crypt/RSA.php'; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $publicKey = new Crypt_RSA(); | 
					
						
							|  |  |  |                 $publicKey->loadKey($key); | 
					
						
							|  |  |  |                 $publicKey->setPublicKey(); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $publicKey; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Load a Certificate Signing Request | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $csr | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function loadCSR($csr) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_array($csr) && isset($csr['certificationRequestInfo'])) { | 
					
						
							|  |  |  |             unset($this->currentCert); | 
					
						
							|  |  |  |             unset($this->currentKeyIdentifier); | 
					
						
							|  |  |  |             unset($this->signatureSubject); | 
					
						
							|  |  |  |             $this->dn = $csr['certificationRequestInfo']['subject']; | 
					
						
							|  |  |  |             if (!isset($this->dn)) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $this->currentCert = $csr; | 
					
						
							|  |  |  |             return $csr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // see http://tools.ietf.org/html/rfc2986
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $csr = $this->_extractBER($csr); | 
					
						
							|  |  |  |         $orig = $csr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($csr === false) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  |         $decoded = $asn1->decodeBER($csr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (empty($decoded)) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $csr = $asn1->asn1map($decoded[0], $this->CertificationRequest); | 
					
						
							|  |  |  |         if (!isset($csr) || $csr === false) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->dn = $csr['certificationRequestInfo']['subject']; | 
					
						
							|  |  |  |         $this->_mapInAttributes($csr, 'certificationRequestInfo/attributes', $asn1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $algorithm = &$csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm']; | 
					
						
							|  |  |  |         $key = &$csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']; | 
					
						
							|  |  |  |         $key = $this->_reformatKey($algorithm, $key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($algorithm) { | 
					
						
							|  |  |  |             case 'rsaEncryption': | 
					
						
							|  |  |  |                 if (!class_exists('Crypt_RSA')) { | 
					
						
							|  |  |  |                     include_once 'Crypt/RSA.php'; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $this->publicKey = new Crypt_RSA(); | 
					
						
							|  |  |  |                 $this->publicKey->loadKey($key); | 
					
						
							|  |  |  |                 $this->publicKey->setPublicKey(); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 $this->publicKey = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->currentKeyIdentifier = null; | 
					
						
							|  |  |  |         $this->currentCert = $csr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $csr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Save CSR request | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Array $csr | 
					
						
							|  |  |  |      * @param Integer $format optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return String | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function saveCSR($csr, $format = FILE_X509_FORMAT_PEM) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_array($csr) || !isset($csr['certificationRequestInfo'])) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case !($algorithm = $this->_subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')): | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |             case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']): | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 switch ($algorithm) { | 
					
						
							|  |  |  |                     case 'rsaEncryption': | 
					
						
							|  |  |  |                         $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'] | 
					
						
							|  |  |  |                             = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']))); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $filters = array(); | 
					
						
							|  |  |  |         $filters['certificationRequestInfo']['subject']['rdnSequence']['value'] | 
					
						
							|  |  |  |             = array('type' => FILE_ASN1_TYPE_UTF8_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadFilters($filters); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->_mapOutAttributes($csr, 'certificationRequestInfo/attributes', $asn1); | 
					
						
							|  |  |  |         $csr = $asn1->encodeDER($csr, $this->CertificationRequest); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($format) { | 
					
						
							|  |  |  |             case FILE_X509_FORMAT_DER: | 
					
						
							|  |  |  |                 return $csr; | 
					
						
							|  |  |  |             // case FILE_X509_FORMAT_PEM:
 | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(base64_encode($csr), 64) . '-----END CERTIFICATE REQUEST-----'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Load a SPKAC CSR | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * SPKAC's are produced by the HTML5 keygen element: | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $csr | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function loadSPKAC($spkac) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_array($spkac) && isset($spkac['publicKeyAndChallenge'])) { | 
					
						
							|  |  |  |             unset($this->currentCert); | 
					
						
							|  |  |  |             unset($this->currentKeyIdentifier); | 
					
						
							|  |  |  |             unset($this->signatureSubject); | 
					
						
							|  |  |  |             $this->currentCert = $spkac; | 
					
						
							|  |  |  |             return $spkac; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |         // OpenSSL produces SPKAC's that are preceeded by the string SPKAC=
 | 
					
						
							|  |  |  |         $temp = preg_replace('#(?:SPKAC=)|[ \r\n\\\]#', '', $spkac); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |         $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false; | 
					
						
							|  |  |  |         if ($temp != false) { | 
					
						
							|  |  |  |             $spkac = $temp; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $orig = $spkac; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($spkac === false) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  |         $decoded = $asn1->decodeBER($spkac); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (empty($decoded)) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $spkac = $asn1->asn1map($decoded[0], $this->SignedPublicKeyAndChallenge); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!isset($spkac) || $spkac === false) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $algorithm = &$spkac['publicKeyAndChallenge']['spki']['algorithm']['algorithm']; | 
					
						
							|  |  |  |         $key = &$spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']; | 
					
						
							|  |  |  |         $key = $this->_reformatKey($algorithm, $key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($algorithm) { | 
					
						
							|  |  |  |             case 'rsaEncryption': | 
					
						
							|  |  |  |                 if (!class_exists('Crypt_RSA')) { | 
					
						
							|  |  |  |                     include_once 'Crypt/RSA.php'; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $this->publicKey = new Crypt_RSA(); | 
					
						
							|  |  |  |                 $this->publicKey->loadKey($key); | 
					
						
							|  |  |  |                 $this->publicKey->setPublicKey(); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 $this->publicKey = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->currentKeyIdentifier = null; | 
					
						
							|  |  |  |         $this->currentCert = $spkac; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $spkac; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Save a SPKAC CSR request | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Array $csr | 
					
						
							|  |  |  |      * @param Integer $format optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return String | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function saveSPKAC($spkac, $format = FILE_X509_FORMAT_PEM) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $algorithm = $this->_subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm'); | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case !$algorithm: | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |             case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']): | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 switch ($algorithm) { | 
					
						
							|  |  |  |                     case 'rsaEncryption': | 
					
						
							|  |  |  |                         $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'] | 
					
						
							|  |  |  |                             = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']))); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  |         $spkac = $asn1->encodeDER($spkac, $this->SignedPublicKeyAndChallenge); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($format) { | 
					
						
							|  |  |  |             case FILE_X509_FORMAT_DER: | 
					
						
							|  |  |  |                 return $spkac; | 
					
						
							|  |  |  |             // case FILE_X509_FORMAT_PEM:
 | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 // OpenSSL's implementation of SPKAC requires the SPKAC be preceeded by SPKAC= and since there are pretty much
 | 
					
						
							|  |  |  |                 // no other SPKAC decoders phpseclib will use that same format
 | 
					
						
							|  |  |  |                 return 'SPKAC=' . base64_encode($spkac); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Load a Certificate Revocation List | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $crl | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function loadCRL($crl) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_array($crl) && isset($crl['tbsCertList'])) { | 
					
						
							|  |  |  |             $this->currentCert = $crl; | 
					
						
							|  |  |  |             unset($this->signatureSubject); | 
					
						
							|  |  |  |             return $crl; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $crl = $this->_extractBER($crl); | 
					
						
							|  |  |  |         $orig = $crl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($crl === false) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  |         $decoded = $asn1->decodeBER($crl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (empty($decoded)) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $crl = $asn1->asn1map($decoded[0], $this->CertificateList); | 
					
						
							|  |  |  |         if (!isset($crl) || $crl === false) { | 
					
						
							|  |  |  |             $this->currentCert = false; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->_mapInExtensions($crl, 'tbsCertList/crlExtensions', $asn1); | 
					
						
							|  |  |  |         $rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates'); | 
					
						
							|  |  |  |         if (is_array($rclist)) { | 
					
						
							|  |  |  |             foreach ($rclist as $i => $extension) { | 
					
						
							|  |  |  |                 $this->_mapInExtensions($rclist, "$i/crlEntryExtensions", $asn1); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->currentKeyIdentifier = null; | 
					
						
							|  |  |  |         $this->currentCert = $crl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $crl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Save Certificate Revocation List. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Array $crl | 
					
						
							|  |  |  |      * @param Integer $format optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return String | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function saveCRL($crl, $format = FILE_X509_FORMAT_PEM) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_array($crl) || !isset($crl['tbsCertList'])) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1 = new File_ASN1(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadOIDs($this->oids); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $filters = array(); | 
					
						
							|  |  |  |         $filters['tbsCertList']['issuer']['rdnSequence']['value'] | 
					
						
							|  |  |  |             = array('type' => FILE_ASN1_TYPE_UTF8_STRING); | 
					
						
							|  |  |  |         $filters['tbsCertList']['signature']['parameters'] | 
					
						
							|  |  |  |             = array('type' => FILE_ASN1_TYPE_UTF8_STRING); | 
					
						
							|  |  |  |         $filters['signatureAlgorithm']['parameters'] | 
					
						
							|  |  |  |             = array('type' => FILE_ASN1_TYPE_UTF8_STRING); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (empty($crl['tbsCertList']['signature']['parameters'])) { | 
					
						
							|  |  |  |             $filters['tbsCertList']['signature']['parameters'] | 
					
						
							|  |  |  |                 = array('type' => FILE_ASN1_TYPE_NULL); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (empty($crl['signatureAlgorithm']['parameters'])) { | 
					
						
							|  |  |  |             $filters['signatureAlgorithm']['parameters'] | 
					
						
							|  |  |  |                 = array('type' => FILE_ASN1_TYPE_NULL); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $asn1->loadFilters($filters); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->_mapOutExtensions($crl, 'tbsCertList/crlExtensions', $asn1); | 
					
						
							|  |  |  |         $rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates'); | 
					
						
							|  |  |  |         if (is_array($rclist)) { | 
					
						
							|  |  |  |             foreach ($rclist as $i => $extension) { | 
					
						
							|  |  |  |                 $this->_mapOutExtensions($rclist, "$i/crlEntryExtensions", $asn1); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $crl = $asn1->encodeDER($crl, $this->CertificateList); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($format) { | 
					
						
							|  |  |  |             case FILE_X509_FORMAT_DER: | 
					
						
							|  |  |  |                 return $crl; | 
					
						
							|  |  |  |             // case FILE_X509_FORMAT_PEM:
 | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return "-----BEGIN X509 CRL-----\r\n" . chunk_split(base64_encode($crl), 64) . '-----END X509 CRL-----'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Helper function to build a time field according to RFC 3280 section | 
					
						
							|  |  |  |      *  - 4.1.2.5 Validity | 
					
						
							|  |  |  |      *  - 5.1.2.4 This Update | 
					
						
							|  |  |  |      *  - 5.1.2.5 Next Update | 
					
						
							|  |  |  |      *  - 5.1.2.6 Revoked Certificates | 
					
						
							|  |  |  |      * by choosing utcTime iff year of date given is before 2050 and generalTime else. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $date in format date('D, d M Y H:i:s O') | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _timeField($date) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this
 | 
					
						
							|  |  |  |         if ($year < 2050) { | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |             return array('utcTime' => $date); | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |             return array('generalTime' => $date); | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Sign an X.509 certificate | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * $issuer's private key needs to be loaded. | 
					
						
							|  |  |  |      * $subject can be either an existing X.509 cert (if you want to resign it), | 
					
						
							|  |  |  |      * a CSR or something with the DN and public key explicitly set. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param File_X509 $issuer | 
					
						
							|  |  |  |      * @param File_X509 $subject | 
					
						
							|  |  |  |      * @param String $signatureAlgorithm optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function sign($issuer, $subject, $signatureAlgorithm = 'sha1WithRSAEncryption') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_object($issuer->privateKey) || empty($issuer->dn)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($subject->publicKey) && !($subjectPublicKey = $subject->_formatSubjectPublicKey())) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $currentCert = isset($this->currentCert) ? $this->currentCert : null; | 
					
						
							|  |  |  |         $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) { | 
					
						
							|  |  |  |             $this->currentCert = $subject->currentCert; | 
					
						
							|  |  |  |             $this->currentCert['tbsCertificate']['signature']['algorithm'] = $signatureAlgorithm; | 
					
						
							|  |  |  |             $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!empty($this->startDate)) { | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                 $this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->_timeField($this->startDate); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |             if (!empty($this->endDate)) { | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                 $this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->_timeField($this->endDate); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |             if (!empty($this->serialNumber)) { | 
					
						
							|  |  |  |                 $this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!empty($subject->dn)) { | 
					
						
							|  |  |  |                 $this->currentCert['tbsCertificate']['subject'] = $subject->dn; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!empty($subject->publicKey)) { | 
					
						
							|  |  |  |                 $this->currentCert['tbsCertificate']['subjectPublicKeyInfo'] = $subjectPublicKey; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $this->removeExtension('id-ce-authorityKeyIdentifier'); | 
					
						
							|  |  |  |             if (isset($subject->domains)) { | 
					
						
							|  |  |  |                 $this->removeExtension('id-ce-subjectAltName'); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |         } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) { | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (!isset($subject->publicKey)) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |             $startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O'); | 
					
						
							|  |  |  |             $endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M Y H:i:s O', strtotime('+1 year')); | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |             if (!empty($this->serialNumber)) { | 
					
						
							|  |  |  |                 $serialNumber = $this->serialNumber; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 if (!function_exists('crypt_random_string')) { | 
					
						
							|  |  |  |                     include_once 'Crypt/Random.php'; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 /* "The serial number MUST be a positive integer" | 
					
						
							|  |  |  |                    "Conforming CAs MUST NOT use serialNumber values longer than 20 octets." | 
					
						
							|  |  |  |                     -- https://tools.ietf.org/html/rfc5280#section-4.1.2.2
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                    for the integer to be positive the leading bit needs to be 0 hence the | 
					
						
							|  |  |  |                    application of a bitmap | 
					
						
							|  |  |  |                 */ | 
					
						
							|  |  |  |                 $serialNumber = new Math_BigInteger(crypt_random_string(20) & ("\x7F" . str_repeat("\xFF", 19)), 256); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             $this->currentCert = array( | 
					
						
							|  |  |  |                 'tbsCertificate' => | 
					
						
							|  |  |  |                     array( | 
					
						
							|  |  |  |                         'version' => 'v3', | 
					
						
							|  |  |  |                         'serialNumber' => $serialNumber, // $this->setserialNumber()
 | 
					
						
							|  |  |  |                         'signature' => array('algorithm' => $signatureAlgorithm), | 
					
						
							|  |  |  |                         'issuer' => false, // this is going to be overwritten later
 | 
					
						
							|  |  |  |                         'validity' => array( | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                             'notBefore' => $this->_timeField($startDate), // $this->setStartDate()
 | 
					
						
							|  |  |  |                             'notAfter' => $this->_timeField($endDate)   // $this->setEndDate()
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                         ), | 
					
						
							|  |  |  |                         'subject' => $subject->dn, | 
					
						
							|  |  |  |                         'subjectPublicKeyInfo' => $subjectPublicKey | 
					
						
							|  |  |  |                     ), | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                     'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), | 
					
						
							|  |  |  |                     'signature'          => false // this is going to be overwritten later
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Copy extensions from CSR.
 | 
					
						
							|  |  |  |             $csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!empty($csrexts)) { | 
					
						
							|  |  |  |                 $this->currentCert['tbsCertificate']['extensions'] = $csrexts; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->currentCert['tbsCertificate']['issuer'] = $issuer->dn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($issuer->currentKeyIdentifier)) { | 
					
						
							|  |  |  |             $this->setExtension('id-ce-authorityKeyIdentifier', array( | 
					
						
							|  |  |  |                     //'authorityCertIssuer' => array(
 | 
					
						
							|  |  |  |                     //    array(
 | 
					
						
							|  |  |  |                     //        'directoryName' => $issuer->dn
 | 
					
						
							|  |  |  |                     //    )
 | 
					
						
							|  |  |  |                     //),
 | 
					
						
							|  |  |  |                     'keyIdentifier' => $issuer->currentKeyIdentifier | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                 )); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             //$extensions = &$this->currentCert['tbsCertificate']['extensions'];
 | 
					
						
							|  |  |  |             //if (isset($issuer->serialNumber)) {
 | 
					
						
							|  |  |  |             //    $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
 | 
					
						
							|  |  |  |             //}
 | 
					
						
							|  |  |  |             //unset($extensions);
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($subject->currentKeyIdentifier)) { | 
					
						
							|  |  |  |             $this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $altName = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($subject->domains) && count($subject->domains) > 1) { | 
					
						
							|  |  |  |             $altName = array_map(array('File_X509', '_dnsName'), $subject->domains); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($subject->ipAddresses) && count($subject->ipAddresses)) { | 
					
						
							|  |  |  |             // should an IP address appear as the CN if no domain name is specified? idk
 | 
					
						
							|  |  |  |             //$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1);
 | 
					
						
							|  |  |  |             $ipAddresses = array(); | 
					
						
							|  |  |  |             foreach ($subject->ipAddresses as $ipAddress) { | 
					
						
							|  |  |  |                 $encoded = $subject->_ipAddress($ipAddress); | 
					
						
							|  |  |  |                 if ($encoded !== false) { | 
					
						
							|  |  |  |                     $ipAddresses[] = $encoded; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (count($ipAddresses)) { | 
					
						
							|  |  |  |                 $altName = array_merge($altName, $ipAddresses); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($altName)) { | 
					
						
							|  |  |  |             $this->setExtension('id-ce-subjectAltName', $altName); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($this->caFlag) { | 
					
						
							|  |  |  |             $keyUsage = $this->getExtension('id-ce-keyUsage'); | 
					
						
							|  |  |  |             if (!$keyUsage) { | 
					
						
							|  |  |  |                 $keyUsage = array(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |             $this->setExtension( | 
					
						
							|  |  |  |                 'id-ce-keyUsage', | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                 array_values(array_unique(array_merge($keyUsage, array('cRLSign', 'keyCertSign')))) | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $basicConstraints = $this->getExtension('id-ce-basicConstraints'); | 
					
						
							|  |  |  |             if (!$basicConstraints) { | 
					
						
							|  |  |  |                 $basicConstraints = array(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |             $this->setExtension( | 
					
						
							|  |  |  |                 'id-ce-basicConstraints', | 
					
						
							|  |  |  |                 array_unique(array_merge(array('cA' => true), $basicConstraints)), | 
					
						
							|  |  |  |                 true | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (!isset($subject->currentKeyIdentifier)) { | 
					
						
							|  |  |  |                 $this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // resync $this->signatureSubject
 | 
					
						
							|  |  |  |         // save $tbsCertificate in case there are any File_ASN1_Element objects in it
 | 
					
						
							|  |  |  |         $tbsCertificate = $this->currentCert['tbsCertificate']; | 
					
						
							|  |  |  |         $this->loadX509($this->saveX509($this->currentCert)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = $this->_sign($issuer->privateKey, $signatureAlgorithm); | 
					
						
							|  |  |  |         $result['tbsCertificate'] = $tbsCertificate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->currentCert = $currentCert; | 
					
						
							|  |  |  |         $this->signatureSubject = $signatureSubject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Sign a CSR | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function signCSR($signatureAlgorithm = 'sha1WithRSAEncryption') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_object($this->privateKey) || empty($this->dn)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $origPublicKey = $this->publicKey; | 
					
						
							|  |  |  |         $class = get_class($this->privateKey); | 
					
						
							|  |  |  |         $this->publicKey = new $class(); | 
					
						
							|  |  |  |         $this->publicKey->loadKey($this->privateKey->getPublicKey()); | 
					
						
							|  |  |  |         $this->publicKey->setPublicKey(); | 
					
						
							|  |  |  |         if (!($publicKey = $this->_formatSubjectPublicKey())) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $this->publicKey = $origPublicKey; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $currentCert = isset($this->currentCert) ? $this->currentCert : null; | 
					
						
							|  |  |  |         $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['certificationRequestInfo'])) { | 
					
						
							|  |  |  |             $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; | 
					
						
							|  |  |  |             if (!empty($this->dn)) { | 
					
						
							|  |  |  |                 $this->currentCert['certificationRequestInfo']['subject'] = $this->dn; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $this->currentCert['certificationRequestInfo']['subjectPKInfo'] = $publicKey; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $this->currentCert = array( | 
					
						
							|  |  |  |                 'certificationRequestInfo' => | 
					
						
							|  |  |  |                     array( | 
					
						
							|  |  |  |                         'version' => 'v1', | 
					
						
							|  |  |  |                         'subject' => $this->dn, | 
					
						
							|  |  |  |                         'subjectPKInfo' => $publicKey | 
					
						
							|  |  |  |                     ), | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                     'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), | 
					
						
							|  |  |  |                     'signature'          => false // this is going to be overwritten later
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // resync $this->signatureSubject
 | 
					
						
							|  |  |  |         // save $certificationRequestInfo in case there are any File_ASN1_Element objects in it
 | 
					
						
							|  |  |  |         $certificationRequestInfo = $this->currentCert['certificationRequestInfo']; | 
					
						
							|  |  |  |         $this->loadCSR($this->saveCSR($this->currentCert)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = $this->_sign($this->privateKey, $signatureAlgorithm); | 
					
						
							|  |  |  |         $result['certificationRequestInfo'] = $certificationRequestInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->currentCert = $currentCert; | 
					
						
							|  |  |  |         $this->signatureSubject = $signatureSubject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Sign a SPKAC | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function signSPKAC($signatureAlgorithm = 'sha1WithRSAEncryption') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_object($this->privateKey)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $origPublicKey = $this->publicKey; | 
					
						
							|  |  |  |         $class = get_class($this->privateKey); | 
					
						
							|  |  |  |         $this->publicKey = new $class(); | 
					
						
							|  |  |  |         $this->publicKey->loadKey($this->privateKey->getPublicKey()); | 
					
						
							|  |  |  |         $this->publicKey->setPublicKey(); | 
					
						
							|  |  |  |         $publicKey = $this->_formatSubjectPublicKey(); | 
					
						
							|  |  |  |         if (!$publicKey) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $this->publicKey = $origPublicKey; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $currentCert = isset($this->currentCert) ? $this->currentCert : null; | 
					
						
							|  |  |  |         $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // re-signing a SPKAC seems silly but since everything else supports re-signing why not?
 | 
					
						
							|  |  |  |         if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['publicKeyAndChallenge'])) { | 
					
						
							|  |  |  |             $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; | 
					
						
							|  |  |  |             $this->currentCert['publicKeyAndChallenge']['spki'] = $publicKey; | 
					
						
							|  |  |  |             if (!empty($this->challenge)) { | 
					
						
							|  |  |  |                 // the bitwise AND ensures that the output is a valid IA5String
 | 
					
						
							|  |  |  |                 $this->currentCert['publicKeyAndChallenge']['challenge'] = $this->challenge & str_repeat("\x7F", strlen($this->challenge)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $this->currentCert = array( | 
					
						
							|  |  |  |                 'publicKeyAndChallenge' => | 
					
						
							|  |  |  |                     array( | 
					
						
							|  |  |  |                         'spki' => $publicKey, | 
					
						
							|  |  |  |                         // quoting <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen>,
 | 
					
						
							|  |  |  |                         // "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified."
 | 
					
						
							|  |  |  |                         // both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way
 | 
					
						
							|  |  |  |                         // we could alternatively do this instead if we ignored the specs:
 | 
					
						
							|  |  |  |                         // crypt_random_string(8) & str_repeat("\x7F", 8)
 | 
					
						
							|  |  |  |                         'challenge' => !empty($this->challenge) ? $this->challenge : '' | 
					
						
							|  |  |  |                     ), | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                     'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), | 
					
						
							|  |  |  |                     'signature'          => false // this is going to be overwritten later
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // resync $this->signatureSubject
 | 
					
						
							|  |  |  |         // save $publicKeyAndChallenge in case there are any File_ASN1_Element objects in it
 | 
					
						
							|  |  |  |         $publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge']; | 
					
						
							|  |  |  |         $this->loadSPKAC($this->saveSPKAC($this->currentCert)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = $this->_sign($this->privateKey, $signatureAlgorithm); | 
					
						
							|  |  |  |         $result['publicKeyAndChallenge'] = $publicKeyAndChallenge; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->currentCert = $currentCert; | 
					
						
							|  |  |  |         $this->signatureSubject = $signatureSubject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Sign a CRL | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * $issuer's private key needs to be loaded. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param File_X509 $issuer | 
					
						
							|  |  |  |      * @param File_X509 $crl | 
					
						
							|  |  |  |      * @param String $signatureAlgorithm optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function signCRL($issuer, $crl, $signatureAlgorithm = 'sha1WithRSAEncryption') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_object($issuer->privateKey) || empty($issuer->dn)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $currentCert = isset($this->currentCert) ? $this->currentCert : null; | 
					
						
							|  |  |  |         $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null; | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |         $thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O'); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) { | 
					
						
							|  |  |  |             $this->currentCert = $crl->currentCert; | 
					
						
							|  |  |  |             $this->currentCert['tbsCertList']['signature']['algorithm'] = $signatureAlgorithm; | 
					
						
							|  |  |  |             $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $this->currentCert = array( | 
					
						
							|  |  |  |                 'tbsCertList' => | 
					
						
							|  |  |  |                     array( | 
					
						
							|  |  |  |                         'version' => 'v2', | 
					
						
							|  |  |  |                         'signature' => array('algorithm' => $signatureAlgorithm), | 
					
						
							|  |  |  |                         'issuer' => false, // this is going to be overwritten later
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                         'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate()
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                     ), | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                     'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), | 
					
						
							|  |  |  |                     'signature'          => false // this is going to be overwritten later
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $tbsCertList = &$this->currentCert['tbsCertList']; | 
					
						
							|  |  |  |         $tbsCertList['issuer'] = $issuer->dn; | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |         $tbsCertList['thisUpdate'] = $this->_timeField($thisUpdate); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($this->endDate)) { | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |             $tbsCertList['nextUpdate'] = $this->_timeField($this->endDate); // $this->setEndDate()
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             unset($tbsCertList['nextUpdate']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($this->serialNumber)) { | 
					
						
							|  |  |  |             $crlNumber = $this->serialNumber; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $crlNumber = $this->getExtension('id-ce-cRLNumber'); | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |             // "The CRL number is a non-critical CRL extension that conveys a
 | 
					
						
							|  |  |  |             //  monotonically increasing sequence number for a given CRL scope and
 | 
					
						
							|  |  |  |             //  CRL issuer.  This extension allows users to easily determine when a
 | 
					
						
							|  |  |  |             //  particular CRL supersedes another CRL."
 | 
					
						
							|  |  |  |             // -- https://tools.ietf.org/html/rfc5280#section-5.2.3
 | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             $crlNumber = $crlNumber !== false ? $crlNumber->add(new Math_BigInteger(1)) : null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->removeExtension('id-ce-authorityKeyIdentifier'); | 
					
						
							|  |  |  |         $this->removeExtension('id-ce-issuerAltName'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Be sure version >= v2 if some extension found.
 | 
					
						
							|  |  |  |         $version = isset($tbsCertList['version']) ? $tbsCertList['version'] : 0; | 
					
						
							|  |  |  |         if (!$version) { | 
					
						
							|  |  |  |             if (!empty($tbsCertList['crlExtensions'])) { | 
					
						
							|  |  |  |                 $version = 1; // v2.
 | 
					
						
							|  |  |  |             } elseif (!empty($tbsCertList['revokedCertificates'])) { | 
					
						
							|  |  |  |                 foreach ($tbsCertList['revokedCertificates'] as $cert) { | 
					
						
							|  |  |  |                     if (!empty($cert['crlEntryExtensions'])) { | 
					
						
							|  |  |  |                         $version = 1; // v2.
 | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ($version) { | 
					
						
							|  |  |  |                 $tbsCertList['version'] = $version; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Store additional extensions.
 | 
					
						
							|  |  |  |         if (!empty($tbsCertList['version'])) { // At least v2.
 | 
					
						
							|  |  |  |             if (!empty($crlNumber)) { | 
					
						
							|  |  |  |                 $this->setExtension('id-ce-cRLNumber', $crlNumber); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (isset($issuer->currentKeyIdentifier)) { | 
					
						
							|  |  |  |                 $this->setExtension('id-ce-authorityKeyIdentifier', array( | 
					
						
							|  |  |  |                         //'authorityCertIssuer' => array(
 | 
					
						
							|  |  |  |                         //    array(
 | 
					
						
							|  |  |  |                         //        'directoryName' => $issuer->dn
 | 
					
						
							|  |  |  |                         //    )
 | 
					
						
							|  |  |  |                         //),
 | 
					
						
							|  |  |  |                         'keyIdentifier' => $issuer->currentKeyIdentifier | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                     )); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                 //$extensions = &$tbsCertList['crlExtensions'];
 | 
					
						
							|  |  |  |                 //if (isset($issuer->serialNumber)) {
 | 
					
						
							|  |  |  |                 //    $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
 | 
					
						
							|  |  |  |                 //}
 | 
					
						
							|  |  |  |                 //unset($extensions);
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $issuerAltName = $this->getExtension('id-ce-subjectAltName', $issuer->currentCert); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ($issuerAltName !== false) { | 
					
						
							|  |  |  |                 $this->setExtension('id-ce-issuerAltName', $issuerAltName); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (empty($tbsCertList['revokedCertificates'])) { | 
					
						
							|  |  |  |             unset($tbsCertList['revokedCertificates']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         unset($tbsCertList); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // resync $this->signatureSubject
 | 
					
						
							|  |  |  |         // save $tbsCertList in case there are any File_ASN1_Element objects in it
 | 
					
						
							|  |  |  |         $tbsCertList = $this->currentCert['tbsCertList']; | 
					
						
							|  |  |  |         $this->loadCRL($this->saveCRL($this->currentCert)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = $this->_sign($issuer->privateKey, $signatureAlgorithm); | 
					
						
							|  |  |  |         $result['tbsCertList'] = $tbsCertList; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->currentCert = $currentCert; | 
					
						
							|  |  |  |         $this->signatureSubject = $signatureSubject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * X.509 certificate signing helper function. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Object $key | 
					
						
							|  |  |  |      * @param File_X509 $subject | 
					
						
							|  |  |  |      * @param String $signatureAlgorithm | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _sign($key, $signatureAlgorithm) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (strtolower(get_class($key))) { | 
					
						
							|  |  |  |             case 'crypt_rsa': | 
					
						
							|  |  |  |                 switch ($signatureAlgorithm) { | 
					
						
							|  |  |  |                     case 'md2WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'md5WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha1WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha224WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha256WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha384WithRSAEncryption': | 
					
						
							|  |  |  |                     case 'sha512WithRSAEncryption': | 
					
						
							|  |  |  |                         $key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm)); | 
					
						
							|  |  |  |                         $key->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         $this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject)); | 
					
						
							|  |  |  |                         return $this->currentCert; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set certificate start date | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $date | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setStartDate($date) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |         $this->startDate = @date('D, d M Y H:i:s O', @strtotime($date)); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set certificate end date | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $date | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setEndDate($date) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /* | 
					
						
							|  |  |  |           To indicate that a certificate has no well-defined expiration date, | 
					
						
							|  |  |  |           the notAfter SHOULD be assigned the GeneralizedTime value of | 
					
						
							|  |  |  |           99991231235959Z. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           -- http://tools.ietf.org/html/rfc5280#section-4.1.2.5
 | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |         if (strtolower($date) == 'lifetime') { | 
					
						
							|  |  |  |             $temp = '99991231235959Z'; | 
					
						
							|  |  |  |             $asn1 = new File_ASN1(); | 
					
						
							|  |  |  |             $temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp; | 
					
						
							|  |  |  |             $this->endDate = new File_ASN1_Element($temp); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |             $this->endDate = @date('D, d M Y H:i:s O', @strtotime($date)); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set Serial Number | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $serial | 
					
						
							|  |  |  |      * @param $base optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setSerialNumber($serial, $base = -256) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->serialNumber = new Math_BigInteger($serial, $base); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Turns the certificate into a certificate authority | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function makeCA() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->caFlag = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a reference to a subarray | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $root | 
					
						
							|  |  |  |      * @param String $path  absolute path with / as component separator | 
					
						
							|  |  |  |      * @param Boolean $create optional | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return array item ref or false | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function &_subArray(&$root, $path, $create = false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $false = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($root)) { | 
					
						
							|  |  |  |             return $false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach (explode('/', $path) as $i) { | 
					
						
							|  |  |  |             if (!is_array($root)) { | 
					
						
							|  |  |  |                 return $false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!isset($root[$i])) { | 
					
						
							|  |  |  |                 if (!$create) { | 
					
						
							|  |  |  |                     return $false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 $root[$i] = array(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $root = &$root[$i]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $root; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a reference to an extension subarray | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $root | 
					
						
							|  |  |  |      * @param String $path optional absolute path with / as component separator | 
					
						
							|  |  |  |      * @param Boolean $create optional | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return array ref or false | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function &_extensions(&$root, $path = null, $create = false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!isset($root)) { | 
					
						
							|  |  |  |             $root = $this->currentCert; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case !empty($path): | 
					
						
							|  |  |  |             case !is_array($root): | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case isset($root['tbsCertificate']): | 
					
						
							|  |  |  |                 $path = 'tbsCertificate/extensions'; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case isset($root['tbsCertList']): | 
					
						
							|  |  |  |                 $path = 'tbsCertList/crlExtensions'; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case isset($root['certificationRequestInfo']): | 
					
						
							|  |  |  |                 $pth = 'certificationRequestInfo/attributes'; | 
					
						
							|  |  |  |                 $attributes = &$this->_subArray($root, $pth, $create); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (is_array($attributes)) { | 
					
						
							|  |  |  |                     foreach ($attributes as $key => $value) { | 
					
						
							|  |  |  |                         if ($value['type'] == 'pkcs-9-at-extensionRequest') { | 
					
						
							|  |  |  |                             $path = "$pth/$key/value/0"; | 
					
						
							|  |  |  |                             break 2; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if ($create) { | 
					
						
							|  |  |  |                         $key = count($attributes); | 
					
						
							|  |  |  |                         $attributes[] = array('type' => 'pkcs-9-at-extensionRequest', 'value' => array()); | 
					
						
							|  |  |  |                         $path = "$pth/$key/value/0"; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $extensions = &$this->_subArray($root, $path, $create); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($extensions)) { | 
					
						
							|  |  |  |             $false = false; | 
					
						
							|  |  |  |             return $false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $extensions; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Remove an Extension | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param String $path optional | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _removeExtension($id, $path = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $extensions = &$this->_extensions($this->currentCert, $path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($extensions)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = false; | 
					
						
							|  |  |  |         foreach ($extensions as $key => $value) { | 
					
						
							|  |  |  |             if ($value['extnId'] == $id) { | 
					
						
							|  |  |  |                 unset($extensions[$key]); | 
					
						
							|  |  |  |                 $result = true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $extensions = array_values($extensions); | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get an Extension | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Returns the extension if it exists and false if not | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param Array $cert optional | 
					
						
							|  |  |  |      * @param String $path optional | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _getExtension($id, $cert = null, $path = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $extensions = $this->_extensions($cert, $path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($extensions)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($extensions as $key => $value) { | 
					
						
							|  |  |  |             if ($value['extnId'] == $id) { | 
					
						
							|  |  |  |                 return $value['extnValue']; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Returns a list of all extensions in use | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $cert optional | 
					
						
							|  |  |  |      * @param String $path optional | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _getExtensions($cert = null, $path = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $exts = $this->_extensions($cert, $path); | 
					
						
							|  |  |  |         $extensions = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($exts)) { | 
					
						
							|  |  |  |             foreach ($exts as $extension) { | 
					
						
							|  |  |  |                 $extensions[] = $extension['extnId']; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $extensions; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set an Extension | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param Mixed $value | 
					
						
							|  |  |  |      * @param Boolean $critical optional | 
					
						
							|  |  |  |      * @param Boolean $replace optional | 
					
						
							|  |  |  |      * @param String $path optional | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _setExtension($id, $value, $critical = false, $replace = true, $path = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $extensions = &$this->_extensions($this->currentCert, $path, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($extensions)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $newext = array('extnId'  => $id, 'critical' => $critical, 'extnValue' => $value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($extensions as $key => $value) { | 
					
						
							|  |  |  |             if ($value['extnId'] == $id) { | 
					
						
							|  |  |  |                 if (!$replace) { | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 $extensions[$key] = $newext; | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $extensions[] = $newext; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Remove a certificate, CSR or CRL Extension | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function removeExtension($id) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->_removeExtension($id); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a certificate, CSR or CRL Extension | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Returns the extension if it exists and false if not | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param Array $cert optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getExtension($id, $cert = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->_getExtension($id, $cert); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Returns a list of all extensions in use in certificate, CSR or CRL | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $cert optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getExtensions($cert = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->_getExtensions($cert); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set a certificate, CSR or CRL Extension | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param Mixed $value | 
					
						
							|  |  |  |      * @param Boolean $critical optional | 
					
						
							|  |  |  |      * @param Boolean $replace optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setExtension($id, $value, $critical = false, $replace = true) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->_setExtension($id, $value, $critical, $replace); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Remove a CSR attribute. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param Integer $disposition optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function removeAttribute($id, $disposition = FILE_X509_ATTR_ALL) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($attributes)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = false; | 
					
						
							|  |  |  |         foreach ($attributes as $key => $attribute) { | 
					
						
							|  |  |  |             if ($attribute['type'] == $id) { | 
					
						
							|  |  |  |                 $n = count($attribute['value']); | 
					
						
							|  |  |  |                 switch (true) { | 
					
						
							|  |  |  |                     case $disposition == FILE_X509_ATTR_APPEND: | 
					
						
							|  |  |  |                     case $disposition == FILE_X509_ATTR_REPLACE: | 
					
						
							|  |  |  |                         return false; | 
					
						
							|  |  |  |                     case $disposition >= $n: | 
					
						
							|  |  |  |                         $disposition -= $n; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case $disposition == FILE_X509_ATTR_ALL: | 
					
						
							|  |  |  |                     case $n == 1: | 
					
						
							|  |  |  |                         unset($attributes[$key]); | 
					
						
							|  |  |  |                         $result = true; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     default: | 
					
						
							|  |  |  |                         unset($attributes[$key]['value'][$disposition]); | 
					
						
							|  |  |  |                         $attributes[$key]['value'] = array_values($attributes[$key]['value']); | 
					
						
							|  |  |  |                         $result = true; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if ($result && $disposition != FILE_X509_ATTR_ALL) { | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attributes = array_values($attributes); | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a CSR attribute | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Returns the attribute if it exists and false if not | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param Integer $disposition optional | 
					
						
							|  |  |  |      * @param Array $csr optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getAttribute($id, $disposition = FILE_X509_ATTR_ALL, $csr = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (empty($csr)) { | 
					
						
							|  |  |  |             $csr = $this->currentCert; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attributes = $this->_subArray($csr, 'certificationRequestInfo/attributes'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($attributes)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($attributes as $key => $attribute) { | 
					
						
							|  |  |  |             if ($attribute['type'] == $id) { | 
					
						
							|  |  |  |                 $n = count($attribute['value']); | 
					
						
							|  |  |  |                 switch (true) { | 
					
						
							|  |  |  |                     case $disposition == FILE_X509_ATTR_APPEND: | 
					
						
							|  |  |  |                     case $disposition == FILE_X509_ATTR_REPLACE: | 
					
						
							|  |  |  |                         return false; | 
					
						
							|  |  |  |                     case $disposition == FILE_X509_ATTR_ALL: | 
					
						
							|  |  |  |                         return $attribute['value']; | 
					
						
							|  |  |  |                     case $disposition >= $n: | 
					
						
							|  |  |  |                         $disposition -= $n; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     default: | 
					
						
							|  |  |  |                         return $attribute['value'][$disposition]; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Returns a list of all CSR attributes in use | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $csr optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getAttributes($csr = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (empty($csr)) { | 
					
						
							|  |  |  |             $csr = $this->currentCert; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $attributes = $this->_subArray($csr, 'certificationRequestInfo/attributes'); | 
					
						
							|  |  |  |         $attrs = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($attributes)) { | 
					
						
							|  |  |  |             foreach ($attributes as $attribute) { | 
					
						
							|  |  |  |                 $attrs[] = $attribute['type']; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $attrs; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set a CSR attribute | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param Mixed $value | 
					
						
							|  |  |  |      * @param Boolean $disposition optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setAttribute($id, $value, $disposition = FILE_X509_ATTR_ALL) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes', true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($attributes)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ($disposition) { | 
					
						
							|  |  |  |             case FILE_X509_ATTR_REPLACE: | 
					
						
							|  |  |  |                 $disposition = FILE_X509_ATTR_APPEND; | 
					
						
							|  |  |  |             case FILE_X509_ATTR_ALL: | 
					
						
							|  |  |  |                 $this->removeAttribute($id); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($attributes as $key => $attribute) { | 
					
						
							|  |  |  |             if ($attribute['type'] == $id) { | 
					
						
							|  |  |  |                 $n = count($attribute['value']); | 
					
						
							|  |  |  |                 switch (true) { | 
					
						
							|  |  |  |                     case $disposition == FILE_X509_ATTR_APPEND: | 
					
						
							|  |  |  |                         $last = $key; | 
					
						
							|  |  |  |                         break; | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                     case $disposition >= $n: | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                         $disposition -= $n; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     default: | 
					
						
							|  |  |  |                         $attributes[$key]['value'][$disposition] = $value; | 
					
						
							|  |  |  |                         return true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case $disposition >= 0: | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             case isset($last): | 
					
						
							|  |  |  |                 $attributes[$last]['value'][] = $value; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 $attributes[] = array('type' => $id, 'value' => $disposition == FILE_X509_ATTR_ALL ? $value: array($value)); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Sets the subject key identifier | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $value | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setKeyIdentifier($value) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (empty($value)) { | 
					
						
							|  |  |  |             unset($this->currentKeyIdentifier); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $this->currentKeyIdentifier = base64_encode($value); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Compute a public key identifier. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Although key identifiers may be set to any unique value, this function
 | 
					
						
							|  |  |  |      * computes key identifiers from public key according to the two | 
					
						
							|  |  |  |      * recommended methods (4.2.1.2 RFC 3280). | 
					
						
							|  |  |  |      * Highly polymorphic: try to accept all possible forms of key: | 
					
						
							|  |  |  |      * - Key object | 
					
						
							|  |  |  |      * - File_X509 object with public or private key defined | 
					
						
							|  |  |  |      * - Certificate or CSR array | 
					
						
							|  |  |  |      * - File_ASN1_Element object | 
					
						
							|  |  |  |      * - PEM or DER string | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Mixed $key optional | 
					
						
							|  |  |  |      * @param Integer $method optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return String binary key identifier | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function computeKeyIdentifier($key = null, $method = 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_null($key)) { | 
					
						
							|  |  |  |             $key = $this; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (true) { | 
					
						
							|  |  |  |             case is_string($key): | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case is_array($key) && isset($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']): | 
					
						
							|  |  |  |                 return $this->computeKeyIdentifier($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $method); | 
					
						
							|  |  |  |             case is_array($key) && isset($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']): | 
					
						
							|  |  |  |                 return $this->computeKeyIdentifier($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $method); | 
					
						
							|  |  |  |             case !is_object($key): | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             case strtolower(get_class($key)) == 'file_asn1_element': | 
					
						
							|  |  |  |                 // Assume the element is a bitstring-packed key.
 | 
					
						
							|  |  |  |                 $asn1 = new File_ASN1(); | 
					
						
							|  |  |  |                 $decoded = $asn1->decodeBER($key->element); | 
					
						
							|  |  |  |                 if (empty($decoded)) { | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $raw = $asn1->asn1map($decoded[0], array('type' => FILE_ASN1_TYPE_BIT_STRING)); | 
					
						
							|  |  |  |                 if (empty($raw)) { | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $raw = base64_decode($raw); | 
					
						
							|  |  |  |                 // If the key is private, compute identifier from its corresponding public key.
 | 
					
						
							|  |  |  |                 if (!class_exists('Crypt_RSA')) { | 
					
						
							|  |  |  |                     include_once 'Crypt/RSA.php'; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $key = new Crypt_RSA(); | 
					
						
							|  |  |  |                 if (!$key->loadKey($raw)) { | 
					
						
							|  |  |  |                     return false;   // Not an unencrypted RSA key.
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if ($key->getPrivateKey() !== false) {  // If private.
 | 
					
						
							|  |  |  |                     return $this->computeKeyIdentifier($key, $method); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $key = $raw;    // Is a public key.
 | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case strtolower(get_class($key)) == 'file_x509': | 
					
						
							|  |  |  |                 if (isset($key->publicKey)) { | 
					
						
							|  |  |  |                     return $this->computeKeyIdentifier($key->publicKey, $method); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (isset($key->privateKey)) { | 
					
						
							|  |  |  |                     return $this->computeKeyIdentifier($key->privateKey, $method); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (isset($key->currentCert['tbsCertificate']) || isset($key->currentCert['certificationRequestInfo'])) { | 
					
						
							|  |  |  |                     return $this->computeKeyIdentifier($key->currentCert, $method); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             default: // Should be a key object (i.e.: Crypt_RSA).
 | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                 $key = $key->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // If in PEM format, convert to binary.
 | 
					
						
							|  |  |  |         $key = $this->_extractBER($key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Now we have the key string: compute its sha-1 sum.
 | 
					
						
							|  |  |  |         if (!class_exists('Crypt_Hash')) { | 
					
						
							|  |  |  |             include_once 'Crypt/Hash.php'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $hash = new Crypt_Hash('sha1'); | 
					
						
							|  |  |  |         $hash = $hash->hash($key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($method == 2) { | 
					
						
							|  |  |  |             $hash = substr($hash, -8); | 
					
						
							|  |  |  |             $hash[0] = chr((ord($hash[0]) & 0x0F) | 0x40); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $hash; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Format a public key as appropriate | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _formatSubjectPublicKey() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!isset($this->publicKey) || !is_object($this->publicKey)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (strtolower(get_class($this->publicKey))) { | 
					
						
							|  |  |  |             case 'crypt_rsa': | 
					
						
							|  |  |  |                 // the following two return statements do the same thing. i dunno.. i just prefer the later for some reason.
 | 
					
						
							|  |  |  |                 // the former is a good example of how to do fuzzing on the public key
 | 
					
						
							|  |  |  |                 //return new File_ASN1_Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())));
 | 
					
						
							|  |  |  |                 return array( | 
					
						
							|  |  |  |                     'algorithm' => array('algorithm' => 'rsaEncryption'), | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                     'subjectPublicKey' => $this->publicKey->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1) | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                 ); | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set the domain name's which the cert is to be valid for | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setDomain() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->domains = func_get_args(); | 
					
						
							|  |  |  |         $this->removeDNProp('id-at-commonName'); | 
					
						
							|  |  |  |         $this->setDNProp('id-at-commonName', $this->domains[0]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set the IP Addresses's which the cert is to be valid for | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @param String $ipAddress optional | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setIPAddress() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->ipAddresses = func_get_args(); | 
					
						
							|  |  |  |         /* | 
					
						
							|  |  |  |         if (!isset($this->domains)) { | 
					
						
							|  |  |  |             $this->removeDNProp('id-at-commonName'); | 
					
						
							|  |  |  |             $this->setDNProp('id-at-commonName', $this->ipAddresses[0]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Helper function to build domain array | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @param String $domain | 
					
						
							|  |  |  |      * @return Array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _dnsName($domain) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return array('dNSName' => $domain); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Helper function to build IP Address array | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * (IPv6 is not currently supported) | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @param String $address | 
					
						
							|  |  |  |      * @return Array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _iPAddress($address) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return array('iPAddress' => $address); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the index of a revoked certificate. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $rclist | 
					
						
							|  |  |  |      * @param String $serial | 
					
						
							|  |  |  |      * @param Boolean $create optional | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @return Integer or false | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _revokedCertificate(&$rclist, $serial, $create = false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $serial = new Math_BigInteger($serial); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($rclist as $i => $rc) { | 
					
						
							|  |  |  |             if (!($serial->compare($rc['userCertificate']))) { | 
					
						
							|  |  |  |                 return $i; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!$create) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $i = count($rclist); | 
					
						
							|  |  |  |         $rclist[] = array('userCertificate' => $serial, | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                           'revocationDate'  => $this->_timeField(@date('D, d M Y H:i:s O'))); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |         return $i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Revoke a certificate. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $serial | 
					
						
							|  |  |  |      * @param String $date optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function revoke($serial, $date = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (isset($this->currentCert['tbsCertList'])) { | 
					
						
							|  |  |  |             if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) { | 
					
						
							|  |  |  |                 if ($this->_revokedCertificate($rclist, $serial) === false) { // If not yet revoked
 | 
					
						
							|  |  |  |                     if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) { | 
					
						
							|  |  |  |                         if (!empty($date)) { | 
					
						
							| 
									
										
										
										
											2015-07-06 19:44:12 +00:00
										 |  |  |                             $rclist[$i]['revocationDate'] = $this->_timeField($date); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         return true; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Unrevoke a certificate. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $serial | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function unrevoke($serial) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) { | 
					
						
							|  |  |  |             if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) { | 
					
						
							|  |  |  |                 unset($rclist[$i]); | 
					
						
							|  |  |  |                 $rclist = array_values($rclist); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a revoked certificate. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $serial | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getRevoked($serial) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_array($rclist = $this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) { | 
					
						
							|  |  |  |             if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) { | 
					
						
							|  |  |  |                 return $rclist[$i]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * List revoked certificates | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $crl optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function listRevoked($crl = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!isset($crl)) { | 
					
						
							|  |  |  |             $crl = $this->currentCert; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!isset($crl['tbsCertList'])) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) { | 
					
						
							|  |  |  |             foreach ($rclist as $rc) { | 
					
						
							|  |  |  |                 $result[] = $rc['userCertificate']->toString(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Remove a Revoked Certificate Extension | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $serial | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function removeRevokedCertificateExtension($serial, $id) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) { | 
					
						
							|  |  |  |             if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) { | 
					
						
							|  |  |  |                 return $this->_removeExtension($id, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a Revoked Certificate Extension | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Returns the extension if it exists and false if not | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $serial | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param Array $crl optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getRevokedCertificateExtension($serial, $id, $crl = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!isset($crl)) { | 
					
						
							|  |  |  |             $crl = $this->currentCert; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) { | 
					
						
							|  |  |  |             if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) { | 
					
						
							| 
									
										
										
										
											2015-10-04 13:24:43 +00:00
										 |  |  |                 return $this->_getExtension($id, $crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); | 
					
						
							| 
									
										
										
										
											2014-03-30 06:57:20 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Returns a list of all extensions in use for a given revoked certificate | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $serial | 
					
						
							|  |  |  |      * @param array $crl optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getRevokedCertificateExtensions($serial, $crl = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!isset($crl)) { | 
					
						
							|  |  |  |             $crl = $this->currentCert; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) { | 
					
						
							|  |  |  |             if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) { | 
					
						
							|  |  |  |                 return $this->_getExtensions($crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set a Revoked Certificate Extension | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param String $serial | 
					
						
							|  |  |  |      * @param String $id | 
					
						
							|  |  |  |      * @param Mixed $value | 
					
						
							|  |  |  |      * @param Boolean $critical optional | 
					
						
							|  |  |  |      * @param Boolean $replace optional | 
					
						
							|  |  |  |      * @access public | 
					
						
							|  |  |  |      * @return Boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (isset($this->currentCert['tbsCertList'])) { | 
					
						
							|  |  |  |             if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) { | 
					
						
							|  |  |  |                 if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) { | 
					
						
							|  |  |  |                     return $this->_setExtension($id, $value, $critical, $replace, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Extract raw BER from Base64 encoding | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @access private | 
					
						
							|  |  |  |      * @param String $str | 
					
						
							|  |  |  |      * @return String | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function _extractBER($str) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them | 
					
						
							|  |  |  |          * above and beyond the ceritificate. | 
					
						
							|  |  |  |          * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line: | 
					
						
							|  |  |  |          * | 
					
						
							|  |  |  |          * Bag Attributes | 
					
						
							|  |  |  |          *     localKeyID: 01 00 00 00 | 
					
						
							|  |  |  |          * subject=/O=organization/OU=org unit/CN=common name | 
					
						
							|  |  |  |          * issuer=/O=organization/CN=common name | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         $temp = preg_replace('#.*?^-+[^-]+-+#ms', '', $str, 1); | 
					
						
							|  |  |  |         // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
 | 
					
						
							|  |  |  |         $temp = preg_replace('#-+[^-]+-+#', '', $temp); | 
					
						
							|  |  |  |         // remove new lines
 | 
					
						
							|  |  |  |         $temp = str_replace(array("\r", "\n", ' '), '', $temp); | 
					
						
							|  |  |  |         $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false; | 
					
						
							|  |  |  |         return $temp != false ? $temp : $str; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |