2

I have this Python decryption function which I am trying to convert to Delphi.

It uses AES CFB mode:

def aes_decrypt(data,key,iv):
    ctx = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128)
    decrypted = ctx.decrypt(data)
    return decrypted

I am using Dcpcrypt in Delphi 7. // key is Md5 hash (this key/IV is just example not exact)

const
  Key = 'c143vvssaaea933f04e956a3ff5vb562'; 
  iv = 'r4022f4577726207fy0etf4fate2gd44';
    
function aes_decrypt(Data: TBytes; key,iv: string): TBytes;
var
  Cipher: TDCP_rijndael;
  InStrm, OutStrm: TMemoryStream;
begin
  InStrm := TMemoryStream.Create;
  OutStrm := TMemoryStream.Create;
  InStrm.Write(Data[0], Length(Data));
  Cipher := TDCP_rijndael.Create(nil);
  Cipher.BlockSize:=128;
  Cipher.CipherMode:=cmCFB8bit;
  Cipher.Init(Key, 128, @IV);
  Cipher.DecryptStream(InStrm, OutStrm, OutStrm.Size);
  SetLength(Result, Integer(OutStrm.size));
  OutStrm.Seek(0, 0);
  OutStrm.Read(Result[0], Length(Result));
  OutStrm.SaveToFile('decbuf.bin');
  InStrm.Free;
  OutStrm.Free;
  Cipher.Free;
end;

I am getting incorrect output with the Delphi code; the Python function is returning the expected output.

The segment_size

segment_size (integer) – (Only MODE_CFB).The number of bits the plaintext and ciphertext are segmented in. It must be a multiple of 8. If not specified, it will be assumed to be 8.

does this apply in Delphi Dcpcrypt ?

Maaz
  • 131
  • 8
  • You must protect your objects with `try..finally` blocks (but maybe you would have done that in a real application). – Andreas Rejbrand Aug 29 '20 at 16:10
  • Yes offcourse, this is just quick test to get some help here – Maaz Aug 29 '20 at 16:28
  • function aes_decrypt(Data: TBytes; key,iv: string; segment_size : Integer = 128): TBytes; – fpiette Aug 29 '20 at 18:31
  • @fpiette could you post full function so i can test ? – Maaz Aug 29 '20 at 19:11
  • The version of DCPcrypt matters. Are you sure about your key? It should have a length of 16, not 32. Looks like it was once a hash and you censored parts of it for us with non-hexadecimal characters. Consider using `Key= #$c1#$43#$vv#$ss...` and same for IV. – AmigoJack Aug 29 '20 at 19:12
  • @Maaz I just shown you how to define an optional argument. I have no idea about how the function has to be implemented. IMO I have answered the question you asked: "How can I put segment_size in a Delphi function?" – fpiette Aug 29 '20 at 19:22
  • @amigojack key Length is 32 and yes key is hex md5 checksum same with IV Version of DcpCrypt matters ? Can you tell more about it please also Cipher mode is it correct ? – Maaz Aug 29 '20 at 19:23
  • Yes my bad I didn't clarify enough in my question about actual implementation – Maaz Aug 29 '20 at 19:26
  • After some search online i found this about "segment_size (integer) – (Only MODE_CFB).The number of bits the plaintext and ciphertext are segmented in. It must be a multiple of 8. If not specified, it will be assumed to be 8." Does this apply in DcpCrypt also ? – Maaz Aug 29 '20 at 19:27

1 Answers1

4

I don't know Python and can only assume OP is importing PyCrypto, but the manual's first example shows and explains what I suspected:

key = b'Sixteen byte key'
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CFB, iv)

Both key and iv are in bytes, not a string. It even literally says "Sixteen byte key", not "32 character hash string". And the b right before the literal is not there for fun either. But in your Pascal code you're handing over text, which surprisingly is double the size of 16 byte, and also (almost) only makes use of hexadecimal digits. But you should provide full bytes instead of their hexadecimal representation. The correct code would be:

const
  // v, s, r, t and g are invalid digits, of course
  Key= #$c1#$43#$vv#$ss#$aa#$ea#$93#$3f#$04#$e9#$56#$a3#$ff#$5v#$b5#$62;
  iv= #$r4#$02#$2f#$45#$77#$72#$62#$07#$fy#$0e#$tf#$4f#$at#$e2#$gd#$44;

// Last parameter is optional, just like you wanted it. Credits: fpiette
function aes_decrypt( Data: TBytes; key, iv: String; segment_size: Integer= 128 ): TBytes;

You have to find out the rest yourself. The comments been given to you barely made you progress. DCPcrypt (just like any software/library) exists in different versions, which differ in details - since nobody knows which one you are using nobody can halfway pinpoint a potential mistake you make. Same goes for PyCrypto. If you would have offered right away

  • an uncensored correct key,
  • an uncensored correct initialization vector,
  • the encrypted data, and
  • the correctly decrypted data

then it would be much simpler. Otherwise you might wait forever until someone shows up who can execute both ends (Python X and Delphi 7). Consider changing your question drastically and provide more details.

AmigoJack
  • 5,234
  • 1
  • 15
  • 31