#1 2020-06-29 13:03:35

der.Christoph
Member
Registered: 2018-08-13
Posts: 7

SynCrypto Example: Encrypt in Delphi Decrypt in C#

I am looking for a working example to encrypt strings (or streams) in Delphi and decrypt them in C#.

I'm new to crypto and would be happy if it works in C# without any additional components.
the example is about stability. It would be good if somebody can name a SynCrypto function and all related encryption parameters, bit length, cypher modes and everything else you need ....

And then the appropriate C# code yikes), can someone show me a good example?


thanks!

Last edited by der.Christoph (2020-06-29 13:12:33)

Offline

#2 2020-06-29 13:47:49

der.Christoph
Member
Registered: 2018-08-13
Posts: 7

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

Offline

#3 2020-06-30 08:30:25

der.Christoph
Member
Registered: 2018-08-13
Posts: 7

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

I have a solution and wanted to share it with you, maybe someone can tell me if I did everything right yikes)

Delphi Code

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, SynCripto, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    GridPanel1: TGridPanel;
    mmoInput: TMemo;
    mmoOutput: TMemo;
    btnEncrypt: TButton;
    btnDecrypt: TButton;
    procedure btnEncryptClick(Sender: TObject);
    procedure btnDecryptClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  KeyStr: AnsiString;
  Key: TSHA256Digest;
  IVStr: AnsiString;
  IV: TAESBlock;

  Form1: TForm1;

implementation

uses
  System.NetEncoding,
  System.IOUtils;

{$R *.dfm}

procedure TForm1.btnEncryptClick(Sender: TObject);
var
  AES: TAESCBC;
  InBytes, OutBytes: TBytes;
begin
  KeyStr := '6078C40F64D3516E9294D9C3D4D45D80';
  IVStr := '9978B3B4893D00EC';
  CopyMemory(@Key, @KeyStr[1], 32);
  CopyMemory(@IV, @IVStr[1], 16);


  InBytes := TEncoding.Unicode.GetBytes(mmoInput.Lines.Text);

  AES := TAESCBC.Create(Key, 256);
  try
    AES.IV := IV;
    OutBytes := AES.EncryptPKCS7(InBytes, False);
  finally
    FreeAndNil(AES);
  end;

  mmoOutput.Lines.Text := TNetEncoding.Base64.EncodeBytesToString(OutBytes);
end;

procedure TForm1.btnDecryptClick(Sender: TObject);
var
  AES: TAESCBC;
  InBytes, OutBytes: TBytes;
begin
  KeyStr := '6078C40F64D3516E9294D9C3D4D45D80';
  IVStr := '9978B3B4893D00EC';
  CopyMemory(@Key, @KeyStr[1], 32);
  CopyMemory(@IV, @IVStr[1], 16);

  InBytes := TNetEncoding.Base64.DecodeStringToBytes(mmoOutput.Lines.Text);

  AES := TAESCBC.Create(Key, 256);
  try
    AES.IV := IV;
    OutBytes := AES.DecryptPKCS7(InBytes, False);
  finally
    FreeAndNil(AES);
  end;

  mmoInput.Lines.Text := TEncoding.Unicode.GetString(OutBytes);
end;

end.

C# Code to Decrypt:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace AES_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            string soutput = "";
            AESDecryptBase64String("ZdBFopJw0o80ESiSUyKG2aaxyK6AU40yYzzmPZ2tmYHN6WWQUQgrYxw3BI7LWtPk5Lc06qvnshSGibiVZ2ig7w==", out soutput);
            Console.WriteLine(soutput);
            Console.ReadLine();
        }
        public static Stream GenerateStreamFromString(string s)
        {
            var stream = new MemoryStream();
            var writer = new StreamWriter(stream);
            writer.Write(s);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }
        static public void AESDecryptBase64String(string input, out string output)
        {
            MemoryStream inputStream = null;
            Stream outputStream = null;
            CryptoStream cryptoStream = null;
            output = "";

            try
            {
                byte[] key = Encoding.ASCII.GetBytes("6078C40F64D3516E9294D9C3D4D45D80");
                byte[] vec = Encoding.ASCII.GetBytes("9978B3B4893D00EC");

                outputStream = GenerateStreamFromString(output);

                AesManaged aesCrypto = new AesManaged();
                aesCrypto.BlockSize = 8 * 16;
                aesCrypto.KeySize = 8 * 32;
                aesCrypto.Padding = PaddingMode.PKCS7;
                aesCrypto.Mode = CipherMode.CBC;
                aesCrypto.IV = vec;

                cryptoStream = new CryptoStream(outputStream, aesCrypto.CreateDecryptor(key, vec), CryptoStreamMode.Write);
                inputStream = new MemoryStream(Convert.FromBase64String(input));

                int length;
                byte[] buffer = new byte[16];

                while ((length = inputStream.Read(buffer, 0, 16)) != 0)
                {
                    cryptoStream.Write(buffer, 0, length);
                }
                cryptoStream.FlushFinalBlock();
                outputStream.Position = 0;
                StreamReader reader = new StreamReader(outputStream, Encoding.Unicode);
                output = reader.ReadToEnd();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                if (cryptoStream != null)
                {
                    cryptoStream.Close();
                }

                if (outputStream != null)
                {
                    outputStream.Close();
                }

                if (inputStream != null)
                {
                    inputStream.Close();
                }
            }
        }

    }
}

the line cryptoStream.FlushFinalBlock(); is very important, because otherwise partly (I think depending on the length of the data) not everything was decrypted back.

Offline

#4 2020-06-30 09:08:19

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,203
Website

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

1. Please follow the forum rules and don't post such pieces of code directly in the forum.

2. Ensure your IV is not fixed, and is random (or at least genuine) for each encryption.

Offline

#5 2020-06-30 09:28:38

der.Christoph
Member
Registered: 2018-08-13
Posts: 7

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

ok, I will in the future. I have read up a little on the topic initialization vector.

Would it be ok if I used a hash over the data itself as IV?

Offline

#6 2020-06-30 09:58:11

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,203
Website

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

Which data?
You can't hash the unciphered data before uncrypting it, and you can't hash the ciphered data before crypting it...

No, the IV could be
- either transmitted with the encrypted content, e.g. as a random initial block - if the content could be duplicated (as with encryption file on disk)
- or derivated from an ephemerous asymetrical key (which may be from a master key with a proven hash reduction function) if the content is not to be duplicated (as with encryption on network stream)

Don't mess with encryption algorithms, unless you know what you are doing - even after decades working with encryption, and even been audited from security experts of (very) big companies, I still stick to the standards and try to follow advices e.g. from https://security.stackexchange.com/

For instance, I am sure that using the hash of the unciphered data as IV, which may be transmitted with the encrypted stream - also used to verify the content after decryption - is not a good practice. The IV should be genuine and not tied to the data. By genuine, I mean that if you encrypt the same content twice, the encrypted content should be properly diverse. So the IV should be diverse. This is similar to perfect forward security IIRC.

Offline

#7 2020-06-30 12:53:54

der.Christoph
Member
Registered: 2018-08-13
Posts: 7

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

I customized it so that the IV is now randomly generated and appended before the Base64 encoding

  CopyMemory(@Key, @AKey[1], 32);
  CreateGUID(IVGUID);
  InBytes := TEncoding.Unicode.GetBytes(ASource);
  IvBytes := IVGUID.ToByteArray;

  Move(IvBytes[0], IV, 16);

.....

  Result := TNetEncoding.Base64.EncodeBytesToString(Concat(IvBytes, OutBytes));

In C# I do the same thing when compiling the streams:

                byte[] key = Encoding.ASCII.GetBytes(Key).Take(32).ToArray();
                byte[] vec = Convert.FromBase64String(input).Take(16).ToArray();
.....
                byte[] InfutData = Convert.FromBase64String(input).Skip(16).ToArray();
                inputStream = new MemoryStream(InfutData);

Thanks for clarifying, hope this is so common practice and safe?

Offline

#8 2020-06-30 13:06:18

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,203
Website

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

It is even safer if you use our built-in IV random generator by setting the optional IVAtBeginning parameter to TRUE.

Offline

#9 2020-06-30 13:08:55

der.Christoph
Member
Registered: 2018-08-13
Posts: 7

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

Then how do I get the IV back in C#?
Are those the first 16 bytes there as well?

Offline

#10 2020-06-30 13:15:04

der.Christoph
Member
Registered: 2018-08-13
Posts: 7

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

Yes they are....

Thank you!

Offline

#11 2023-09-25 05:16:57

berkninan
Member
Registered: 2023-09-25
Posts: 1

Re: SynCrypto Example: Encrypt in Delphi Decrypt in C#

Check this one...AES Encryption In C#

Offline

Board footer

Powered by FluxBB