Beispiel #1
0
    /**
     * Save Certificate Revocation List.
     *
     * @param array $crl
     * @param int $format optional
     * @access public
     * @return string
     */
    function saveCRL($crl, $format = self::FORMAT_PEM)
    {
        if (!is_array($crl) || !isset($crl['tbsCertList'])) {
            return false;
        }

        $asn1 = new ASN1();

        $asn1->loadOIDs($this->oids);

        $filters = array();
        $filters['tbsCertList']['issuer']['rdnSequence']['value']
            = array('type' => ASN1::TYPE_UTF8_STRING);
        $filters['tbsCertList']['signature']['parameters']
            = array('type' => ASN1::TYPE_UTF8_STRING);
        $filters['signatureAlgorithm']['parameters']
            = array('type' => ASN1::TYPE_UTF8_STRING);

        if (empty($crl['tbsCertList']['signature']['parameters'])) {
            $filters['tbsCertList']['signature']['parameters']
                = array('type' => ASN1::TYPE_NULL);
        }

        if (empty($crl['signatureAlgorithm']['parameters'])) {
            $filters['signatureAlgorithm']['parameters']
                = array('type' => 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 self::FORMAT_DER:
                return $crl;
            // case self::FORMAT_PEM:
            default:
                return "-----BEGIN X509 CRL-----\r\n" . chunk_split(base64_encode($crl), 64) . '-----END X509 CRL-----';
        }
    }
Beispiel #2
0
 /**
  * Wrap a private key appropriately
  *
  * @access public
  * @param string $algorithm
  * @param string $key
  * @param string $attr
  * @param string $password
  * @return string
  */
 static function wrapPrivateKey($key, $algorithm, $attr, $password)
 {
     $asn1 = new ASN1();
     $asn1->loadOIDs(oids);
     $key = ['version' => 'v1', 'privateKeyAlgorithm' => ['algorithm' => $algorithm], 'privateKey' => Base64::encode($key)];
     if (!empty($attr)) {
         $key['attributes'] = $attr;
     }
     $key = $asn1->encodeDER($key, PrivateKeyInfo);
     if (!empty($password) && is_string($password)) {
         $salt = Random::string(8);
         $iterationCount = self::$defaultIterationCount;
         if (self::$defaultEncryptionAlgorithm == 'id-PBES2') {
             $crypto = self::getPBES2EncryptionObject(self::$defaultEncryptionScheme);
             $hash = str_replace('-', '/', substr(self::$defaultPRF, 11));
             $kdf = 'pbkdf2';
             $iv = Random::string($crypto->getBlockLength() >> 3);
             $PBKDF2params = ['salt' => Base64::encode($salt), 'iterationCount' => $iterationCount, 'prf' => ['algorithm' => self::$defaultPRF, 'parameters' => null]];
             $PBKDF2params = $asn1->encodeDER($PBKDF2params, PBKDF2params);
             if (!$crypto instanceof RC2) {
                 $params = ['octetString' => Base64::encode($iv)];
             } else {
                 $params = ['rc2ParametersVersion' => 58, 'iv' => Base64::encode($iv)];
                 $params = $asn1->encodeDER($params, RC2CBCParameter);
                 $params = new ASN1\Element($params);
             }
             $params = ['keyDerivationFunc' => ['algorithm' => 'id-PBKDF2', 'parameters' => new ASN1\Element($PBKDF2params)], 'encryptionScheme' => ['algorithm' => self::$defaultEncryptionScheme, 'parameters' => $params]];
             $params = $asn1->encodeDER($params, PBES2params);
             $crypto->setIV($iv);
         } else {
             $crypto = self::getPBES1EncryptionObject(self::$defaultEncryptionAlgorithm);
             $hash = self::getPBES1Hash(self::$defaultEncryptionAlgorithm);
             $kdf = self::getPBES1KDF(self::$defaultEncryptionAlgorithm);
             $params = ['salt' => Base64::encode($salt), 'iterationCount' => $iterationCount];
             $params = $asn1->encodeDER($params, PBEParameter);
         }
         $crypto->setPassword($password, $kdf, $hash, $salt, $iterationCount);
         $key = $crypto->encrypt($key);
         $key = ['encryptionAlgorithm' => ['algorithm' => self::$defaultEncryptionAlgorithm, 'parameters' => new ASN1\Element($params)], 'encryptedData' => Base64::encode($key)];
         $key = $asn1->encodeDER($key, EncryptedPrivateKeyInfo);
         return "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END ENCRYPTED PRIVATE KEY-----";
     }
     return "-----BEGIN PRIVATE KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END PRIVATE KEY-----";
 }
Beispiel #3
0
 /**
  * RSASSA-PKCS1-V1_5-VERIFY (relaxed matching)
  *
  * Per {@link http://tools.ietf.org/html/rfc3447#page-43 RFC3447#page-43} PKCS1 v1.5
  * specified the use BER encoding rather than DER encoding that PKCS1 v2.0 specified.
  * This means that under rare conditions you can have a perfectly valid v1.5 signature
  * that fails to validate with _rsassa_pkcs1_v1_5_verify(). PKCS1 v2.1 also recommends
  * that if you're going to validate these types of signatures you "should indicate
  * whether the underlying BER encoding is a DER encoding and hence whether the signature
  * is valid with respect to the specification given in [PKCS1 v2.0+]". so if you do
  * $rsa->getLastPadding() and get RSA::PADDING_RELAXED_PKCS1 back instead of
  * RSA::PADDING_PKCS1... that means BER encoding was used.
  *
  * @access private
  * @param string $m
  * @param string $s
  * @return bool
  */
 function _rsassa_pkcs1_v1_5_relaxed_verify($m, $s)
 {
     // Length checking
     if (strlen($s) != $this->k) {
         return false;
     }
     // RSA verification
     $s = $this->_os2ip($s);
     $m2 = $this->_rsavp1($s);
     if ($m2 === false) {
         return false;
     }
     $em = $this->_i2osp($m2, $this->k);
     if ($em === false) {
         return false;
     }
     if ($this->_string_shift($em, 2) != "") {
         return false;
     }
     $em = ltrim($em, "ÿ");
     if ($this->_string_shift($em) != "") {
         return false;
     }
     $asn1 = new ASN1();
     $decoded = $asn1->decodeBER($em);
     if (!is_array($decoded) || empty($decoded[0]) || strlen($em) > $decoded[0]['length']) {
         return false;
     }
     $AlgorithmIdentifier = array('type' => ASN1::TYPE_SEQUENCE, 'children' => array('algorithm' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER), 'parameters' => array('type' => ASN1::TYPE_ANY, 'optional' => true)));
     $DigestInfo = array('type' => ASN1::TYPE_SEQUENCE, 'children' => array('digestAlgorithm' => $AlgorithmIdentifier, 'digest' => array('type' => ASN1::TYPE_OCTET_STRING)));
     $oids = array('1.2.840.113549.2.2' => 'md2', '1.2.840.113549.2.4' => 'md4', '1.2.840.113549.2.5' => 'md5', '1.3.14.3.2.26' => 'sha1', '2.16.840.1.101.3.4.2.1' => 'sha256', '2.16.840.1.101.3.4.2.2' => 'sha384', '2.16.840.1.101.3.4.2.3' => 'sha512');
     $asn1->loadOIDs($oids);
     $decoded = $asn1->asn1map($decoded[0], $DigestInfo);
     if (!isset($decoded) || $decoded === false) {
         return false;
     }
     if (!in_array($decoded['digestAlgorithm']['algorithm'], $oids)) {
         return false;
     }
     $hash = new Hash($decoded['digestAlgorithm']['algorithm']);
     $em = $hash->hash($m);
     $em2 = Base64::decode($decoded['digest']);
     return $this->_equals($em, $em2);
 }