/***************************************************************************** wmain *****************************************************************************/ DWORD __cdecl wmain( int argc, LPWSTR argv[] ) { HRESULT hr = S_OK; BOOL fSign = TRUE; LPCWSTR pwszInputFile = NULL; LPCWSTR pwszOutputFile = NULL; BYTE *pbInput = NULL; DWORD cbInput = 0; BYTE *pbOutput = NULL; DWORD cbOutput = 0; CERT_CHAIN_PARA ChainPara = {0}; CERT_CHAIN_POLICY_PARA ChainPolicy = {0}; CERT_CHAIN_POLICY_STATUS PolicyStatus = {0}; PCCERT_CHAIN_CONTEXT pChain = NULL; PCCERT_CONTEXT pSignerCert = NULL; HCERTSTORE hStoreHandle = NULL; LPCWSTR pwszStoreName = L"MY"; // by default LPCWSTR pwszCName = L"Test"; // by default LPCWSTR wszHashAlgName = L"SHA1"; int i; // // options // for( i=1; i<argc; i++ ) { if ( lstrcmpW (argv[i], L"/?") == 0 || lstrcmpW (argv[i], L"-?") == 0 ) { Usage( L"cms_sign.exe" ); goto CleanUp; } if( *argv[i] != L'-' ) break; if ( lstrcmpW (argv[i], L"-s") == 0 ) { if( i+1 >= argc ) { hr = E_INVALIDARG; goto CleanUp; } pwszStoreName = argv[++i]; } else if ( lstrcmpW (argv[i], L"-n") == 0 ) { if( i+1 >= argc ) { hr = E_INVALIDARG; goto CleanUp; } pwszCName = argv[++i]; } else if ( lstrcmpW (argv[i], L"-a") == 0 ) { if( i+1 >= argc ) { hr = E_INVALIDARG; goto CleanUp; } wszHashAlgName = argv[++i]; } } if( 0 == lstrcmpW (argv[i], L"SIGN")) { if( i+2 >= argc ) { hr = E_INVALIDARG; goto CleanUp; } fSign = TRUE; pwszInputFile = argv[++i]; pwszOutputFile = argv[++i]; } else if( 0 == lstrcmpW (argv[i], L"VERIFY")) { if( i+1 >= argc ) { hr = E_INVALIDARG; goto CleanUp; } fSign = FALSE; pwszInputFile = argv[++i]; } else { hr = E_INVALIDARG; goto CleanUp; } if( i != argc-1 ) { hr = E_INVALIDARG; goto CleanUp; } //------------------------------------------------------------------- // Open the certificate store to be searched. hStoreHandle = CertOpenStore( CERT_STORE_PROV_SYSTEM, // the store provider type 0, // the encoding type is not needed NULL, // use the default HCRYPTPROV CERT_SYSTEM_STORE_CURRENT_USER, // set the store location in a // registry location pwszStoreName ); // the store name if( NULL == hStoreHandle ) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } // // Load file // hr = HrLoadFile( pwszInputFile, &pbInput, &cbInput ); if( FAILED(hr) ) { wprintf( L"Unable to read file: %s\n", pwszInputFile ); goto CleanUp; } if( fSign ) { //------------------------------------------------------------------- // Sign Message PCCRYPT_OID_INFO pOidInfo = NULL; CRYPT_SIGN_MESSAGE_PARA SigParams = {0}; // Create the MessageArray and the MessageSizeArray. const BYTE* MessageArray[] = {pbInput}; DWORD MessageSizeArray[] = {cbInput}; // // Get a certificate that has the specified Subject Name // pSignerCert = CertFindCertificateInStore( hStoreHandle, X509_ASN_ENCODING , // Use X509_ASN_ENCODING 0, // No dwFlags needed CERT_FIND_SUBJECT_STR, // Find a certificate with a // subject that matches the // string in the next parameter pwszCName, // The Unicode string to be found // in a certificate's subject NULL); // NULL for the first call to the // function; In all subsequent // calls, it is the last pointer // returned by the function if( NULL == pSignerCert ) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } // // Build a chain in order to include certs to the message // if( !CertGetCertificateChain( NULL, // use the default chain engine pSignerCert, // pointer to the end certificate NULL, // use the default time NULL, // search no additional stores &ChainPara, // use AND logic and enhanced key usage // as indicated in the ChainPara // data structure CERT_CHAIN_REVOCATION_CHECK_END_CERT, NULL, // currently reserved &pChain )) // return a pointer to the chain created { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } // // Verify that the chain complies with Base policy // ChainPolicy.cbSize = sizeof(CERT_CHAIN_POLICY_PARA); ChainPolicy.dwFlags = 0; PolicyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS); ChainPolicy.pvExtraPolicyPara = NULL; if (!CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_BASE, pChain, &ChainPolicy, &PolicyStatus)) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } if( PolicyStatus.dwError != S_OK ) { ReportError( L"Base Policy Chain Status Failure:", PolicyStatus.dwError ); hr = PolicyStatus.dwError; } // Initialize the signature structure. SigParams.cbSize = sizeof(SigParams); SigParams.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; SigParams.pSigningCert = pSignerCert; SigParams.cAuthAttr = 0; SigParams.dwInnerContentType = 0; SigParams.cMsgCrl = 0; SigParams.cUnauthAttr = 0; SigParams.dwFlags = 0; SigParams.pvHashAuxInfo = NULL; SigParams.rgAuthAttr = NULL; // // Addd max of 8 certs to the message // PCCERT_CONTEXT rgpMsgCert[8] = {NULL}; SigParams.rgpMsgCert = rgpMsgCert; for( SigParams.cMsgCert=0; SigParams.cMsgCert<pChain->rgpChain[0]->cElement && SigParams.cMsgCert<8; SigParams.cMsgCert++ ) { rgpMsgCert[SigParams.cMsgCert] = pChain->rgpChain[0]->rgpElement[SigParams.cMsgCert]->pCertContext; } // // Find OID // pOidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_NAME_KEY, (void*)wszHashAlgName, CRYPT_HASH_ALG_OID_GROUP_ID ); if( NULL == pOidInfo ) { hr = CRYPT_E_UNKNOWN_ALGO; goto CleanUp; } SigParams.HashAlgorithm.pszObjId = (LPSTR)pOidInfo->pszOID; // First, get the size of the signed BLOB. if( !CryptSignMessage( &SigParams, FALSE, 1, MessageArray, &cbInput, NULL, &cbOutput )) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } // Allocate memory for the signed BLOB. pbOutput = (BYTE*)LocalAlloc( LPTR, cbOutput ); if( NULL == pbOutput ) { hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY ); goto CleanUp; } // Get the signed message BLOB. if( !CryptSignMessage( &SigParams, FALSE, 1, MessageArray, MessageSizeArray, pbOutput, &cbOutput )) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } hr = HrSaveFile( pwszOutputFile, pbOutput, cbOutput ); if( FAILED(hr) ) { wprintf( L"Unable to save file: %s\n", pwszOutputFile ); goto CleanUp; } wprintf( L"Successfully signed message using CryptSignMessage.\n"); } else { //------------------------------------------------------------------- // Verify signed message CRYPT_VERIFY_MESSAGE_PARA VerifyParams = {0}; VerifyParams.cbSize = sizeof(VerifyParams); VerifyParams.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; VerifyParams.hCryptProv = 0; VerifyParams.pfnGetSignerCertificate = NULL; VerifyParams.pvGetArg = NULL; // First, call CryptVerifyMessageSignature to get the length // of the buffer needed to hold the decoded message. if( !CryptVerifyMessageSignature( &VerifyParams, 0, pbInput, cbInput, NULL, &cbOutput, NULL)) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } pbOutput = (BYTE*)LocalAlloc( LPTR, cbOutput ); if( NULL == pbOutput ) { hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY ); goto CleanUp; } //--------------------------------------------------------------- // Call CryptVerifyMessageSignature again to verify the signature // and, if successful, copy the decoded message into the buffer. if( !CryptVerifyMessageSignature( &VerifyParams, 0, pbInput, cbInput, pbOutput, &cbOutput, &pSignerCert)) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } wprintf( L"Successfully verified signed message using CryptVerifyMessageSignature.\n"); // // Build a chain in order to verify certificate trust // // // Instruction : Create a certificate store from the CMS message and provide as a parameter to // CertGetCertificateChain. This will ensure that all additional certificates from // the CMS message are used in chain building // Otherwise chain will be build using the local stores only. // if( !CertGetCertificateChain( NULL, // use the default chain engine pSignerCert, // pointer to the end certificate NULL, // use the default time NULL, // search no additional stores &ChainPara, // use AND logic and enhanced key usage // as indicated in the ChainPara // data structure CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, NULL, // currently reserved &pChain )) // return a pointer to the chain created { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } // // Verify that the chain complies with Base policy // ChainPolicy.cbSize = sizeof(CERT_CHAIN_POLICY_PARA); ChainPolicy.dwFlags = 0; PolicyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS); ChainPolicy.pvExtraPolicyPara = NULL; if (!CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_BASE, pChain, &ChainPolicy, &PolicyStatus)) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } if( PolicyStatus.dwError != S_OK ) { ReportError( L"Base Policy Chain Status Failure:", PolicyStatus.dwError ); hr = PolicyStatus.dwError; } } hr = S_OK; //------------------------------------------------------------------- // Clean up memory. CleanUp: if( NULL != pbInput ) { LocalFree(pbInput); } if( NULL != pbOutput ) { LocalFree(pbOutput); } if( NULL != pChain ) { CertFreeCertificateChain(pChain); } if( NULL != pSignerCert ) { CertFreeCertificateContext(pSignerCert); } if( NULL != hStoreHandle) { CertCloseStore( hStoreHandle, 0 ); } if( FAILED( hr )) { ReportError( NULL, hr ); } return (DWORD)hr; } // End of main
int _tmain(int argc, _TCHAR* argv[]) { //-------------------------------------------------------------------- // Declare and initialize variables. HCERTSTORE hCertStore = NULL; PCCERT_CONTEXT pCertContext = NULL; TCHAR * pszStoreName = TEXT("MY"); HCRYPTKEY hKey = NULL; HCRYPTPROV hProv = NULL; DWORD dwKeySpec = 0; BOOL bCallerFreeProv = FALSE; HCRYPTHASH hHash; DWORD dwSigLen= 0; BYTE * pbSignature = NULL; //------------------------------------------------------------- // Declare and initialize variables. BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed."; DWORD dwBufferLen = strlen((char *)pbBuffer)+1; //-------------------------------------------------------------------- // Open a certificate store. if ( hCertStore = CertOpenSystemStore( NULL, pszStoreName)) { fprintf(stderr,"The store has been opened.\n"); } else { printf("Unable to open store.\n"); goto err; } //-------------------------------------------------------------------- // Display a list of the certificates in the store and // allow the user to select a certificate. if(!(pCertContext = CryptUIDlgSelectCertificateFromStore( hCertStore, // Open the store that contains the certificates to // display NULL, NULL, NULL, CRYPTUI_SELECT_LOCATION_COLUMN, 0, NULL))) { printf("Select Certificate UI failed.\n" ); goto err; } #if 1 //获取CSP句柄 if (!CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL, &hProv, &dwKeySpec, &bCallerFreeProv)) { printf("CryptAcquireCertificatePrivateKey failed.\n" ); goto err; } //获取密钥句柄 if(!CryptGetUserKey(hProv, dwKeySpec, &hKey)) { printf("CryptGetUserKey failed.\n" ); goto err; } //-------------------------------------------------------------------- // Acquire a hash object handle. if(CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash)) { printf("An empty hash object has been created. \n"); } else { printf("Error during CryptBeginHash!\n"); goto err; } //-------------------------------------------------------------------- // This code assumes that the handle of a cryptographic context // has been acquired and that a hash object has been created // and its handle (hHash) is available. if(CryptHashData( hHash, pbBuffer, dwBufferLen, 0)) { printf("The data buffer has been added to the hash.\n"); } else { printf("Error during CryptHashData.\n"); goto err; } //-------------------------------------------------------------------- // Determine the size of the signature and allocate memory. dwSigLen= 0; if(CryptSignHash( hHash, dwKeySpec, NULL, 0, NULL, &dwSigLen)) { printf("Signature length %d found.\n",dwSigLen); } else { printf("Error during CryptSignHash\n"); goto err; } //-------------------------------------------------------------------- // Allocate memory for the signature buffer. if(pbSignature = (BYTE *)malloc(dwSigLen)) { printf("Memory allocated for the signature.\n"); } else { printf("Out of memory\n"); goto err; } //-------------------------------------------------------------------- // Sign the hash object. if(CryptSignHash( hHash, dwKeySpec, NULL, 0, pbSignature, &dwSigLen)) { printf("pbSignature is the hash signature.\n"); } else { printf("Error during CryptSignHash.\n"); goto err; } { DWORD dwBlobLen = 0; BYTE * pbKeyBlob = 0; HCRYPTKEY hPubKey = 0; if(CryptExportKey( hKey, NULL, PUBLICKEYBLOB, //导出公钥 0, NULL, &dwBlobLen)) //返回密钥数据长度 { printf("Size of the BLOB for the public key determined. \n"); } else { printf("Error computing BLOB length.\n"); goto err; } if(pbKeyBlob = (BYTE*)malloc(dwBlobLen)) { printf("Memory has been allocated for the BLOB. \n"); } else { printf("Out of memory. \n"); goto err; } if(CryptExportKey( hKey, NULL, PUBLICKEYBLOB, 0, pbKeyBlob, //返回密钥数据 &dwBlobLen)) //导出的密钥数据的长度 { printf("Contents have been written to the BLOB. \n"); } else { printf("Error exporting key.\n"); goto err; } if(CryptImportKey(hProv,pbKeyBlob, dwBlobLen, NULL, 0, &hPubKey)) { printf("CryptImportKey OK. \n"); } else { printf("Error CryptImportKey.\n"); goto err; } if(CryptVerifySignature(hHash, pbSignature, dwSigLen,hPubKey,NULL,0)) { printf("verify OK.\n"); } else { printf("Error during CryptVerifySignature.\n"); goto err; } } if(CryptVerifySignature(hHash, pbSignature, dwSigLen,hKey,NULL,0)) { printf("verify OK.\n"); } else { printf("Error during CryptVerifySignature.\n"); goto err; } #endif BYTE* pbMessage = (BYTE*)"CryptoAPI is a good way to handle security"; DWORD cbMessage = strlen((char*) pbMessage)+1; //证书的上下文 CRYPT_SIGN_MESSAGE_PARA SigParams; DWORD cbSignedMessageBlob; BYTE *pbSignedMessageBlob; DWORD cbDecodedMessageBlob; BYTE *pbDecodedMessageBlob; CRYPT_VERIFY_MESSAGE_PARA VerifyParams; const BYTE* MessageArray[] = {pbMessage}; DWORD MessageSizeArray[1]; MessageSizeArray[0] = cbMessage; printf("Begin processing. \n"); printf(" The message to be signed is\n-> %s.\n",pbMessage); //-------------------------------------------------------------------- //初始化签名结构 SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA); SigParams.dwMsgEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING); SigParams.pSigningCert = pCertContext; SigParams.HashAlgorithm.pszObjId = szOID_RSA_MD5; SigParams.HashAlgorithm.Parameters.cbData = NULL; SigParams.cMsgCert = 1; SigParams.rgpMsgCert = &pCertContext; SigParams.cAuthAttr = 0; SigParams.dwInnerContentType = 0; SigParams.cMsgCrl = 0; SigParams.cUnauthAttr = 0; SigParams.dwFlags = 0; SigParams.pvHashAuxInfo = NULL; SigParams.rgAuthAttr = NULL; //首先得到BLOB的大小 if(CryptSignMessage( &SigParams, // Signature parameters FALSE, // Not detached 1, // Number of messages MessageArray, // Messages to be signed MessageSizeArray, // Size of messages NULL, // Buffer for signed message &cbSignedMessageBlob)) // Size of buffer { printf("The size of the BLOB is %d.\n",cbSignedMessageBlob); } else { printf("Getting signed BLOB size failed"); } //-------------------------------------------------------------------- //分配BLOB的内存. if(!(pbSignedMessageBlob = (BYTE*)malloc(cbSignedMessageBlob))) { printf("Memory allocation error while signing."); } if(CryptSignMessage( &SigParams, // FALSE, // 1, //消息数量 MessageArray, //待签名的消息 MessageSizeArray, //消息大小 pbSignedMessageBlob, //缓冲区 &cbSignedMessageBlob)) //缓冲区大小 { printf("The message was signed successfully. \n"); } else { printf("Error getting signed BLOB"); } //-------------------------------------------------------------------- //验证签名信息 //-------------------------------------------------------------------- //初始化VerifyParams结构. VerifyParams.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA); VerifyParams.dwMsgAndCertEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING); VerifyParams.hCryptProv = 0; VerifyParams.pfnGetSignerCertificate = NULL; VerifyParams.pvGetArg = NULL; if(CryptVerifyMessageSignature( &VerifyParams, //. 0, // pbSignedMessageBlob, //. cbSignedMessageBlob, // NULL, // &cbDecodedMessageBlob, // NULL)) // Pointer to signer certificate. { printf("%d bytes need for the buffer.\n",cbDecodedMessageBlob); } else { printf("Verification message failed. \n"); } //为缓冲区分配内存. if(!(pbDecodedMessageBlob = (BYTE*)malloc(cbDecodedMessageBlob))) { printf("Memory allocation error allocating decode BLOB."); } //得到缓冲区的大小 if(CryptVerifyMessageSignature( &VerifyParams, // Verify parameters. 0, // Signer index. pbSignedMessageBlob, // Pointer to signed BLOB. cbSignedMessageBlob, // Size of signed BLOB. pbDecodedMessageBlob, // Buffer for decoded message. &cbDecodedMessageBlob, // Size of buffer. NULL)) // Pointer to signer certificate. { printf("The verified message is \n-> %s \n",pbDecodedMessageBlob); } else { printf("Verification message failed. \n"); } err: WTF_PrintErrorMsg(); if(pbSignedMessageBlob) { free(pbSignedMessageBlob); } if(pbDecodedMessageBlob) { free(pbDecodedMessageBlob); } if (pbSignature) { free(pbSignature); } if(hHash) { CryptDestroyHash(hHash); } if (hKey) { CryptDestroyKey(hKey); } if (hProv) { CryptReleaseContext(hProv, 0); } if (pCertContext) { CertFreeCertificateContext(pCertContext); } if (hCertStore) { CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); } return 0; }