Question

I have an IV (initialization vector) and key, i need to cypher a string this is the code:

function TForm1.CipherAES (key: AnsiString; Vector: AnsiString;
  InStream: TMemoryStream) : TMemoryStream;
var
  cipher: TDCP_rijndael;
  i: integer;
  toEnc, toSnd : array of byte;
  outStream, AStream :TMemoryStream;
  StreamR, Stream2 : AnsiString;
begin
  outStream := TMemoryStream.Create;
  SetLength(toEnc, InStream.Size);

  cipher := TDCP_rijndael.Create(nil);
  cipher.Init(key[1], 128, nil);
  cipher.SetIV(vector[1]);
  cipher.BlockSize := 16;
  InStream.Position := 0;

  for I := 0 to InStream.Size-1 do
    InStream.Read(ToEnc[i], 1);

  for I := 0 to inStream.size-1 do
    StreamR := StreamR + ByteToHex(toEnc[i]) + ' ';
  Memo1.Lines.Add(StreamR);
  inStream.Position := 0;

  cipher.CipherMode := cmCBC;
  cipher.EncryptStream(inStream, outStream, InStream.Size);
  Base64Encode(outStream.Memory, @StreamR[1], outStream.Size);

  Stream2 := Copy(StreamR, 1, outStream.Size + 8);
  Memo1.Lines.Add(Stream2);
  Memo1.Lines.Add(StreamR);

  outStream.Position := 0;

  SetLength(toSnd, outStream.Size);
  for I := 0 to outStream.Size-1 do
    outStream.Read(toSnd[i], 1);

  StreamR := '';
  for I := 0 to outStream.size-1 do
    StreamR := StreamR + ByteToHex(toSnd[i]) + ' ';
  Memo1.Lines.Add(StreamR);

  cipher.burn;
  cipher.free;

  Result := outStream;
end;

when i pass the stream to base64 gives me the next answer:

ub/JkCsCZwbAnyqjo+miIw==

but it should be:

ub/JkCsCZwbAnyqjo+miI2XNZwNrJo31YBNTwQuHkq0=

somebody can help me? why is something like this happening?

thanks in advance Vauli

Was it helpful?

Solution

If you base64 decode these two values you will get:

ub/JkCsCZwbAnyqjo+miIw== decodes to:

B9 BF C9 90 2B 02 67 06-C0 9F 2A A3 A3 E9 A2 23 (in hex) 

=> 16 bytes

ub/JkCsCZwbAnyqjo+miI2XNZwNrJo31YBNTwQuHkq0= decodes to:

B9 BF C9 90 2B 02 67 06-C0 9F 2A A3 A3 E9 A2 23
65 CD 67 03 6B 26 8D F5-60 13 53 C1 0B 87 92 AD (in hex) 

=> 32 bytes

This makes me think you are passing only 16 bytes to TForm1.CipherAES(). I'm saying that, because after calling cipher.EncryptStream, outStream.size should be equal to inStream.size

Please clarify what is the value for InStream.Size when you test using breakpoints.

Some notes on your code:

  1. Base64Encode returns the number of bytes that output buffer contain. You never use this value to set the size of StreamR.

    Your call to base64encode should be something like:

    // Allocate buffer for base64 decoded data
    setLength(StreamR, ((inStrem.size + 2) div 3) * 4); 
    size := Base64Encode(outStream.Memory, @StreamR[1], outStream.Size);
    setLength(StreamR, size);
    
  2. I really do not get the meaning of this:

    Stream2 := Copy(StreamR, 1, outStream.Size + 8);

    Why outStream.Size + 8? You are copying something from StreamR, based on a size of other buffer, disregarding the real size of your StreamR? Also "Copy()" will get only at most LENGTH(StreamR) chars.

  3. Instead of filling ToEnc byte by byte consider using:

    InStream.ReadBuffer(ToEnc[0], InStream.size);

    The same for toSnd (but .writeBuffer())


Note about encrypting strings (because I don't know how you feed InStream):

Ensure you're encrypting Unicode version of the text (UTF16-LE or UTF-8). Converting string to ansiString goes via OS system locale and can result in data loss (the famous '????')

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