DelphiXe4。使用WinCryptoApi加密 - 解密功能文件。加密模式CBC。它似乎工作。加密和解密。
// get winapi functions - http://msdn.microsoft.com/en-us/library/ms936171.aspx and ect..
procedure GuCryptFile(const SourceFileName, DestinationFileName, Password: tGuString; ToCrypt: TGuBoolean);
var
hProv, hKey, hHashP: TGuUlong;
Buffer: TguPByte;
len, aBufLen, CGuSoC, Mode, padMode: TGuDWord;
fsIn, fsOut: TGuStreamF;
k: TGuBoolean;
begin
CGuSoC:=SizeOf(TGuChar);hProv := 0;k := false; aBufLen := 0;
if not GuCryptAcquireContext(@hProv, nil, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, // Init crypto provider
CRYPT_VERIFYCONTEXT) then
MessageBox(0, 'Not CAC', 0, 0);
if not GuCryptCreateHash(hProv, CALG_MD2{MD5, SHA}, 0, 0, @hHashP) then // Create Hash
MessageBox(0, 'Not CCH', 0, 0);
if not GuCryptHashData(hHashP, @Password[1], Length(Password) * CGuSoC, 0) then // Get Hash
MessageBox(0, 'Not CHD', 0, 0);
if not GuCryptDeriveKey(hProv, CALG_RC4{RC2, AES}, hHashP, 0, @hKey) then // Init Key
MessageBox(0, 'Not CDK', 0, 0);
if not GuCryptDestroyHash(hHashP) then // Kill Hash
MessageBox(0, 'Not CDH', 0, 0);
// MessageBox(0, PChar(IntToStr(hprov)), 0, 0);
Mode := CRYPT_MODE_CBC;
if not GuCryptSetKeyParam(hKey, KP_MODE, @Mode, 0) then // Set CBC crypto mode
MessageBox(0, 'Not SKP', 0, 0);
if Mode <> CRYPT_MODE_CBC then // Check CBC mode
MessageBox(0, 'Not mCBC', 0, 0);
padMode := PKCS5_PADDING;
if not GuCryptSetKeyParam(hKey, KP_PADDING, @padMode, 0) then // Add PAdding
MessageBox(0, 'Not mPAD', 0, 0);
if not FileExists(SourceFileName) then
MessageBox(0, 'FNF', 0, 0);
if FileExists(DestinationFileName) then // Check files
DeleteFile(PChar(DestinationFileName));
if tocrypt then
if not GuCryptEncrypt(hKey, hHashP, true, 0, Nil, @aBufLen, 0) then // Get buflen if crypto mode
MessageBox(0, 'Not GBL', 0, 0);
fsIn := TFileStream.Create(SourceFileName, fmOpenRead); // open file for read
fsOut := TFileStream.Create(DestinationFileName, fmCreate); // open file for write
GetMem(Buffer, 512 + aBufLen); // get memory for buffer
repeat
len := fsIn.Read(Buffer^, 512); // read buffer
if len <> 512 then // check last bufffer
k := True;
if ToCrypt then
guCryptEncrypt(hkey, 0, k, 0, Buffer, @len, len + aBufLen) // crypt
else
guCryptDecrypt(hkey, 0, k, 0, Buffer, @len); // decrypt
fsOut.Write(Buffer^, len); // write buffer
until len <> 512; // check EOF
FreeMem(Buffer, 512+aBufLen); // free memory
fsIn.Free; // close file
fsOut.Free; // close file
if not GuCryptDestroyKey(hKey) then // kill key
MessageBox(0, 'Not CDK', 0, 0);
if hProv <> 0 then
if not GuCryptReleaseContext(hProv, 0) then // kill prov
MessageBox(0, 'Not CRC', 0, 0);
end;
使用
procedure TForm1.ButtonCryptClick(Sender: TObject);
begin
GuCryptFile('d:\1.txt', 'd:\1.xxx', 'mama mila ramu', True); // crypt file
end;
procedure TForm1.ButtonDeCryptClick(Sender: TObject);
begin
GuCryptFile('d:\1.xxx', 'd:\11.txt', 'mama mila ramu', False); // decrypt file
end;
问题:
现在(红色方块 - 坏字节):
必须:
它应该是哪种方式?
抱歉英语不好。
答案 0 :(得分:1)
如果在解密之前在CBC模式下更改单个块,则完全更改同一位置的纯文本块。此外,下一个块稍有改变:在块中的相同位置,XOR将导致一些损坏。 CBC模式在这方面恢复得非常快。
单个块加密或解密块密码将始终产生明文。基本上,分组密码是PRP,伪随机置换。因此,在加密期间,单个块明文被置换为单个块密文。当然,在解密期间,单个块密文被置换为单个块明文。
如果在加密或解密函数的输入中更改1位,则基本上所有位都具有与预期输出完全无关的值。但是,没有失败的块加密这样的事情。所有数值均可接受。如果您希望解密失败,则需要添加身份验证标记(例如,使用HMAC或GCM模式加密)。然后,由于身份验证失败,解密将失败。