Openssl php signed string not verified by Win CryptoAPI

I sign some text using php openssl and try to test it in a Windows application using CryptoApi, but the check always fails. Please help me.

PHP code:

<?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 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 ++ Code:

 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  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; MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANDiE2 + Xi / WnO + s120NiiJhNyIButVu6zxqlVzz0wy2j4kQVUC4ZRZD80IY + 4wIiX2YxKBZKGnd2TtPkcJ / ljkUCAwEAAQ == ----- END PUBLIC KEY -----"; 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  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; 
0
c ++ windows php openssl rsa
source share
1 answer

To verify the use of CryptoAPI, cancel the signature and then verify. This is due to the fact that on Windows the byte order is different from OpenSSL (this is the big end).

You can do it as follows

 for(i=0, j=dwSigLen-1; i<j; ++i, --j) { char t = pbSignature[i]; pbSignature[i] = pbSignature[j]; pbSignature[j] = t; } 

After that check the signature.

This question may help you, as it faces a similar problem (signed from CryptoAPI and verifies the use of OpenSSL).

+1
source share

All Articles