0

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;

问题:

  1. 据我了解,涉及 CBC 模式对上一个块的下一个块的依赖。测试 CBC:我加密文件 1.txt (20 Kb),得到 1.xxx。文件 1.xxx 在 HEX 编辑器中打开并将其更改为 1 个随机字节。解密1.xxx,得到11.txt。比较文件:“Fc / b 1.txt 11.txt”(或只是视觉上)。我看到发生在 11.txt 中的文字记录只在 1.txt 中更改者的大致位置更改了几个字节。按照规矩以后的地方我不应该全部抄录。正确的?特别是安装CBC模式并检查它,即使描述说它是默认安装的。错误在哪里?

现在(红色方块 - 坏字节):

在此处输入图像描述

必须:

在此处输入图像描述

无论哪种方式都应该是?

对不起英语不好。

4

1 回答 1

1

如果在解密之前在 CBC 模式下更改单个块,则同一位置的纯文本块将完全更改。此外,下一个块略有变化:在块中的相同位置,异或将导致一些损坏。在这方面,CBC 模式会很快恢复。

在此处输入图像描述

分组密码的单个分组加密或解密将始终产生明文。基本上,分组密码是 PRP,一种伪随机排列。因此,在加密期间将单个块明文置换为单个块密文。当然,在解密过程中,单个块密文被置换为单个块明文。

如果您在加密或解密函数的输入中更改 1 位,则基本上所有位都具有与预期输出完全无关的值。但是,没有失败的块加密这样的事情。所有值都是可接受的。如果您希望解密失败,您需要添加一个身份验证标签(例如使用 HMAC 或 GCM 模式加密)。然后解密将由于身份验证失败而失败。

于 2013-07-11T17:49:11.420 回答