You are not logged in.
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 ), can someone show me a good example?
thanks!
Last edited by der.Christoph (2020-06-29 13:12:33)
Offline
Found what i need: https://synopse.info/forum/viewtopic.php?id=3395
Thank You!
Offline
I have a solution and wanted to share it with you, maybe someone can tell me if I did everything right )
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
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
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
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
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
Then how do I get the IV back in C#?
Are those the first 16 bytes there as well?
Offline
Yes they are....
Thank you!
Offline
Check this one...AES Encryption In C#
Offline