Openssl_verify
What is the usage of openssl_verify?
I want to know what value his three parameters pass separately!
Reply to discussion (solution)
$pub _key_id No suspense is the public key! Two other parameters what do $data and $signature mean?
$signature the public key to encrypt the generated data, $data the original data
$fp = fopen ("Pem public Key", "R");
$cert = Fread ($fp, 8192);
Fclose ($FP);
$pub _key_id = Openssl_get_publickey ($cert);
$signature the public key to encrypt the generated data, $data the original data
Are you saying that $signature was generated by $pub_key_id encryption? How to encrypt?
This can be a general matter.
It's settled!
Find a class on the Internet, can.
/**
* 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 has been encrypted itself.
* In particular the documention on openssl_verify () never explains where
* To get the actual signature to verify. The Iscertsigner () function below
* Would accept both PEM encoded certs as arguments and would return true if
* One certificate is 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), 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-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 has 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));
}
/**
* Determine if one cert is used to sign another
* Note that the more than one CA cert can give a positive result, some certs
* Re-issue signing Certs after have 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-extract encrypted signature from Certpem. ');
}
Extract the public key from the CA cert, which are what have
been used to encrypt the signature in the cert.
$pubKey = Openssl_pkey_get_public ($caCertPem);
if ($pubKey = = = False) {
Die (' Failed-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, the This CA is not used to sign it for sure ...
$RC = Openssl_public_decrypt ($encryptedSig, $decryptedSig, $pubKey);
if ($RC = = = False) {return false;}
We are now having the decrypted signature, which is DER Encoded
ASN1 data containing the signature algorithm and signature hash.
Now we need-originally hashed by the issuer, which are
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 would be is 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. ';
}
}
}
*/
?>