📄 aescryptworkerthreads.cpp
字号:
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
result_code = GetLastError();
if (GetLastError() == NTE_BAD_KEYSET)
{
if (!CryptAcquireContext( &hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT))
{
result_code = GetLastError();
}
else
{
result_code = ERROR_SUCCESS;
}
}
if (result_code != ERROR_SUCCESS)
{
::ReportError(
_T("Could not acquire handle to crypto context"),
0);
error_abort = true;
}
}
// Walk through the list of files encrypting each
while(!file_list->empty() && !error_abort)
{
// Get the filename
in_file = file_list->front();
out_file = in_file + _T(".aes");
// Reset the progress bar (default range is 0..100)
dlg.SendDlgItemMessage( IDC_PROGRESSBAR,
PBM_SETPOS,
0,
0);
// Display the file name
dlg.SetDlgItemText( IDC_FILENAME,
in_file.c_str());
// Make sure the window is visible
dlg.ShowWindow(SW_SHOWNORMAL);
dlg.UpdateWindow();
DoMessageLoop();
result_code = in_buffered_file.OpenFile(in_file.c_str(),
false,
OPEN_EXISTING);
if (result_code != ERROR_SUCCESS)
{
::ReportError( _T("Unable to open input file ") + in_file,
result_code);
error_abort = true;
}
else
{
result_code = out_buffered_file.OpenFile(
out_file.c_str(),
true,
CREATE_NEW);
if (result_code != ERROR_SUCCESS)
{
// Close the input file
in_buffered_file.CloseFile();
::ReportError( _T("Unable to open output file ") + out_file,
result_code);
error_abort = true;
}
else
{
try
{
// Create the 16-bit IV and 32-bit encryption key
// used for encrypting the plaintext file. We do
// not trust the system's randomization functions, so
// we improve on that by also hashing the random digits
// and using only a portion of the hash. This IV and key
// generation could be replaced with any good random
// source of data.
memset(iv_key, 0, 48);
for (i=0; i<48; i+=16)
{
memset(buffer, 0, 32);
sha256_starts(&sha_ctx);
for(j=0; j<256; j++)
{
if (!CryptGenRandom(hProv,
32,
(BYTE *) buffer))
{
throw SystemErrorException(
_T("Windows is unable to generate random digits"),
0);
}
sha256_update(&sha_ctx, buffer, 32);
}
sha256_finish(&sha_ctx, digest);
memcpy(iv_key+i, digest, 16);
}
// Determine the file size
result_code = in_buffered_file.FileSize(&file_size);
if (result_code != ERROR_SUCCESS)
{
throw SystemErrorException(
_T("Unable to determine file size of ") +
in_file,
result_code);
}
// Write an AES signature at the head of the file.
// Write file versioning information. Since this is
// version 1, we will just write a 1. This field might
// be bit-mapped in a future update, so if the field
// is not zero, the program should not try to
// interpret the file.
buffer[0] = 'A';
buffer[1] = 'E';
buffer[2] = 'S';
buffer[3] = (unsigned char) 0x01; // Version 1
buffer[4] = '\0'; // Reserved for version 0
result_code = out_buffered_file.WriteFile( buffer,
5,
&bytes_written);
if (result_code != ERROR_SUCCESS)
{
throw SystemErrorException(
_T("Unable to write to ") +
out_file,
result_code);
}
// We will use an initialization vector comprised of
// the current time, file size, file name, and 32 octets
// of psuedo-random digits, all hashed together with
// SHA-256.
current_time = time(NULL);
for(i = 0; i < 8; i++)
{
buffer[i] = (unsigned char)
(current_time >> (i * 8));
}
for(i = 0; i< 8; i++)
{
buffer[i+8] = (unsigned char)
(file_size.QuadPart >> (i*8));
}
sha256_starts( &sha_ctx);
sha256_update( &sha_ctx, buffer, 16);
sha256_update( &sha_ctx,
(unsigned char *)in_file.c_str(),
// Unicode means the bytes are twice
// the string length.
(unsigned long)
_tcsnlen( in_file.c_str(),
(MAX_PATH+1)) *
sizeof(TCHAR));
for(i=0; i<256; i++)
{
if (!CryptGenRandom(hProv,
32,
(BYTE *) buffer))
{
throw SystemErrorException(
_T("Windows is unable to generate random digits"),
0);
}
sha256_update(&sha_ctx, buffer, 32);
}
sha256_finish(&sha_ctx, digest);
memcpy(IV, digest, 16);
// Write the initialization vector to the file
result_code = out_buffered_file.WriteFile( IV,
16,
&bytes_written);
if (result_code != ERROR_SUCCESS)
{
throw SystemErrorException(
_T("Unable to write to ") +
out_file,
result_code);
}
// Hash the IV and password 8192 times
memset(digest, 0, 32);
memcpy(digest, IV, 16);
for(i=0; i<8192; i++)
{
sha256_starts( &sha_ctx);
sha256_update( &sha_ctx, digest, 32);
sha256_update( &sha_ctx,
(unsigned char*)passwd,
// Unicode means the bytes are twice
// the string length.
(unsigned long)
_tcsnlen(passwd, MAX_PASSWD_LEN+1)*
sizeof(TCHAR));
sha256_finish( &sha_ctx,
digest);
}
// Because the aes_set_key routine is not thread safe,
// protect it with a critical section.
EnterCriticalSection(&Critical_Section);
aes_set_key(&aes_ctx, digest, 256);
LeaveCriticalSection(&Critical_Section);
// Set the ipad and opad arrays with values as
// per RFC 2104 (HMAC). HMAC is defined as
// H(K XOR opad, H(K XOR ipad, text))
memset(ipad, 0x36, 64);
memset(opad, 0x5C, 64);
for(i=0; i<32; i++)
{
ipad[i] ^= digest[i];
opad[i] ^= digest[i];
}
sha256_starts(&sha_ctx);
sha256_update(&sha_ctx, ipad, 64);
// Encrypt the IV and key used to encrypt the plaintext file,
// writing that encrypted text to the output file.
for(i=0; i<48; i+=16)
{
// Place the next 16 octets of IV and key buffer into
// the input buffer.
memcpy(buffer, iv_key+i, 16);
// XOR plain text block with previous encrypted
// output (i.e., use CBC)
for(j=0; j<16; j++)
{
buffer[j] ^= IV[j];
}
// Encrypt the contents of the buffer
aes_encrypt(&aes_ctx, buffer, buffer);
// Concatenate the "text" as we compute the HMAC
sha256_update(&sha_ctx, buffer, 16);
// Write the encrypted block
result_code = out_buffered_file.WriteFile(
buffer,
16,
&bytes_written);
if (result_code != ERROR_SUCCESS)
{
throw SystemErrorException(
_T("Unable to write to ") +
out_file,
result_code);
}
// Update the IV (CBC mode)
memcpy(IV, buffer, 16);
}
// Write the HMAC
sha256_finish(&sha_ctx, digest);
sha256_starts(&sha_ctx);
sha256_update(&sha_ctx, opad, 64);
sha256_update(&sha_ctx, digest, 32);
sha256_finish(&sha_ctx, digest);
result_code = out_buffered_file.WriteFile(
digest,
32,
&bytes_written);
if (result_code != ERROR_SUCCESS)
{
throw SystemErrorException(
_T("Unable to write to ") +
out_file,
result_code);
}
// Re-load the IV and encryption key with the IV and
// key to now encrypt the datafile. Also, reset the HMAC
// computation.
memcpy(IV, iv_key, 16);
// Because the aes_set_key routine is not thread safe,
// protect it with a critical section.
EnterCriticalSection(&Critical_Section);
aes_set_key(&aes_ctx, iv_key+16, 256);
LeaveCriticalSection(&Critical_Section);
// Set the ipad and opad arrays with values as
// per RFC 2104 (HMAC). HMAC is defined as
// H(K XOR opad, H(K XOR ipad, text))
memset(ipad, 0x36, 64);
memset(opad, 0x5C, 64);
for(i=0; i<32; i++)
{
ipad[i] ^= iv_key[i+16];
opad[i] ^= iv_key[i+16];
}
// Wipe the IV and encryption mey from memory
memset(iv_key, 0, 48);
sha256_starts(&sha_ctx);
sha256_update(&sha_ctx, ipad, 64);
last_clock_time = clock();
current_percent = 0;
bytes_left = file_size.QuadPart;
while(bytes_left > 0)
{
n = (bytes_left > 16) ? 16 : (int) bytes_left;
bytes_left -= n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -