Title: to crypt/decrypt the file using Crypt API
Question: How can I crypt/decrypt the file in Crypt API?
Answer:
Hello,
in last time I worked a lot with crypt algorithmes and today I want to post the new tip with sample code where I'll show how you may crypt and decrypt any file using standard Crypt API which is available in MS Windows.
The standard task is to encrypt the file content using some password. And as result, the encrypted file nobody can decrypt if he/she don't provide the valid password.
The code below allow to solve this task:
procedure CryptFile(const SourceFileName, DestinationFileName, Password: string; ToCrypt: Boolean);
var
hProv: HCRYPTPROV;
hash: HCRYPTHASH;
key: HCRYPTKEY;
Buffer: PByte;
len: dWord;
fsIn, fsOut: TFileStream;
IsEndOfFile: Boolean;
begin
{get context for crypt default provider}
CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
{create hash-object (SHA algorithm)}
CryptCreateHash(hProv, CALG_SHA, 0, 0, @hash);
{get hash from password}
CryptHashData(hash, @Password[1], Length(Password), 0);
{create key from hash by RC4 algorithm}
CryptDeriveKey(hProv, CALG_RC4, hash, 0, @key);
{destroy hash-object}
CryptDestroyHash(hash);
{open source+destination files}
fsIn := TFileStream.Create(SourceFileName, fmOpenRead or fmShareDenyWrite);
fsOut := TFileStream.Create(DestinationFileName, fmCreate);
try
{allocate buffer to read content from source file}
GetMem(Buffer, 512);
repeat
IsEndOfFile := (fsIn.Position = fsIn.Size);
if IsEndOfFile then break;
{read content from source file}
len := fsIn.Read(Buffer^, 512);
if ToCrypt then
{crypt buffer}
CryptEncrypt(key, 0, IsEndOfFile, 0, Buffer, @len, len)
else
{decrypt buffer}
CryptDecrypt(key, 0, IsEndOfFile, 0, Buffer, @len);
{write changed buffer to destination file}
fsOut.Write(Buffer^, len)
until IsEndOfFile;
{release memory allocated for buffer}
FreeMem(Buffer, 512);
finally
fsIn.Free;
fsOut.Free;
end;
{release the context for crypt default provider}
CryptReleaseContext(hProv, 0);
end;
And sample to use:
- to encrypt file:
CryptFile('c:\datafile.txt', 'd:\encrypted.dat', 'peter', True);
- to decrypt file
CryptFile('d:\encrypted.dat', 'c:\datafile.txt', 'peter', False);
Of course, you may change the code above to accept the any streams (not only file streams) and/or to use another algorithmes.
PS: please note to compile the code above you need header files for Crypt API. for example, you may use the wcrypt2.pas unit which is available at ftp://ftp.delphi-jedi.org/api/CryptoAPI2.zip