Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replicate encryption algorithm

(I tried asking this on Cryptography Stack Exchange and they didn't feel it was appropriate there.)

I'm trying to replicate an algorithm written in Delphi in C#, preferably using the standard .NET libraries. Supposedly the Delphi algorithm passes standard reference tests. It's supposed to be AES/CBC; however, I've been unable to duplicate the results with System.Security.Cryptography.AesManaged.

Example of calling it with simple input:

function StringToHex(S: string): string;
var
  i: integer;
begin
  Result := '';
  for i := 1 to Length(S) do
    Result := Result + IntToHex(Ord(S[i]), 2);
end;

var
  PlainText:     AnsiString;
  AES:           TAES;
  Key:           TAESKey256;  // array[0..31] of byte;
  InitialVector: TAESBuffer;  // array[0..15] of byte;
  InputStream:   TStringStream;
  OutputStream:  TStringStream;

begin
  PlainText := 'test';
  FillChar(Key, SizeOf(Key), 1);
  FillChar(InitialVector, SizeOf(InitialVector), 2);

  AES          := TAES.Create;
  InputStream  := TStringStream.Create(PlainText);
  OutputStream := TStringStream.Create('');

  try
    AES.EncryptAESStreamCBC(InputStream, 0, Key, InitialVector, OutputStream);

    Writeln(StringToHex(OutputStream.DataString));
    Readln;
  finally
    InputStream.Free;
    OutputStream.Free;
    AES.Free;
  end;
end.

Output:

CEE3684F05D02E5A0930CED21F76075A

The code appears to have been based on the Delphi Spring Framework.

How can I replicate this in .NET?

What I've tried (even switching to bytes to avoid any Unicode issues):

public byte[] Encrypt()
{
    using (var algorithm = new AesManaged())
    {
        // Default is CBC
        algorithm.Key = Enumerable.Repeat((byte)0x01, 32).ToArray();
        algorithm.IV = Enumerable.Repeat((byte)0x02, 16).ToArray();

        using (ICryptoTransform encryptor = algorithm.CreateEncryptor(algorithm.Key, algorithm.IV))
        {
            using (var stream = new MemoryStream())
            {
                using (var cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
                {
                    using (var writer = new BinaryWriter(cryptoStream))
                    {
                        writer.Write(new byte[] {0x74, 0x65, 0x73, 0x74});
                    }
                    return stream.ToArray();
                }
            }
        }
    }
}

This results in different output, though (the first byte is x6D).

like image 798
TrueWill Avatar asked Feb 12 '23 22:02

TrueWill


2 Answers

In other task guy mentioned default settings for c#:

BlockSize = 128;
Mode = System.Security.Cryptography.CipherMode.CBC;
Padding = System.Security.Cryptography.PaddingMode.PKCS7

In Delphi i can't see any option to change PaddingMode and i guess it padds with zeros. If it is correct, then you should switch padding in C# to

System.Security.Cryptography.PaddingMode.Zeros

(sorry, can't check it, it is just assumption).

Update: As shunty mention, it works, just add line:

algorithm.Padding = PaddingMode.Zeros;
like image 151
Andrei Galatyn Avatar answered Feb 15 '23 11:02

Andrei Galatyn


If you want to use the facility by the Spring framework in Delphi my suggestion is to create a Win32 [Library] DLL using Delphi and consume that DLL inside your .NET application. That sounds like a more logical solution than rewriting the code in C#(reinventing the wheel?).

like image 25
MHOOS Avatar answered Feb 15 '23 11:02

MHOOS