#define MY_TYPE X509_ASN_ENCODING #define _WIN32_WINNT 0x0500 #define TestCertificate "d://onets-1a9b69ade.onets.com_hope10.crt" #include <stdio.h> #include <windows.h> #include "velidatacertificate.h" #include "SHA1.cpp" void HandleError(char *s); int VerifyCertificateSig(); void main(void) { VerifyCertificateSig(); } // End of main /* 函数说明: 1. 验证证书的签名,CertVerifyCertificateSignature()的第一个参数为NULL,可以验证成功Microsoft csp的证书; CertVerifyCertificateSignature()第一个参数为onetscsp时,可以验证成功Onets的证书; 这种情况说明Onets加密卡RSA算法和Microsoft RSA算法不兼容。 2. 调用加密卡公钥加解密函数对非由加密卡密钥产生的证书的签名进行公钥加密 3. 提取证书的公钥信息(解码前和解码后)。该部分要置于函数末尾,因为函数调用后,公钥指针会被释放 */ int VerifyCertificateSig() { HINSTANCE hHandle = NULL; HCRYPTPROV hProv = NULL; //用于CertVerifyCertificateSignature()的第一个参数,指定csp FILE *fp = NULL; BYTE* Fca = NULL; BYTE* Fca1 = NULL; int readsize; PCERT_SIGNED_CONTENT_INFO pcertsignedctx; PCERT_PUBLIC_KEY_INFO ppublickeyinfo; PCCERT_CONTEXT pCertContext; DWORD cbDecoded; BYTE *pbDecoded; int er = -1; BYTE* mcipherText = NULL; RSAPUBLICKEY_BLOB *rsapubblob = NULL; //加密卡函数指针定义 typedef int (*RSA_E)(unsigned char* Pubkey, int PubKeyLength, unsigned char* data, int dataLength, unsigned char* cipherText, int* er ); RSA_E rsa_e; hHandle = LoadLibrary("pises_api.dll"); if(hHandle == NULL) { printf("loadlibrary failed /n"); return 0; } rsa_e = (RSA_E)GetProcAddress(hHandle, "RSA_Encrypt" ); if(rsa_e==NULL) { MessageBox(NULL,"获取解密函数地址失败!/n","Notice!",MB_OK | MB_ICONWARNING); return FALSE; } //打开证书文件 fp = fopen(TestCertificate, "rb"); if(fp == NULL) { printf("file open failed. /n"); return 0; } Fca = (BYTE*)malloc(2048); Fca1 = (BYTE*)malloc(2048); mcipherText = (BYTE*)malloc(2048); memset(Fca, 0, 2048); memset(Fca1, 0, 2048); readsize = fread(Fca, 1, 2048, fp); fclose(fp); //创建证书上下文,以提取证书中包含的公钥 if (NULL == (pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, (const unsigned char *)Fca, readsize))) { printf( "Can not resolve. "); exit(1); } else { printf("/n********************************/n"); printf("CertCreateCertificateContext successful !/n "); } //从以上创建的证书上下文中获得公钥的指针 ppublickeyinfo = &(pCertContext->pCertInfo->SubjectPublicKeyInfo); if (NULL == (fp = fopen( TestCertificate, "rb "))) { printf( "File can not be opened. "); exit(1); } readsize = fread(Fca1,1,2048,fp); //解码证书文件 printf("********************************/n"); printf("开始解码证书文件……/n"); if(CryptDecodeObject(X509_ASN_ENCODING, X509_CERT, (const unsigned char*)Fca1, readsize, CRYPT_DECODE_NOCOPY_FLAG, NULL, &cbDecoded)) { printf( "The needed buffer length is %d/n ",cbDecoded); } else { HandleError( "The first decode pass failed. "); } //-------------------------------------------------------------- // Allocate memory for the decoded information if(!(pbDecoded = (BYTE*)malloc(cbDecoded))) { HandleError( "Decode buffer memory allocation failed. "); } //-------------------------------------------------------------------- // Decode the encoded buffer. if(CryptDecodeObject(MY_TYPE,X509_CERT,(const unsigned char *)Fca1, readsize, CRYPT_DECODE_NOCOPY_FLAG, pbDecoded, &cbDecoded)) { // 解码成功 fp = fopen("d://证书中提取的签名.dat", "wb"); //从解码(ASN.1 BER)的证书指针中提取证书的签名和被签名的原始数据 pcertsignedctx = (CERT_SIGNED_CONTENT_INFO*)pbDecoded; printf(" the length is: %d/n", pcertsignedctx->Signature.cbData); // CRYPT_BIT_BLOB fwrite(pcertsignedctx->Signature.pbData, 1, pcertsignedctx->Signature.cbData, fp); //证书的签名 在CRYPT_BIT_BLOB 结构中 fclose(fp); fp = fopen("d://证书中提取的被签名数据.dat", "wb"); fwrite(pcertsignedctx->ToBeSigned.pbData, 1, pcertsignedctx->ToBeSigned.cbData, fp); //证书签名和hash前的原始数据,在CRYPT_DER_BLOB fclose(fp); fp = fopen("d://证书中提取的公钥.dat", "wb"); fwrite(ppublickeyinfo->PublicKey.pbData, 1, ppublickeyinfo->PublicKey.cbData, fp); fclose(fp); } else { printf("Decoding Certificate failed !/n"); } printf("%s/n",pcertsignedctx->SignatureAlgorithm.pszObjId); printf("/n********************************/n"); printf("开始验证证书签名……/n"); // **********验证用户证书的签名是否有效*********** 利用的是CA证书的公钥值(未经ASN.1解码) // 获取Onets CSP句柄, 由hProv保存 CryptAcquireContext( &hProv, "hope10", "Onets Cryptographic Provider v1.0", 1, 0 ); // if(CryptVerifyCertificateSignature(NULL, X509_ASN_ENCODING, Fca1, readsize, ppublickeyinfo)) //Microsoft CSP: Microsoft Strong Cryptographic Provider (default) if(CryptVerifyCertificateSignature(hProv, X509_ASN_ENCODING, Fca1, readsize, ppublickeyinfo)) //Onets CSP: Onets Cryptographic Provider v1.0 { // 签名验证通过 printf( "Valid Signature/n "); } else { // 签名验证失败 HandleError( "Verification failure. "); } printf("/n********************************/n"); printf("开始调用加密卡函数加密……/n"); //调用加密卡函数完成签名数据的解密,以便比较Hash值 if(rsa_e(ppublickeyinfo->PublicKey.pbData, 2048, pcertsignedctx->Signature.pbData, pcertsignedctx->Signature.cbData, mcipherText, &er)) { printf("rsa failed error code : %d /n", er); return FALSE; } else { fp = fopen("d://证书签名解密数据.dat", "wb"); fwrite(mcipherText, 1, 256, fp); fclose(fp); unsigned char* m_outdata=(unsigned char*)malloc(30*sizeof(char)); if(m_outdata==NULL) { SetLastError(NTE_NO_MEMORY); return FALSE; } memset(m_outdata,0,30); CSHA1 sha1; sha1.Update((UINT_8*)(pcertsignedctx->ToBeSigned.pbData), pcertsignedctx->ToBeSigned.cbData); //对缓冲区内容进行hash sha1.Final(); sha1.GetHash((UINT_8*)m_outdata); if(fp = fopen("d://Hash证书原始数据.dat", "wb")) { fwrite(m_outdata, 1, 30, fp); fclose(fp); } else { printf("file open error !/n"); } } printf("/n********************************/n"); printf("开始解码证书的公钥……/n"); //解码公钥 if(CryptDecodeObject(MY_TYPE, RSA_CSP_PUBLICKEYBLOB, ppublickeyinfo->PublicKey.pbData, ppublickeyinfo->PublicKey.cbData, CRYPT_DECODE_NOCOPY_FLAG, pbDecoded, &cbDecoded)) { //解码后的公钥信息 printf("public key decoded successfully ! /n"); rsapubblob = (RSAPUBLICKEY_BLOB*)pbDecoded; printf("The pubkey bitlen is: %d /n", rsapubblob->rsaPubKey.bitlen); printf("The pubkey pubexp is: %d /n", rsapubblob->rsaPubKey.pubexp); printf("The pubkey magic is: %d /n", rsapubblob->rsaPubKey.magic); } else { printf("public key decoded failed ! /n"); } printf("/n********************************/n"); printf("结束/n"); return 1; } void HandleError(char *s) { fprintf(stderr, "An error occurred in running the program. /n "); fprintf(stderr, "%s/n ",s); fprintf(stderr, "Error number %X /n ", GetLastError()); fprintf(stderr, "Program terminating. /n "); exit(1); } // End of HandleError