openssl_verify的用法是什么?
我想知道他的三个参数分别传递什么值!openssl_verify

解决方案 »

  1.   

    $pub_key_id 毫无悬疑是公钥!其他两个参数$data 和 $signature分别表示什么意思?
      

  2.   

    $signature公钥加密生成的数据,$data原始数据$fp = fopen("pem公钥", "r");
    $cert = fread($fp, 8192);
    fclose($fp);
    $pub_key_id = openssl_get_publickey($cert);
      

  3.   

    Quote: 引用 2 楼 sjqzone 的回复:

    $signature公钥加密生成的数据,$data原始数据 你是说$signature 是$pub_key_id 加密生成的?如何加密?
      

  4.   

    已经解决了!
    在网上找了个类,可以。
    <?php
    /**
     * Is one pem encoded certificate the signer of another?
     *
     * The PHP openssl functionality is severely limited by the lack of a stable
     * api and documentation that might as well have been encrypted itself.
     * In particular the documention on openssl_verify() never explains where
     * to get the actual signature to verify.  The isCertSigner() function below
     * will accept two PEM encoded certs as arguments and will return true if
     * one certificate was used to sign the other.  It only relies on the
     * openssl_pkey_get_public() and openssl_public_decrypt() openssl functions,
     * which should stay fairly stable.  The ASN parsing code snippets were mostly
     * borrowed from the horde project's smime.php.
     *
     * @author Mike Green <mikey at badpenguins dot com>
     * @copyright Copyright (c) 2010, Mike Green
     * @license http://opensource.org/licenses/gpl-2.0.php GPLv2
     *//**
     * If viewSource is in the request string, show the source, luke.
     
    if (isset($_REQUEST['viewSource'])) {
        die(highlight_file(__FILE__));
        }
    */
    class OpensslVerifyAPI {
    /**
     * Extract signature from der encoded cert.
     * Expects x509 der encoded certificate consisting of a section container
     * containing 2 sections and a bitstream.  The bitstream contains the
     * original encrypted signature, encrypted by the public key of the issuing
     * signer.
     * @param string $der
     * @return string on success
     * @return bool false on failures
     */
    function extractSignature($der=false) {
        if (strlen($der) < 5) { return false; }
        // skip container sequence
        $der = substr($der,4);
        // now burn through two sequences and the return the final bitstream
        while(strlen($der) > 1) {
            $class = ord($der[0]);
            $classHex = dechex($class);
            switch($class) {
                // BITSTREAM
                case 0x03:
                    $len = ord($der[1]);
                    $bytes = 0;
                    if ($len & 0x80) {
                        $bytes = $len & 0x0f;
                        $len = 0;
                        for ($i = 0; $i < $bytes; $i++) {
                            $len = ($len << 8) | ord($der[$i + 2]);
                            }
                        }
                    return substr($der,3 + $bytes, $len);
                break;
                // SEQUENCE
                case 0x30:
                    $len = ord($der[1]);
                    $bytes = 0;
                    if ($len & 0x80) {
                        $bytes = $len & 0x0f;
                        $len = 0;
                        for($i = 0; $i < $bytes; $i++) {
                            $len = ($len << 8) | ord($der[$i + 2]);
                            }
                        }
                    $contents = substr($der, 2 + $bytes, $len);
                    $der = substr($der,2 + $bytes + $len);
                break;
                default:
                    return false;
                break;
                }
            }
        return false;
        }/**
     * Get signature algorithm oid from der encoded signature data.
     * Expects decrypted signature data from a certificate in der format.
     * This ASN1 data should contain the following structure:
     * SEQUENCE
     *    SEQUENCE
     *       OID    (signature algorithm)
     *       NULL
     * OCTET STRING (signature hash)
     * @return bool false on failures
     * @return string oid
     */
    function getSignatureAlgorithmOid($der=null) {
        // Validate this is the der we need...
        if (!is_string($der) or strlen($der) < 5) { return false; }
        $bit_seq1 = 0;
        $bit_seq2 = 2;
        $bit_oid  = 4;
        if (ord($der[$bit_seq1]) !== 0x30) {
            die('Invalid DER passed to getSignatureAlgorithmOid()');
            }
        if (ord($der[$bit_seq2]) !== 0x30) {
            die('Invalid DER passed to getSignatureAlgorithmOid()');
            }
        if (ord($der[$bit_oid]) !== 0x06) {
            die('Invalid DER passed to getSignatureAlgorithmOid');
            }
        // strip out what we don't need and get the oid
        $der = substr($der,$bit_oid);
        // Get the oid
        $len = ord($der[1]);
        $bytes = 0;
        if ($len & 0x80) {
            $bytes = $len & 0x0f;
            $len = 0;
            for ($i = 0; $i < $bytes; $i++) {
                $len = ($len << 8) | ord($der[$i + 2]);
                }
            }
        $oid_data = substr($der, 2 + $bytes, $len);
        // Unpack the OID
        $oid  = floor(ord($oid_data[0]) / 40);
        $oid .= '.' . ord($oid_data[0]) % 40;
        $value = 0;
        $i = 1;
        while ($i < strlen($oid_data)) {
            $value = $value << 7;
            $value = $value | (ord($oid_data[$i]) & 0x7f);
            if (!(ord($oid_data[$i]) & 0x80)) {
                $oid .= '.' . $value;
                $value = 0;
                }
            $i++;
            }
        return $oid;
        }/**
     * Get signature hash from der encoded signature data.
     * Expects decrypted signature data from a certificate in der format.
     * This ASN1 data should contain the following structure:
     * SEQUENCE
     *    SEQUENCE
     *       OID    (signature algorithm)
     *       NULL
     * OCTET STRING (signature hash)
     * @return bool false on failures
     * @return string hash
     */
    function getSignatureHash($der=null) {
        // Validate this is the der we need...
        if (!is_string($der) or strlen($der) < 5) { return false; }
        if (ord($der[0]) !== 0x30) {
            die('Invalid DER passed to getSignatureHash()');
            }
        // strip out the container sequence
        $der = substr($der,2);
        if (ord($der[0]) !== 0x30) {
            die('Invalid DER passed to getSignatureHash()');
            }
        // Get the length of the first sequence so we can strip it out.
        $len = ord($der[1]);
        $bytes = 0;
        if ($len & 0x80) {
            $bytes = $len & 0x0f;
            $len = 0;
            for ($i = 0; $i < $bytes; $i++) {
                $len = ($len << 8) | ord($der[$i + 2]);
                }
            }
        $der = substr($der, 2 + $bytes + $len);
        // Now we should have an octet string
        if (ord($der[0]) !== 0x04) {
            die('Invalid DER passed to getSignatureHash()');
            }
        $len = ord($der[1]);
        $bytes = 0;
        if ($len & 0x80) {
            $bytes = $len & 0x0f;
            $len = 0;
            for ($i = 0; $i < $bytes; $i++) {
                $len = ($len << 8) | ord($der[$i + 2]);
                }
            }
        return bin2hex(substr($der, 2 + $bytes, $len));
        }
      

  5.   

    /**
     * Determine if one cert was used to sign another
     * Note that more than one CA cert can give a positive result, some certs
     * re-issue signing certs after having only changed the expiration dates.
     * @param string $cert - PEM encoded cert
     * @param string $caCert - PEM encoded cert that possibly signed $cert
     * @return bool
     */
    function isCertSigner($certPem=null,$caCertPem=null) {
        if (!function_exists('openssl_pkey_get_public')) {
            die('Need the openssl_pkey_get_public() function.');
            }
        if (!function_exists('openssl_public_decrypt')) {
            die('Need the openssl_public_decrypt() function.');
            }
        if (!function_exists('hash')) {
            die('Need the php hash() function.');
            }
        if (empty($certPem) or empty($caCertPem)) { return false; }
        // Convert the cert to der for feeding to extractSignature.
        $certDer = $this->pemToDer($certPem);
        if (!is_string($certDer)) { die('invalid certPem'); }
        // Grab the encrypted signature from the der encoded cert.
        $encryptedSig = $this->extractSignature($certDer);
        if (!is_string($encryptedSig)) {
            die('Failed to extract encrypted signature from certPem.');
            }
        // Extract the public key from the ca cert, which is what has
        // been used to encrypt the signature in the cert.
        $pubKey = openssl_pkey_get_public($caCertPem);
        if ($pubKey === false) {
            die('Failed to extract the public key from the ca cert.');
            }
        // Attempt to decrypt the encrypted signature using the CA's public
        // key, returning the decrypted signature in $decryptedSig.  If
        // it can't be decrypted, this ca was not used to sign it for sure...
        $rc = openssl_public_decrypt($encryptedSig,$decryptedSig,$pubKey);
        if ($rc === false) { return false; }
        // We now have the decrypted signature, which is der encoded
        // asn1 data containing the signature algorithm and signature hash.
        // Now we need what was originally hashed by the issuer, which is
        // the original DER encoded certificate without the issuer and
        // signature information.
        $origCert = $this->stripSignerAsn($certDer);
        if ($origCert === false) {
            die('Failed to extract unsigned cert.');
            }
        // Get the oid of the signature hash algorithm, which is required
        // to generate our own hash of the original cert.  This hash is
        // what will be compared to the issuers hash.
        $oid = $this->getSignatureAlgorithmOid($decryptedSig);
        if ($oid === false) {
            die('Failed to determine the signature algorithm.');
            }
        switch($oid) {
            case '1.2.840.113549.2.2':     $algo = 'md2';    break;
            case '1.2.840.113549.2.4':     $algo = 'md4';    break;
            case '1.2.840.113549.2.5':     $algo = 'md5';    break;
            case '1.3.14.3.2.18':          $algo = 'sha';    break;
            case '1.3.14.3.2.26':          $algo = 'sha1';   break;
            case '2.16.840.1.101.3.4.2.1': $algo = 'sha256'; break;
            case '2.16.840.1.101.3.4.2.2': $algo = 'sha384'; break;
            case '2.16.840.1.101.3.4.2.3': $algo = 'sha512'; break;
            default:
                die('Unknown signature hash algorithm oid: ' . $oid);
            break;
            }
        // Get the issuer generated hash from the decrypted signature.
        $decryptedHash = $this->getSignatureHash($decryptedSig);
        // Ok, hash the original unsigned cert with the same algorithm
        // and if it matches $decryptedHash we have a winner.
        $certHash = hash($algo,$origCert);
        return ($decryptedHash === $certHash);
        }/**
     * Convert pem encoded certificate to DER encoding
     * @return string $derEncoded on success
     * @return bool false on failures
     */
    function pemToDer($pem=null) {
        if (!is_string($pem)) { return false; }
        $cert_split = preg_split('/(-----((BEGIN)|(END)) CERTIFICATE-----)/',$pem);
        if (!isset($cert_split[1])) { return false; }
        return base64_decode($cert_split[1]);
        }/**
     * Obtain der cert with issuer and signature sections stripped.
     * @param string $der - der encoded certificate
     * @return string $der on success
     * @return bool false on failures.
     */
    function stripSignerAsn($der=null) {
        if (!is_string($der) or strlen($der) < 8) { return false; }
        $bit = 4;
        $len   = ord($der[($bit + 1)]);
        $bytes = 0;
        if ($len & 0x80) {
            $bytes = $len & 0x0f;
            $len   = 0;
            for($i = 0; $i < $bytes; $i++) {
                $len = ($len << 8) | ord($der[$bit + $i + 2]);
                }
            }
        return substr($der,4,$len + 4);
        }
    }
    /**
     * HTML form starts here...
     */ $this->answer = 'Enter PEM Encoded Certificates for the Issuer and Subject '
            . 'and click Submit.  Include the entire certificates, including '
            . 'the BEGIN CERTIFICATE and END CERTIFICATE lines.';
    /*
    if (isset($_POST['subjectPem']) and isset($_POST['issuerPem'])) {
        if (strlen($_POST['subjectPem']) > 0 and strlen($_POST['issuerPem']) > 0) {
            $rc = isCertSigner($_POST['subjectPem'],$_POST['issuerPem']);
            if ($rc === true) {
                $answer = 'The issuer cert DID sign the subject cert.';
                } else {
                $answer = 'The issuer cert DID NOT sign the subject cert.';
                }
            }
        }
    */?>