Code:
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include <wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ENCODING | X509v3_ENCODING)
#define KEYLENGTH 0x00800000
void MyHandleError(char *s);
void GetConsoleInput(char* strInput, int intMaxChars);
//-------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// The following additional #define statements are required.
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
// Declare the function EncryptFile. The function definition
// follows main.
BOOL EncryptFile(
PCHAR szSource,
PCHAR szDestination,
PCHAR szPassword);
//-------------------------------------------------------------------
// Begin main.
void main(void)
{
PCHAR szSource;
PCHAR szDestination;
CHAR szPassword[100] = "";
char response;
if(!(szSource=(char *)malloc(100)))
MyHandleError("Memory allocation failed.");
if(!(szDestination=(char *)malloc(100)))
MyHandleError("Memory allocation failed.");
printf("Encrypt a file. \n\n");
printf("Enter the name of the file to be encrypted: ");
fgets(szSource, 100, stdin);
if(szSource[strlen(szSource)-1] == '\n')
szSource[strlen(szSource)-1] = '\0';
printf("Enter the name of the output file: ");
fgets(szDestination, 100, stdin);
if(szDestination[strlen(szDestination)-1] == '\n')
szDestination[strlen(szDestination)-1] = '\0';
printf("Use a password to encrypt this file? ( y/n ) ");
response = getchar();
if(response == 'y')
{
printf("Enter the password:");
GetConsoleInput(szPassword, sizeof(szPassword)/sizeof(char) - 1);
}
else
{
printf("The key will be generated without using a password. \n");
}
//-------------------------------------------------------------------
// Call EncryptFile to do the actual encryption.
if(EncryptFile(szSource, szDestination, szPassword))
{
printf("Encryption of the file %s was a success. \n",
szSource);
printf("The encrypted data is in file %s.\n",szDestination);
}
else
{
MyHandleError("Error encrypting file!");
}
//-------------------------------------------------------------------
// Free memory.
if(szSource)
free(szSource);
if(szDestination)
free(szDestination);
} // end main
//-------------------------------------------------------------------
// Code for the function EncryptFile called by main.
static BOOL EncryptFile(
PCHAR szSource,
PCHAR szDestination,
PCHAR szPassword)
//-------------------------------------------------------------------
// Parameters passed are:
// szSource, the name of the input, a plaintext file.
// szDestination, the name of the output, an encrypted file to be
// created.
// szPassword, either NULL if a password is not to be used or the
// string that is the password.
{
//-------------------------------------------------------------------
// Declare and initialize local variables.
FILE *hSource;
FILE *hDestination;
HCRYPTPROV hCryptProv;
HCRYPTKEY hKey;
HCRYPTKEY hXchgKey;
HCRYPTHASH hHash;
PBYTE pbKeyBlob;
DWORD dwKeyBlobLen;
PBYTE pbBuffer;
DWORD dwBlockLen;
DWORD dwBufferLen;
DWORD dwCount;
//-------------------------------------------------------------------
// Open source file.
if(hSource = fopen(szSource,"rb"))
{
printf("The source plaintext file, %s, is open. \n", szSource);
}
else
{
MyHandleError("Error opening source plaintext file!");
}
//-------------------------------------------------------------------
// Open destination file.
if(hDestination = fopen(szDestination,"wb"))
{
printf("Destination file %s is open. \n", szDestination);
}
else
{
MyHandleError("Error opening destination ciphertext file!");
}
// Get the handle to the default provider.
if(CryptAcquireContext(
&hCryptProv,
NULL,
MS_ENHANCED_PROV,
PROV_RSA_FULL,
0))
{
printf("A cryptographic provider has been acquired. \n");
}
else
{
MyHandleError("Error during CryptAcquireContext!");
}
//-------------------------------------------------------------------
// Create the session key.
if(!szPassword )
{
//--------------------------------------------------------------
// No password was passed.
// Encrypt the file with a random session key, and write the key
// to a file.
//--------------------------------------------------------------
// Create a random session key.
if(CryptGenKey(
hCryptProv,
ENCRYPT_ALGORITHM,
KEYLENGTH | CRYPT_EXPORTABLE,
&hKey))
{
printf("A session key has been created. \n");
}
else
{
MyHandleError("Error during CryptGenKey. \n");
}
//--------------------------------------------------------------
// Get the handle to the encrypter's exchange public key.
if(CryptGetUserKey(
hCryptProv,
AT_KEYEXCHANGE,
&hXchgKey))
{
printf("The user public key has been retrieved. \n");
}
else
{
MyHandleError("User public key is not available \
and may not exist.");
}
//--------------------------------------------------------------
// Determine size of the key BLOB, and allocate memory.
if(CryptExportKey(
hKey,
hXchgKey,
SIMPLEBLOB,
0,
NULL,
&dwKeyBlobLen))
{
printf("The key BLOB is %d bytes long. \n",dwKeyBlobLen);
}
else
{
MyHandleError("Error computing BLOB length! \n");
}
if(pbKeyBlob =(BYTE *)malloc(dwKeyBlobLen))
{
printf("Memory is allocated for the key BLOB. \n");
}
else
{
MyHandleError("Out of memory. \n");
}
//--------------------------------------------------------------
// Encrypt and export the session key into a simple key BLOB.
if(CryptExportKey(
hKey,
hXchgKey,
SIMPLEBLOB,
0,
pbKeyBlob,
&dwKeyBlobLen))
{
printf("The key has been exported. \n");
}
else
{
MyHandleError("Error during CryptExportKey!\n");
}
//--------------------------------------------------------------
// Release the key exchange key handle.
if(hXchgKey)
{
if(!(CryptDestroyKey(hXchgKey)))
MyHandleError("Error during CryptDestroyKey");
hXchgKey = 0;
}
//--------------------------------------------------------------
// Write the size of the key BLOB to a destination file.
fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDestination);
if(ferror(hDestination))
{
MyHandleError("Error writing header.");
}
else
{
printf("A file header has been written. \n");
}
//--------------------------------------------------------------
// Write the key BLOB to a destination file.
fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDestination);
if(ferror(hDestination))
{
MyHandleError("Error writing header");
}
else
{
printf("The key BLOB has been written to the file. \n");
}
// Free memory.
free(pbKeyBlob);
}
else
{
//-------------------------------------------------------------------
// The file will be encrypted with a session key derived from a
// password.
// The session key will be recreated when the file is decrypted
// only if the password used to create the key is available.
//-------------------------------------------------------------------
// Create a hash object.
if(CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash))
{
printf("A hash object has been created. \n");
}
else
{
MyHandleError("Error during CryptCreateHash!\n");
}
//-------------------------------------------------------------------
// Hash the password.
if(CryptHashData(
hHash,
(BYTE *)szPassword,
strlen(szPassword),
0))
{
printf("The password has been added to the hash. \n");
}
else
{
MyHandleError("Error during CryptHashData. \n");
}
//-------------------------------------------------------------------
// Derive a session key from the hash object.
if(CryptDeriveKey(
hCryptProv,
ENCRYPT_ALGORITHM,
hHash,
KEYLENGTH,
&hKey))
{
printf("An encryption key is derived from the password hash. \n");
}
else
{
MyHandleError("Error during CryptDeriveKey!\n");
}
//-------------------------------------------------------------------
// Destroy hash object.
if(hHash)
{
if(!(CryptDestroyHash(hHash)))
MyHandleError("Error during CryptDestroyHash");
hHash = 0;
}
}
//-------------------------------------------------------------------
// The session key is now ready. If it is not a key derived from a
// password, the session key encrypted with the encrypter's private
// key has been written to the destination file.
//-------------------------------------------------------------------
// Determine the number of bytes to encrypt at a time.
// This must be a multiple of ENCRYPT_BLOCK_SIZE.
// ENCRYPT_BLOCK_SIZE is set by a #define statement.
dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
//-------------------------------------------------------------------
// Determine the block size. If a block cipher is used,
// it must have room for an extra block.
if(ENCRYPT_BLOCK_SIZE > 1)
dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
else
dwBufferLen = dwBlockLen;
//-------------------------------------------------------------------
// Allocate memory.
if(pbBuffer = (BYTE *)malloc(dwBufferLen))
{
printf("Memory has been allocated for the buffer. \n");
}
else
{
MyHandleError("Out of memory. \n");
}
//-------------------------------------------------------------------
// In a do loop, encrypt the source file,
// and write to the source file.
do
{
//-------------------------------------------------------------------
// Read up to dwBlockLen bytes from the source file.
dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
if(ferror(hSource))
{
MyHandleError("Error reading plaintext!\n");
}
//-------------------------------------------------------------------
// Encrypt data.
if(!CryptEncrypt(
hKey,
0,
feof(hSource),
0,
pbBuffer,
&dwCount,
dwBufferLen))
{
MyHandleError("Error during CryptEncrypt. \n");
}
//-------------------------------------------------------------------
// Write data to the destination file.
fwrite(pbBuffer, 1, dwCount, hDestination);
if(ferror(hDestination))
{
MyHandleError("Error writing ciphertext.");
}
}
while(!feof(hSource));
//-------------------------------------------------------------------
// End the do loop when the last block of the source file has been
// read, encrypted, and written to the destination file.
//-------------------------------------------------------------------
// Close files.
if(hSource)
{
if(fclose(hSource))
MyHandleError("Error closing source file");
}
if(hDestination)
{
if(fclose(hDestination))
MyHandleError("Error closing destination file");
}
//-------------------------------------------------------------------
// Free memory.
if(pbBuffer)
free(pbBuffer);
//-------------------------------------------------------------------
// Destroy the session key.
if(hKey)
{
if(!(CryptDestroyKey(hKey)))
MyHandleError("Error during CryptDestroyKey");
}
//-------------------------------------------------------------------
// Release the provider handle.
if(hCryptProv)
{
if(!(CryptReleaseContext(hCryptProv, 0)))
MyHandleError("Error during CryptReleaseContext");
}
return(TRUE);
} // end Encryptfile
//-------------------------------------------------------------------
// This example uses the function MyHandleError, a simple error
// handling function to print an error message to the standard error
// (stderr) file and exit the program.
// For most applications, replace this function with one
// that does more extensive error reporting.
void MyHandleError(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 MyHandleError
//-------------------------------------------------------------------
// The GetConsoleInput function gets an array of characters from the
// keyboard, while printing only asterisks to the screen.
void GetConsoleInput(char* strInput,
int intMaxChars)
{
char ch;
char minChar = ' ';
minChar++;
ch = getch();
while (ch != '\r')
{
if (ch == '\b' && strlen(strInput) > 0)
{
strInput[strlen(strInput)-1] = '\0';
printf("\b \b");
}
else if (ch >= minChar && strlen(strInput) < intMaxChars)
{
strInput[strlen(strInput)+1] = '\0';
strInput[strlen(strInput)] = ch;
putch('*');
}
ch = getch();
}
putch('\n');
}