VERIFILE.C
/******************************************************************************\ 
*       This is a part of the Microsoft Source Code Samples.  
*       Copyright 1996 - 1998 Microsoft Corporation. 
*       All rights reserved.  
*       This source code is only intended as a supplement to  
*       Microsoft Development Tools and/or WinHelp documentation. 
*       See these sources for detailed information regarding the  
*       Microsoft samples programs. 
\******************************************************************************/ 
 
#include <windows.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <wincrypt.h> 
 
static BOOL VerifyFile(PCHAR szSourceFile, PCHAR szSignatureFile, PCHAR szDescription); 
 
/*****************************************************************************/ 
void _cdecl main(int argc, char *argv[]) 
{ 
    PCHAR szSourceFile  = NULL; 
    PCHAR szSignatureFile = NULL; 
    PCHAR szDescription  = NULL; 
 
    // Validate argument count. 
    if(argc != 4) { 
printf("USAGE: signfile <source file> <signature file> <description>\n"); 
exit(1); 
    } 
 
    // Parse arguments. 
    szSourceFile    = argv[1]; 
    szSignatureFile = argv[2]; 
    szDescription   = argv[3]; 
 
    if(!VerifyFile(szSourceFile, szSignatureFile, szDescription)) { 
printf("Error verifying file!\n"); 
exit(1); 
    } 
 
    exit(0); 
} 
 
/*****************************************************************************/ 
static BOOL VerifyFile(PCHAR szSourceFile, PCHAR szSignatureFile, PCHAR szDescription) 
{ 
    FILE *hSourceFile = NULL; 
    FILE *hSignatureFile = NULL; 
    INT eof = 0; 
 
    HCRYPTPROV hProv = 0; 
    HCRYPTHASH hHash = 0; 
    HCRYPTKEY hSigPublicKey = 0; 
 
    PBYTE pbSignature = NULL; 
    DWORD dwSignatureLen; 
 
    PBYTE pbBuffer = NULL; 
    DWORD dwBufferLen; 
    DWORD dwCount; 
 
    // Get handle to the default provider. 
    if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) { 
        printf("Error %x during CryptAcquireContext!\n", GetLastError()); 
goto error; 
    } 
 
    // 
    // Hash source file. 
    // 
 
    // Determine number of bytes to hash at once. 
    dwBufferLen = 1000; 
 
    // Allocate memory for 'pbBuffer'. 
    if((pbBuffer = malloc(dwBufferLen)) == NULL) { 
printf("Out of memory 1!\n"); 
goto error; 
    } 
 
    // Open source file. 
    if((hSourceFile = fopen(szSourceFile,"rb")) == NULL) { 
printf("Error opening source file!\n"); 
goto error; 
    } 
 
    // Create a hash object. 
    if(!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { 
printf("Error %x during CryptCreateHash!\n", GetLastError()); 
goto error; 
    } 
 
    // Hash source file. 
    do { 
// Read up to 'dwBufferLen' bytes from source file. 
dwCount = fread(pbBuffer, 1, dwBufferLen, hSourceFile); 
if(ferror(hSourceFile)) { 
    printf("Error reading Plaintext!\n"); 
    goto error; 
        } 
eof = feof(hSourceFile); 
 
// Add data to hash object. 
if(!CryptHashData(hHash, pbBuffer, dwCount, 0)) { 
    printf("Error %x during CryptHashData!\n", GetLastError()); 
    goto error; 
} 
    } while(!feof(hSourceFile)); 
 
    // Close source file. 
    fclose(hSourceFile); 
    hSourceFile = 0; 
 
    // Free 'pbBuffer' memory. 
    free(pbBuffer); 
    pbBuffer = NULL; 
 
 
    // 
    // Read in signature file. 
    // 
 
    // Determine size of signature. 
    dwSignatureLen = 0; 
    if(!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSignatureLen)) { 
printf("Error %x during CryptSignHash!\n", GetLastError()); 
goto error; 
    } 
 
    // Allocate memory for 'pbSignature'. 
    if((pbSignature = malloc(dwSignatureLen)) == NULL) { 
printf("Out of memory 2!\n"); 
goto error; 
    } 
 
    // Open signature file. 
    if((hSignatureFile = fopen(szSignatureFile,"rb")) == NULL) { 
printf("Error opening signature file!\n"); 
goto error; 
    } 
 
    // Read signature data. 
    dwCount = fread(pbSignature, 1, dwSignatureLen, hSignatureFile); 
    if(ferror(hSignatureFile)) { 
printf("Error reading signature!\n"); 
goto error; 
    } 
 
    // Close signature file. 
    fclose(hSignatureFile); 
    hSignatureFile = 0; 
 
 
    // 
    // Verify signature. 
    // 
 
    // Get handle to signature key. 
    if(!CryptGetUserKey(hProv, AT_SIGNATURE, &hSigPublicKey)) { 
printf("Error %x during CryptGetUserKey!\n", GetLastError()); 
goto error; 
    } 
 
    // Verify signature. 
    if(!CryptVerifySignature(hHash, pbSignature, dwSignatureLen, hSigPublicKey, szDescription, 0)) { 
if(GetLastError() == NTE_BAD_SIGNATURE) { 
    printf("Signature did not match!\n"); 
} else { 
    printf("Error %x during CryptVerifySignature!\n", GetLastError()); 
} 
goto error; 
    } 
 
    // Release signature key. 
    CryptDestroyKey(hSigPublicKey); 
    hSigPublicKey = 0; 
 
    // Free 'pbSignature' memory. 
    free(pbSignature); 
    pbSignature = NULL; 
 
    // Destroy hash object. 
    CryptDestroyHash(hHash); 
    hHash = 0; 
 
    // Release provider handle. 
    CryptReleaseContext(hProv, 0); 
    hProv = 0; 
 
    printf("OK\n"); 
 
    return TRUE; 
 
    error: 
 
    // 
    // Do cleanup 
    // 
 
    // Close files. 
    if(hSourceFile) fclose(hSourceFile); 
    if(hSignatureFile) fclose(hSignatureFile); 
 
    // Free memory. 
    if(pbSignature) free(pbSignature); 
    if(pbBuffer) free(pbBuffer); 
 
    // Release crypto handles. 
    if(hHash) CryptDestroyHash(hHash); 
    if(hSigPublicKey) CryptDestroyKey(hSigPublicKey); 
    if(hProv) CryptReleaseContext(hProv, 0); 
 
    return FALSE; 
}