Home  >  Article  >  Backend Development  >  openssl_verify的用法!?

openssl_verify的用法!?

WBOY
WBOYOriginal
2016-06-23 14:27:153850browse

openssl_verify

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

回复讨论(解决方案)

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

$signature公钥加密生成的数据,$data原始数据

$fp = fopen("pem公钥", "r");
$cert = fread($fp, 8192);
fclose($fp);
$pub_key_id = openssl_get_publickey($cert);


$signature公钥加密生成的数据,$data原始数据

 你是说$signature 是$pub_key_id 加密生成的?如何加密?

这个一般可以不管。

已经解决了!
在网上找了个类,可以。
/**
 * 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 
 * @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)      // 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                          $len = ($len                          }
                    }
                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                          $len = ($len                          }
                    }
                $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)      $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              $len = ($len              }
        }
    $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          $value = $value          $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)      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              $len = ($len              }
        }
    $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              $len = ($len              }
        }
    return bin2hex(substr($der, 2 + $bytes, $len));
    }

/**
 * 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)      $bit = 4;
    $len   = ord($der[($bit + 1)]);
    $bytes = 0;
    if ($len & 0x80) {
        $bytes = $len & 0x0f;
        $len   = 0;
        for($i = 0; $i              $len = ($len              }
        }
    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.';
            }
        }
    }
*/

?>

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn