openssl_verify - php openssl_sign p12
php openssl cadena firmada no verificada por Win CryptoAPI (1)
Para verificar el uso de CryptoAPI, invierta la firma y luego verifique. Esto se debe a que, en Windows, el orden de bytes es diferente de OpenSSL (que es Big Endian).
Puedes hacerlo de la siguiente manera
for(i=0, j=dwSigLen-1; i<j; ++i, --j) {
char t = pbSignature[i];
pbSignature[i] = pbSignature[j];
pbSignature[j] = t;
}
Después de eso, verifica la firma.
Esta pregunta puede ayudarlo ya que enfrenta un problema similar (firmado desde CryptoAPI y verifica con OpenSSL).
Estoy firmando texto usando php openssl e intentando verificarlo en la aplicación de Windows usando CryptoApi pero la validación siempre falla. Por favor, ayúdame.
Código PHP:
<?php
$data = "data that is to be hashed and signed.";
$private_key = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6zxqlVzz0wy2j4kQVUC4Z
RZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQJAL151ZeMKHEU2c1qdRKS9
sTxCcc2pVwoAGVzRccNX16tfmCf8FjxuM3WmLdsPxYoHrwb1LFNxiNk1MXrxjH3R
6QIhAPB7edmcjH4bhMaJBztcbNE1VRCEi/bisAwiPPMq9/2nAiEA3lyc5+f6DEIJ
h1y6BWkdVULDSM+jpi1XiV/DevxuijMCIQCAEPGqHsF+4v7Jj+3HAgh9PU6otj2n
Y79nJtCYmvhoHwIgNDePaS4inApN7omp7WdXyhPZhBmulnGDYvEoGJN66d0CIHra
I2SvDkQ5CmrzkW5qPaE2oO7BSqAhRZxiYpZFb5CI
-----END RSA PRIVATE KEY-----
EOD;
$public_key = <<<EOD
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6
zxqlVzz0wy2j4kQVUC4ZRZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQ==
-----END PUBLIC KEY-----
EOD;
$binary_signature = "";
// At least with PHP 5.2.2 / OpenSSL 0.9.8b (Fedora 7)
// there seems to be no need to call openssl_get_privatekey or similar.
// Just pass the key as defined above
openssl_sign($data, $binary_signature, $private_key, OPENSSL_ALGO_SHA1);
// Check signature
$ok = openssl_verify($data, $binary_signature, $public_key, OPENSSL_ALGO_SHA1);
echo $binary_signature;
echo "/n";
echo strlen($binary_signature);
echo "/n";
echo strlen($public_key);
$binary_signature="ÅâŸoÀÞü¸IOT6ê¿›¹ý“´Šæ¸Ûà$,&†-X÷bË`‡0¥u«CAÚNgϼ‡Êû`Sî";
echo "check #1: ";
echo sha1($data);
if ($ok == 1) {
echo "signature ok (as it should be)/n";
} elseif ($ok == 0) {
echo "bad (there''s something wrong)/n";
} else {
echo "ugly, error checking signature/n";
}
$ok = openssl_verify(''tampered''.$data, $binary_signature, $public_key, OPENSSL_ALGO_SHA1);
echo "check #2: ";
if ($ok == 1) {
echo "ERROR: Data has been tampered, but signature is still valid! Argh!/n";
} elseif ($ok == 0) {
echo "bad signature (as it should be, since data has beent tampered)/n";
} else {
echo "ugly, error checking signature/n";
}
?>
Código C ++:
HCRYPTPROV hProv;
BYTE *pbBuffer= (BYTE *)"data that is to be hashed and signed.";
DWORD dwBufferLen = strlen((char *)pbBuffer)+1;
HCRYPTHASH hHash;
HCRYPTKEY hPubKey;
BYTE *pbKeyBlob;
// signature from php script
BYTE *pbSignature = (BYTE*)"BõŸûëN2¸GõÂÌ_;3µÜåJˆLôMÐh’*¡mø&·À„<ááø‡–e…ÎJ‡B¥tyƒ¥Óþ''N]Ù";
//-------------------------------------------------------------------
char pemPubKey[2048] = "-----BEGIN PUBLIC KEY-----MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6zxqlVzz0wy2j4kQVUC4ZRZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQ==-----END PUBLIC KEY-----";
//int readLen;
unsigned char derPubKey[2048];
DWORD derPubKeyLen = 2048;
CERT_PUBLIC_KEY_INFO *publicKeyInfo;
DWORD publicKeyInfoLen;
//HANDLE hFile;
if ( !CryptStringToBinaryA( pemPubKey, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen, NULL, NULL ) )
{
fprintf( stderr, "CryptStringToBinary failed. Err: %d/n", GetLastError() );
}
/*
* Decode from DER format to CERT_PUBLIC_KEY_INFO
*/
if ( !CryptDecodeObjectEx( X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, derPubKey, derPubKeyLen,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen ) )
{
fprintf( stderr, "CryptDecodeObjectEx 1 failed. Err: %p/n", GetLastError() );
return -1;
}
// Acquire a cryptographic provider context handle.
if(CryptAcquireContext(
&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
printf("CSP context acquired./n");
}
else
{
MyHandleError("Error during CryptAcquireContext.");
}
if ( CryptImportPublicKeyInfo( hProv, MY_ENCODING_TYPE, publicKeyInfo, &hPubKey ) )
{
printf("The key has been imported./n");
}
else
{
MyHandleError("Public key import failed.");
}
if(publicKeyInfo)
LocalFree( publicKeyInfo );
//-------------------------------------------------------------------
// Create a new hash object.
if(CryptCreateHash(
hProv,
CALG_SHA1,
0,
0,
&hHash))
{
printf("The hash object has been recreated. /n");
}
else
{
MyHandleError("Error during CryptCreateHash.");
}
//-------------------------------------------------------------------
// Compute the cryptographic hash of the buffer.
if(CryptHashData(
hHash,
pbBuffer,
dwBufferLen,
0))
{
printf("The new hash has been created./n");
}
else
{
MyHandleError("Error during CryptHashData.");
}
//-------------------------------------------------------------------
// Validate the digital signature.
if(CryptVerifySignature(
hHash,
pbSignature,
dwSigLen,
hPubKey,
NULL,
0))
{
printf("The signature has been verified./n");
}
else
{
printf("Signature not validated!/n");
}
//-------------------------------------------------------------------
// Free memory to be used to store signature.
/*if(pbSignature)
free(pbSignature);*/
//-------------------------------------------------------------------
// Destroy the hash object.
if(hHash)
CryptDestroyHash(hHash);
//-------------------------------------------------------------------
// Release the provider handle.
if(hProv)
CryptReleaseContext(hProv, 0);
system("PAUSE");
return 0;