/** * Verifies if a signature + public key matches a hash context. * * @param hash The hash context that the signature should match. * @param pubKey The public key to use on the signature. * @param signature The signature to check. * @param signatureLen The length of the signature. * @return CryptoX_Success on success, CryptoX_Error on error. */ CryptoX_Result CyprtoAPI_VerifySignature(HCRYPTHASH *hash, HCRYPTKEY *pubKey, const BYTE *signature, DWORD signatureLen) { DWORD i; BOOL result; /* Windows APIs expect the bytes in the signature to be in little-endian * order, but we write the signature in big-endian order. Other APIs like * NSS and OpenSSL expect big-endian order. */ BYTE *signatureReversed; if (!hash || !pubKey || !signature || signatureLen < 1) { return CryptoX_Error; } signatureReversed = malloc(signatureLen); if (!signatureReversed) { return CryptoX_Error; } for (i = 0; i < signatureLen; i++) { signatureReversed[i] = signature[signatureLen - 1 - i]; } result = CryptVerifySignature(*hash, signatureReversed, signatureLen, *pubKey, NULL, 0); free(signatureReversed); return result ? CryptoX_Success : CryptoX_Error; }
bool VerifySHA1Signature(const void *data, size_t dataLen, const char *hexSignature, const void *pubkey, size_t pubkeyLen) { HCRYPTPROV hProv = 0; HCRYPTKEY hPubKey = 0; HCRYPTHASH hHash = 0; BOOL ok = false; ScopedMem<BYTE> signature; size_t signatureLen; #define Check(val) if ((ok = (val)) == FALSE) goto CleanUp Check(ExtractSignature(hexSignature, data, dataLen, signature, signatureLen)); Check(CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)); Check(CryptImportKey(hProv, (const BYTE *)pubkey, (DWORD)pubkeyLen, 0, 0, &hPubKey)); Check(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)); #ifdef _WIN64 for (; dataLen > DWORD_MAX; data = (const BYTE *)data + DWORD_MAX, dataLen -= DWORD_MAX) { Check(CryptHashData(hHash, (const BYTE *)data, DWORD_MAX, 0)); } #endif Check(dataLen <= DWORD_MAX && pubkeyLen <= DWORD_MAX && signatureLen <= DWORD_MAX); Check(CryptHashData(hHash, (const BYTE *)data, (DWORD)dataLen, 0)); Check(CryptVerifySignature(hHash, signature, (DWORD)signatureLen, hPubKey, NULL, 0)); #undef Check CleanUp: if (hHash) CryptDestroyHash(hHash); if (hProv) CryptReleaseContext(hProv, 0); return ok; }
bool testVerifyHash(bool bVerbose){ BYTE bSignature[64]; strtobyte( "41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC049301456C64BA4642A1653C235A98A60249BCD6D3F746B631DF928014F6C5BF9C40" , bSignature ); DWORD dwSigLen = 64; HCRYPTHASH hHash; HCRYPTKEY hPub; BYTE bHashVal[32+1] = "\x2D\xFB\xC1\xB3\x72\xD8\x9A\x11\x88\xC0\x9C\x52\xE0\xEE\xC6\x1F\xCE\x52\x03\x2A\xB1\x02\x2E\x8E\x67\xEC\xE6\x67\x2B\x04\x3E\xE5"; if ( bVerbose ) std::cout << "Supplied hash value is: \n" << bHashVal << std::endl; if (!(CryptCreateHash(hProv, CALG_GOST_HASH, 0, 0, &hHash))) { if ( bVerbose ) printf("CryptCreateHash Failed\n"); return false; } if ( !CryptSetHashParam( hHash, HP_HASHVAL, bHashVal, 0)) { if ( bVerbose ) printf("CryptSetHashParam Failed\n"); return false; } if ( !CryptGetUserKey( hProv, AT_SIGNATURE, &hPub )) { if ( bVerbose ) printf("CryptGetUserKey Failed\n"); return false; } if (!CryptVerifySignature(hHash, bSignature, dwSigLen, hPub, NULL, 0)) { if ( bVerbose ) printf("Test Failed\n"); return false; } return true; }
int main(int argc, char *argv[]) { HANDLE signf = 0; HANDLE signmmf = 0; PBYTE signdata = NULL; LARGE_INTEGER signsz = {.QuadPart = 0}; void *keyblob = NULL; unsigned char err = 1; HCRYPTPROV prov; HCRYPTKEY key; HCRYPTHASH hash = 0; if (argc != 3) { fputs("Usage: lab2sign <input file> <output file>", stderr); return -1; } crash_if(!CryptAcquireContext(&prov, "lab2", MS_ENHANCED_PROV, PROV_RSA_FULL, 0), "Can't acquire crypt context."); hash = GetFileHash(prov, argv[1]); signf = CreateFileA(argv[2], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); signmmf = CreateFileMappingA(signf, NULL, PAGE_READONLY, 0, 0, NULL); crash_if(!signmmf, "Can't open memory mapped file."); GetFileSizeEx(signf, &signsz); signdata = MapViewOfFile(signmmf, FILE_MAP_READ, 0, 0, 0); crash_if(!signdata, "Can't map view of file."); crash_if(!CryptGetUserKey(prov, AT_SIGNATURE, &key), "Can't acquire signature key."); if (CryptVerifySignature(hash, signdata, signsz.LowPart, key, NULL, 0)) { printf("Signature matches.\n"); err = 0; } else { printf("Signature mismatch.\n"); } err: apply_not_null(signdata, UnmapViewOfFile); apply_not_null(signmmf, CloseHandle); apply_not_null(signf, CloseHandle); apply_not_null(keyblob, free); apply_not_null(hash, CryptDestroyHash) if (err) return -1; return 0; }
/** * Hashes a block of data and verifies it against an RSA signature. */ int verify_RSA_sig(RSA_key_t rsa, int hashtype, const unsigned char *mes, unsigned int meslen, unsigned char *sig, unsigned int siglen) { HCRYPTHASH hash; ALG_ID alg; unsigned hashlen, i; int rval; unsigned char *insig; hashlen = get_hash_len(hashtype); alg = get_hash(hashtype); if (!CryptCreateHash(base_prov, alg, 0, 0, &hash)) { mserror("CryptCreateHash failed"); return 0; } if (!CryptHashData(hash, mes, meslen, 0)) { mserror("CryptHashData failed"); rval = 0; goto end; } insig = calloc(siglen, 1); if (insig == NULL) { syserror(0, 0, "calloc failed!"); exit(1); } // CryptoAPI expects signatures in little endian, so reverse the bytes for (i = 0; i < siglen; i++) { insig[i] = sig[siglen - i - 1]; } if (!CryptVerifySignature(hash, insig, siglen, rsa, NULL, 0)) { mserror("CryptVerifySignature failed"); free(insig); rval = 0; goto end; } free(insig); rval = 1; end: if (!CryptDestroyHash(hash)) { mserror("CryptDestroyHash failed"); } return rval; }
void checkSig(unsigned char *tucHashBuf, unsigned char *tucSignature, DWORD dwSignatureLen, unsigned char *tucPubKeyBlob, DWORD dwPubKeyBlobLen) { HCRYPTPROV hProv; HCRYPTKEY hPubKey; HCRYPTHASH hHash; DWORD err; int errors = 0; if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) ERR_LOG_RET("CryptAcquireContext()"); if (!CryptImportKey(hProv, tucPubKeyBlob, dwPubKeyBlobLen, 0, 0, &hPubKey)) ERR_LOG_RET("CryptImportKey()"); if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) ERR_LOG_RET("CryptCreateHash(CALG_MD5)"); if (!CryptSetHashParam(hHash, HP_HASHVAL, tucHashBuf, 0)) ERR_LOG_RET("CryptSetHashParam(HP_HASHVAL)"); if (!CryptVerifySignature(hHash, tucSignature, dwSignatureLen, hPubKey, NULL, 0)) { err = GetLastError(); printf("ERR (line %d): CryptVerifySignature() returned %s (0x%0x)\n", __LINE__, e2str(err), err); errors++; } if (!CryptDestroyHash(hHash)) ERR_LOG_RET("CryptDestroyHash()"); if (!CryptDestroyKey(hPubKey)) ERR_LOG_RET("CryptDestroyKey()"); CryptReleaseContext(hProv, 0); done: return; }
// verify a signature using public key BOOL verify(void) { BOOL bStatus = FALSE; // initialize crypto API if (open_crypt()) { // import public key if (open_key(DSA_PUBLIC_BIN)) { // hash the input if (open_hash()) { // convert signature to binary sig2bin(); if (pbSignature != NULL) { // verify signature bStatus = CryptVerifySignature(hHash, pbSignature, dwSigLen, hKey, NULL, 0); printf(" [ signature is %s\n", bStatus ? "valid" : "invalid"); xfree(pbSignature); } close_hash(); } else { printf("open_hash()"); } close_key(); } else { printf("open_key()"); } close_crypt(); } else { printf("open_crypt()"); } return bStatus; }
/** * * verify a signature using public key * * sfile : file with signature encoded in PEM format * ifile : file with data to verify signature for * rsa : RSA object with public key * */ int rsa_verify( RSA* rsa, const char* ifile, const char* sfile) { DWORD sigLen; LPVOID sig; BOOL ok = FALSE; // convert PEM data to binary sig = rsa_read_pem(sfile, &sigLen); if (sig != NULL) { // calculate sha256 hash of file if (rsa_hash(rsa, ifile)) { // verify signature using public key ok = CryptVerifySignature(rsa->hash, sig, sigLen, rsa->pubkey, NULL, 0); } } return ok; }
bool vmsSecurity::VerifySign(LPCTSTR ptszFile, LPCTSTR ptszPubKey) { HCRYPTPROV hProv = NULL; BOOL bOK = CryptAcquireContext (&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!bOK) return false; BYTE abKey [1000]; DWORD dwKeySize; HANDLE h = CreateFile (ptszPubKey, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (h == INVALID_HANDLE_VALUE) return false; ReadFile (h, abKey, sizeof (abKey), &dwKeySize, NULL); CloseHandle (h); HCRYPTKEY hKey; if (FALSE == CryptImportKey (hProv, abKey, dwKeySize, NULL, 0, &hKey)) return false; LPBYTE pbData; DWORD dwDataSize; h = CreateFile (ptszFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (h == INVALID_HANDLE_VALUE) return FALSE; dwDataSize = GetFileSize (h, NULL); if (dwDataSize < strlen (FdmCryptSignatureMarker)) { CloseHandle (h); return false; } pbData = new BYTE [dwDataSize]; DWORD dw; ReadFile (h, pbData, dwDataSize, &dw, NULL); CloseHandle (h); int nSigLen = strlen (FdmCryptSignatureMarker); LPBYTE pbSig = pbData + dwDataSize - nSigLen; while (pbSig != pbData && strncmp ((char*)pbSig, FdmCryptSignatureMarker, nSigLen) != 0) pbSig--; if (pbData == pbSig) { delete [] pbData; return false; } HCRYPTHASH hHash; if (FALSE == CryptCreateHash (hProv, CALG_MD5, 0, 0, &hHash)) return false; if (FALSE == CryptHashData (hHash, pbData, pbSig - pbData, 0)) return false; BOOL bResult = CryptVerifySignature (hHash, pbSig + nSigLen, pbData + dwDataSize - pbSig - nSigLen, hKey, NULL, 0); CryptDestroyHash (hHash); delete [] pbData; CryptDestroyKey (hKey); CryptReleaseContext (hProv, 0); return bResult != FALSE; }
bool CCommonUtils::VerifyFile(LPCTSTR lpFileName, LPVOID lpKeyData, DWORD dwKeySize, LPCTSTR lpBase64) { LPVOID lpFileData = NULL; DWORD dwFileSize = 0; bool bRet = false; HCRYPTPROV hProv = NULL; HCRYPTKEY hKey = NULL; HCRYPTHASH hHash = NULL; LPVOID lpSignature = NULL; DWORD dwSigSize = 0; try { lpFileData = ReadFileData(lpFileName, dwFileSize); if(!lpFileData) { throw _com_error(E_FAIL); } if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptImportKey(hProv, (LPBYTE)lpKeyData, dwKeySize, NULL, 0, &hKey)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptHashData(hHash, (LPBYTE)lpFileData, dwFileSize, 0)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptStringToBinary(lpBase64, 0, CRYPT_STRING_BASE64, NULL, &dwSigSize, NULL, NULL)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } lpSignature = malloc(dwSigSize); if(!CryptStringToBinary(lpBase64, 0, CRYPT_STRING_BASE64, (LPBYTE)lpSignature, &dwSigSize, NULL, NULL)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptVerifySignature(hHash, (LPBYTE)lpSignature, dwSigSize, hKey, NULL, 0)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } bRet = true; } catch(_com_error& err) { DEBUG_PRINTF(L"Error in verifying file 0x%08X\n", err.Error()); } if(hHash) { CryptDestroyHash(hHash); } if(hProv) { CryptReleaseContext(hProv, 0); } if(lpSignature) { free(lpSignature); } if(lpFileData) { free(lpFileData); } if(lpKeyData) { free(lpKeyData); } return bRet; }
int KSI_PKITruststore_verifyRawSignature(KSI_CTX *ctx, const unsigned char *data, unsigned data_len, const char *algoOid, const unsigned char *signature, unsigned signature_len, const KSI_PKICertificate *certificate) { int res = KSI_UNKNOWN_ERROR; ALG_ID algorithm=0; HCRYPTPROV hCryptProv = 0; PCCERT_CONTEXT subjectCert = NULL; HCRYPTKEY publicKey = 0; DWORD i=0; BYTE *little_endian_pkcs1= NULL; DWORD pkcs1_len = 0; HCRYPTHASH hash = 0; char buf[1024]; KSI_ERR_clearErrors(ctx); if (ctx == NULL || data == NULL || signature == NULL || signature_len >= UINT_MAX || algoOid == NULL || certificate == NULL){ res = KSI_INVALID_ARGUMENT; goto cleanup; } algorithm = algIdFromOID(algoOid); if (algorithm == 0) { KSI_pushError(ctx, res = KSI_UNAVAILABLE_HASH_ALGORITHM, NULL); goto cleanup; } // Get the CSP context if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get cryptographic provider."); goto cleanup; } // Get the public key from the issuer certificate subjectCert = certificate->x509; if (!CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,&subjectCert->pCertInfo->SubjectPublicKeyInfo,&publicKey)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Failed to read PKI public key."); goto cleanup; } /*Convert big-endian to little-endian PKCS#1 signature*/ pkcs1_len = signature_len; little_endian_pkcs1 = (BYTE*)KSI_malloc(pkcs1_len); if (little_endian_pkcs1 == NULL){ KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } for (i=0; i<pkcs1_len; i++){ little_endian_pkcs1[pkcs1_len-1-i] = signature[i]; } // Create the hash object and hash input data. if (!CryptCreateHash(hCryptProv, algorithm, 0, 0, &hash)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to create hasher."); goto cleanup; } if (!CryptHashData(hash, (BYTE*)data, data_len,0)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to hash data."); goto cleanup; } /*Verify the signature. The format MUST be PKCS#1*/ if (!CryptVerifySignature(hash, (BYTE*)little_endian_pkcs1, pkcs1_len, publicKey, NULL, 0)){ DWORD error = GetLastError(); const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf)); KSI_LOG_debug(ctx, "%s", errmsg); if (error == NTE_BAD_SIGNATURE) KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Invalid PKI signature."); else if (error == NTE_NO_MEMORY) KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, "Unable to verify PKI signature. CSP out of memory."); else KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, errmsg); goto cleanup; } KSI_LOG_debug(certificate->ctx, "CryptoAPI: PKI signature verified successfully."); res = KSI_OK; cleanup: KSI_free(little_endian_pkcs1); if (hCryptProv) CryptReleaseContext(hCryptProv, 0); if (hash) CryptDestroyHash(hash); return res; }
int VerifyDataSignWithHashAlg(const char * userData, const char * hashAlg, const char * certDataB64, const char * signatureDataB64) { int rv = -1; int ulHashAlg = 0; HCRYPTHASH hHash = NULL; char * pbCert = NULL; char * pbSignature = NULL; unsigned int ulCert = 0; unsigned int ulSignature = 0; PCCERT_CONTEXT pCertContext = NULL; HCRYPTPROV hProv = NULL; HCRYPTKEY hPubKey = NULL; { ulCert = modp_b64_decode_len(strlen(certDataB64)); ulSignature = modp_b64_decode_len(strlen(signatureDataB64)); pbCert = (char *)malloc(ulCert); pbSignature = (char *) malloc(ulSignature); if (NULL == pbCert || NULL == pbSignature) { sprintf(m_errMsg, "%s","memroy less.\n" ); goto err; } ulCert = modp_b64_decode(pbCert, certDataB64,strlen(certDataB64)); ulSignature = modp_b64_decode(pbSignature, signatureDataB64,strlen(signatureDataB64)); } if (0 == strcmp(hashAlg, "MD5")) { ulHashAlg = CALG_MD5; } else if (0 == strcmp(hashAlg, "SHA")) { ulHashAlg = CALG_SHA; } else if (0 == strcmp(hashAlg, "SHA1")) { ulHashAlg = CALG_SHA1; } else if (0 == strcmp(hashAlg, "SHA_256")) { ulHashAlg = CALG_SHA_256; } else if (0 == strcmp(hashAlg, "SHA_384")) { ulHashAlg = CALG_SHA_384; } pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (BYTE *)pbCert,ulCert); if (!pCertContext) { sprintf(m_errMsg, "%s","Select Certificate UI failed.\n" ); goto err; } //Ò»¡¢»ñµÃÒ»¸öCSP¾ä±ú if(!CryptAcquireContext( &hProv, NULL, //ÃÜÔ¿ÈÝÆ÷Ãû£¬NULL±íʾʹÓÃĬÈÏÈÝÆ÷ NULL, //CSP_NAME PROV_RSA_FULL, 0 )) { if(!CryptAcquireContext( &hProv, NULL, //ÃÜÔ¿ÈÝÆ÷Ãû£¬NULL±íʾʹÓÃĬÈÏÈÝÆ÷ NULL, //CSP_NAME PROV_RSA_FULL, CRYPT_NEWKEYSET //´´½¨ÃÜÔ¿ÈÝÆ÷ )) { sprintf(m_errMsg, "%s","CryptAcquireContext fail.\n"); goto err; } } if(CryptImportPublicKeyInfo( hProv, X509_ASN_ENCODING, &(pCertContext->pCertInfo->SubjectPublicKeyInfo), &hPubKey )) { sprintf(m_errMsg,"CryptImportPublicKeyInfo OK. \n"); } else { sprintf(m_errMsg,"Error CryptImportPublicKeyInfo.\n"); goto err; } //if(CryptImportKey(hProv,pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData, NULL, 0, &hPubKey)) //{ // sprintf(m_errMsg,"CryptImportKey OK. \n"); //} //else //{ // sprintf(m_errMsg,"Error CryptImportKey.\n"); // goto err; //} if(CryptCreateHash( hProv, ulHashAlg, 0, 0, &hHash)) { sprintf(m_errMsg, "%s","An empty hash object has been created. \n"); } else { sprintf(m_errMsg, "%s","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, (unsigned char *)userData, strlen(userData), 0)) { sprintf(m_errMsg, "%s","The data buffer has been added to the hash.\n"); } else { sprintf(m_errMsg, "%s","Error during CryptHashData.\n"); goto err; } if(CryptVerifySignature(hHash, (const BYTE *)pbSignature, ulSignature,hPubKey,NULL,0)) { sprintf(m_errMsg,"verify OK.\n"); } else { sprintf(m_errMsg,"Error during CryptVerifySignature.\n"); goto err; } rv = 0; err: if(hHash) { CryptDestroyHash(hHash); } if (pbSignature) { free(pbSignature); } if (pbCert) { free(pbCert); } if (pCertContext) { CertFreeCertificateContext(pCertContext); } if(hProv) { CryptReleaseContext(hProv,0); } return rv; }
void main(void) { //------------------------------------------------------------------- // Declare and initialize variables. HCRYPTPROV hProv; BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed."; DWORD dwBufferLen = strlen((char *)pbBuffer)+1; HCRYPTHASH hHash; HCRYPTKEY hKey; HCRYPTKEY hPubKey; BYTE *pbKeyBlob; BYTE *pbSignature; DWORD dwSigLen; DWORD dwBlobLen; //------------------------------------------------------------------- // Acquire a cryptographic provider context handle. if(CryptAcquireContext( &hProv, NULL, NULL, PROV_RSA_FULL, 0)) { printf("CSP context acquired.\n"); } else { MyHandleError("Error during CryptAcquireContext."); } //------------------------------------------------------------------- // Get the public at signature key. This is the public key // that will be used by the receiver of the hash to verify // the signature. In situations where the receiver could obtain the // sender's public key from a certificate, this step would not be // needed. if(CryptGetUserKey( hProv, AT_SIGNATURE, &hKey)) { printf("The signature key has been acquired. \n"); } else { MyHandleError("Error during CryptGetUserKey for signkey."); } //------------------------------------------------------------------- // Export the public key. Here the public key is exported to a // PUBLICKEYBOLB so that the receiver of the signed hash can // verify the signature. This BLOB could be written to a file and // sent to another user. if(CryptExportKey( hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) { printf("Size of the BLOB for the public key determined. \n"); } else { MyHandleError("Error computing BLOB length."); } //------------------------------------------------------------------- // Allocate memory for the pbKeyBlob. if(pbKeyBlob = (BYTE*)malloc(dwBlobLen)) { printf("Memory has been allocated for the BLOB. \n"); } else { MyHandleError("Out of memory. \n"); } //------------------------------------------------------------------- // Do the actual exporting into the key BLOB. if(CryptExportKey( hKey, NULL, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) { printf("Contents have been written to the BLOB. \n"); } else { MyHandleError("Error during CryptExportKey."); } //------------------------------------------------------------------- // Create the hash object. if(CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash)) { printf("Hash object created. \n"); } else { MyHandleError("Error during CryptCreateHash."); } //------------------------------------------------------------------- // Compute the cryptographic hash of the buffer. if(CryptHashData( hHash, pbBuffer, dwBufferLen, 0)) { printf("The data buffer has been hashed.\n"); } else { MyHandleError("Error during CryptHashData."); } //------------------------------------------------------------------- // Determine the size of the signature and allocate memory. dwSigLen= 0; if(CryptSignHash( hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen)) { printf("Signature length %d found.\n",dwSigLen); } else { MyHandleError("Error during CryptSignHash."); } //------------------------------------------------------------------- // Allocate memory for the signature buffer. if(pbSignature = (BYTE *)malloc(dwSigLen)) { printf("Memory allocated for the signature.\n"); } else { MyHandleError("Out of memory."); } //------------------------------------------------------------------- // Sign the hash object. if(CryptSignHash( hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)) { printf("pbSignature is the hash signature.\n"); } else { MyHandleError("Error during CryptSignHash."); } //------------------------------------------------------------------- // Destroy the hash object. if(hHash) CryptDestroyHash(hHash); printf("The hash object has been destroyed.\n"); printf("The signing phase of this program is completed.\n\n"); //------------------------------------------------------------------- // In the second phase, the hash signature is verified. // This would most often be done by a different user in a // separate program. The hash, signature, and the PUBLICKEYBLOB // would be read from a file, an email message, // or some other source. // Here, the original pbBuffer, pbSignature, szDescription. // pbKeyBlob, and their lengths are used. // The contents of the pbBuffer must be the same data // that was originally signed. //------------------------------------------------------------------- // Get the public key of the user who created the digital signature // and import it into the CSP by using CryptImportKey. This returns // a handle to the public key in hPubKey. if(CryptImportKey( hProv, pbKeyBlob, dwBlobLen, 0, 0, &hPubKey)) { printf("The key has been imported.\n"); } else { MyHandleError("Public key import failed."); } //------------------------------------------------------------------- // Create a new hash object. if(CryptCreateHash( hProv, CALG_MD5, 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); } // End of main
BOOL SignVerifyFile(HCRYPTPROV hProv, HCRYPTKEY hPubKey, DWORD dwKeySpec, ALG_ID HashAlgId, LPTSTR szFileToSign, LPTSTR szSigFile, BOOL fSign) { HCRYPTHASH hHash = NULL; HANDLE hDataFile = INVALID_HANDLE_VALUE; HANDLE hSigFile = INVALID_HANDLE_VALUE; LPBYTE pbSignature = NULL; DWORD dwSignature; BYTE pbBuffer[BUFFER_SIZE]; DWORD dwBytesRead, dwBytesWritten; BOOL fResult; BOOL fFinished = FALSE; BOOL fReturn = FALSE; __try { // Open Data file hDataFile = CreateFile(szFileToSign, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDataFile == INVALID_HANDLE_VALUE) { MyPrintf(_T("CreateFile failed with %d\n"), GetLastError()); __leave; } // Open/Create signature file hSigFile = CreateFile(szSigFile, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hSigFile == INVALID_HANDLE_VALUE) { MyPrintf(_T("CreateFile failed with %d\n"), GetLastError()); __leave; } // Create Hash fResult = CryptCreateHash(hProv, HashAlgId, 0, 0, &hHash); if (!fResult) { MyPrintf(_T("CryptCreateHash failed with %x\n"), GetLastError()); __leave; } // Loop through file and hash file contents do { dwBytesRead = 0; fResult = ReadFile(hDataFile, pbBuffer, BUFFER_SIZE, &dwBytesRead, NULL); if (dwBytesRead == 0) break; if (!fResult) { MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); __leave; } fFinished = (dwBytesRead < BUFFER_SIZE); fResult = CryptHashData(hHash, pbBuffer, dwBytesRead, 0); if (!fResult) { MyPrintf(_T("CryptHashData failed with %x\n"), GetLastError()); __leave; } } while (fFinished == FALSE); if (fSign) { // Get Signature size fResult = CryptSignHash(hHash, dwKeySpec, NULL, 0, NULL, &dwSignature); if (!fResult) { MyPrintf(_T("CryptSignHash failed with %x\n"), GetLastError()); __leave; } // Allocate signature bytes pbSignature = (LPBYTE)LocalAlloc(LPTR, dwSignature); if (!pbSignature) { MyPrintf(_T("LocalAlloc failed with %d\n"), GetLastError()); __leave; } // Sign and get back signature fResult = CryptSignHash(hHash, dwKeySpec, NULL, 0, pbSignature, &dwSignature); if (!fResult) { MyPrintf(_T("CryptSignHash failed with %x\n"), GetLastError()); __leave; } // Write signature to file fResult = WriteFile(hSigFile, pbSignature, dwSignature, &dwBytesWritten, NULL); if (!fResult) { MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); __leave; } } else { // Get size of signature file dwSignature = GetFileSize(hSigFile, NULL); if (dwSignature == INVALID_FILE_SIZE) { MyPrintf(_T("GetFileSize failed with %d\n"), GetLastError()); __leave; } // Allocate signature bytes pbSignature = (LPBYTE)LocalAlloc(LPTR, dwSignature); if (!pbSignature) { MyPrintf(_T("LocalAlloc failed with %d\n"), GetLastError()); __leave; } // Read Signature fResult = ReadFile(hSigFile, pbSignature, dwSignature, &dwBytesRead, NULL); if (!fResult) { MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); __leave; } // Verify Signature fResult = CryptVerifySignature(hHash, pbSignature, dwSignature, hPubKey, NULL, 0); if (!fResult) { MyPrintf(_T("CryptVerifySignature failed with %x\n"), GetLastError()); __leave; } } fReturn = TRUE; } __finally { // Clean up if (hHash != NULL) CryptDestroyHash(hHash); if (hDataFile != INVALID_HANDLE_VALUE) CloseHandle(hDataFile); if (hSigFile != INVALID_HANDLE_VALUE) CloseHandle(hSigFile); CheckAndLocalFree(pbSignature); } return fReturn; }
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; }