Question

DelphiXe4. Encryption-decryption function file with WinCryptoApi. Encryption mode CBC. It seems to be working. Encrypts and decrypts.

// 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;

Use

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;

Questions:

  1. As far as I understand it, involves the dependence of the CBC mode the next block from previous one. Test CBC: I encrypt file 1.txt (20 Kb), get 1.xxx. File 1.xxx open in HEX-editor and change it to 1 random byte. Decrypt 1.xxx, get 11.txt. Compare files: "Fc / b 1.txt 11.txt" (or just visually). I see that the transcript occurred in 11.txt changed only a few bytes in roughly the spot where changers in 1.txt. According to the rules after the place where I should not all transcribed. Right? Especially install CBC mode and check it out, even though the description says that it is installed by default. Where is the mistake?

Now (Red squares - bad bytes):

enter image description here

Must:

enter image description here

Either way it should be?

Sorry for the bad English.

Was it helpful?

Solution

If you change a single block in CBC mode before decryption then the plain text block at the same location is completely changed. Furthermore, the next block is changed slightly: at the same location in the block the XOR will result in a bit of corruption. CBC mode restores itself pretty quickly in this regard.

enter image description here

A single block encrypt or decrypt of a block cipher will always result in plaintext. Basically, a block cipher is a PRP, a pseudo-random permutation. So a single block plaintext is permuted to a single block ciphertext during encryption. And, of course, a single block ciphertext is permuted to a single block plaintext during decryption.

If you change 1 bit in the input of the encryption or decryption functions than basically all bits have a value that is completely unrelated to the expected output. However, there is no such thing as a failed block encrypt. All values are acceptable. If you want decryption to fail, you need to add an authentication tag (e.g. using HMAC or GCM mode encryption). Then the decryption will fail because of an authentication failure.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top