Added: vcl/trunk/web/.ht-inc/phpseclib/File/X509.php
URL: 
http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/phpseclib/File/X509.php?rev=1796097&view=auto
==============================================================================
--- vcl/trunk/web/.ht-inc/phpseclib/File/X509.php (added)
+++ vcl/trunk/web/.ht-inc/phpseclib/File/X509.php Wed May 24 20:28:10 2017
@@ -0,0 +1,4887 @@
+<?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 <[email protected]>
+ * @copyright 2012 Jim Wigginton
+ * @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 self::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 self::saveX509()
+ * @see self::saveCSR()
+ * @see self::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);
+/**
+ * Auto-detect the format
+ *
+ * Used only by the load*() functions
+ */
+define('FILE_X509_FORMAT_AUTO_DETECT', 3);
+/**#@-*/
+
+/**
+ * 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 <[email protected]>
+ * @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 $SubjectDirectoryAttributes;
+    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 various DN attributes
+     *
+     * @access private
+     */
+    var $PostalAddress;
+    /**#@-*/
+
+    /**
+     * 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 re-encode 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 bool
+     * @access private
+     */
+    var $caFlag = false;
+
+    /**
+     * SPKAC Challenge
+     *
+     * @var string
+     * @access private
+     */
+    var $challenge;
+
+    /**
+     * Default Constructor.
+     *
+     * @return File_X509
+     * @access public
+     */
+    function __construct()
+    {
+        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
+                          )
+            )
+        );
+
+        $this->SubjectDirectoryAttributes = array(
+            'type'     => FILE_ASN1_TYPE_SEQUENCE,
+            'min'      => 1,
+            'max'      => -1,
+            'children' => $Attribute
+        );
+
+        // 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)
+            )
+        );
+
+        $this->PostalAddress = array(
+            'type'     => FILE_ASN1_TYPE_SEQUENCE,
+            'optional' => true,
+            'min'      => 1,
+            'max'      => -1,
+            'children' => $this->DirectoryString
+        );
+
+        // 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',
+            '2.5.4.16' => 'id-at-postalAddress',
+
+            '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
+        );
+    }
+
+    /**
+     * PHP4 compatible Default Constructor.
+     *
+     * @see self::__construct()
+     * @access public
+     */
+    function File_X509()
+    {
+        $this->__construct();
+    }
+
+    /**
+     * 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
+     * @param int $mode
+     * @access public
+     * @return mixed
+     */
+    function loadX509($cert, $mode = FILE_X509_FORMAT_AUTO_DETECT)
+    {
+        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();
+
+        if ($mode != FILE_X509_FORMAT_DER) {
+            $newcert = $this->_extractBER($cert);
+            if ($mode == FILE_X509_FORMAT_PEM && $cert == $newcert) {
+                return false;
+            }
+            $cert = $newcert;
+        }
+
+        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']);
+
+        if ($this->_isSubArrayValid($x509, 'tbsCertificate/extensions')) {
+            $this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1);
+        }
+        $this->_mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence', $asn1);
+        $this->_mapInDNs($x509, 'tbsCertificate/subject/rdnSequence', $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 int $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'])));
+                        /* "[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;
+                }
+        }
+
+        $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);
+        $this->_mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence', $asn1);
+        $this->_mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence', $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->_subArrayUnchecked($root, $path);
+
+        if ($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;
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    $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++) {
+                if (is_object($extensions[$i]) && 
strtolower(get_class($extensions[$i])) == 'file_asn1_element') {
+                    continue;
+                }
+
+                $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->_isSubArrayValid($values, $j)) {
+                                $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);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Map DN values from ANY type to DN-specific internal
+     *   format.
+     *
+     * @param array ref $root
+     * @param string $path
+     * @param object $asn1
+     * @access private
+     */
+    function _mapInDNs(&$root, $path, $asn1)
+    {
+        $dns = &$this->_subArray($root, $path);
+
+        if (is_array($dns)) {
+            for ($i = 0; $i < count($dns); $i++) {
+                for ($j = 0; $j < count($dns[$i]); $j++) {
+                    $type = $dns[$i][$j]['type'];
+                    $value = &$dns[$i][$j]['value'];
+                    if (is_object($value) && strtolower(get_class($value)) == 
'file_asn1_element') {
+                        $map = $this->_getMapping($type);
+                        if (!is_bool($map)) {
+                            $decoded = $asn1->decodeBER($value);
+                            $value = $asn1->asn1map($decoded[0], $map);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Map DN values from DN-specific internal format to
+     *   ANY type.
+     *
+     * @param array ref $root
+     * @param string $path
+     * @param object $asn1
+     * @access private
+     */
+    function _mapOutDNs(&$root, $path, $asn1)
+    {
+        $dns = &$this->_subArray($root, $path);
+
+        if (is_array($dns)) {
+            $size = count($dns);
+            for ($i = 0; $i < $size; $i++) {
+                for ($j = 0; $j < count($dns[$i]); $j++) {
+                    $type = $dns[$i][$j]['type'];
+                    $value = &$dns[$i][$j]['value'];
+                    if (is_object($value) && strtolower(get_class($value)) == 
'file_asn1_element') {
+                        continue;
+                    }
+
+                    $map = $this->_getMapping($type);
+                    if (!is_bool($map)) {
+                        $value = new 
File_ASN1_Element($asn1->encodeDER($value, $map));
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 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-subjectDirectoryAttributes':
+                return $this->SubjectDirectoryAttributes;
+            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
+            // "Certificate Transparency"
+            // https://tools.ietf.org/html/rfc6962
+            case '1.3.6.1.4.1.11129.2.4.2':
+                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;
+            case 'id-at-postalAddress':
+                return $this->PostalAddress;
+        }
+
+        return false;
+    }
+
+    /**
+     * Load an X.509 certificate as a certificate authority
+     *
+     * @param string $cert
+     * @access public
+     * @return bool
+     */
+    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 bool
+     */
+    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

[... 2804 lines stripped ...]

Reply via email to