You are not logged in.
Pages: 1
Hi,
I created the following Base64 string with C#
4XoaSLUowvAbRZl76s053aRzoWrMpxqayzBOk/syjdQ=
With the following settings:
Key Size: 256 bits / 32 bytes
Cipher Mode: CBC
Padding: PKCS#7
Initialization Vector: 16 byte
And the IV is at the beginning of the data.
The content is Hallo and the password was also Hallo.
So I try to do this in Delphi:
procedure TTest.DecryptEigenschaften(cryptedString: string);
var
AES: TAESCBC;
sha: TSHA256Digest;
InBytes, OutBytes: TBytes;
s: string;
begin
InBytes := TNetEncoding.Base64.DecodeStringToBytes(cryptedString);
sha := SHA256Digest(UTF8Encode('Hallo'));
AES := TAESCBC.Create(sha, 256);
try
OutBytes := AES.DecryptPKCS7(InBytes, True);
s := TNetEncoding.Base64.EncodeBytesToString(OutBytes);
finally
FreeAndNil(AES);
end;
end;
But I got, invalid data. What to do?
Offline
Could be useful to show the C# code too of how you encrypted this.
How did you pad the key in C#, with spaces? With #0? etc
The problem is that during decryption the last byte (which should contain the padding) is larger than the sizeof(TAESBlock).
Key should also be exactly 32 bytes (or padding to that number should be the same on both ends).
Offline
This is the C# code.
public string Encrypt(string value, string password)
{
var rngCryptoServiceProvider = new RNGCryptoServiceProvider();
// password
var passwordBytes = Encoding.UTF8.GetBytes(password);
// iv
var iv = new byte[16];
rngCryptoServiceProvider.GetNonZeroBytes(iv);
// salt erstellen
var salt = Encoding.UTF8.GetBytes(password);
var sha1 = HashAlgorithm.Create("SHA1");
salt = Enumerable.Range(0, Iterations).Aggregate(salt, (current, i) => sha1.ComputeHash(current));
var passwordDeriveBytes = new Rfc2898DeriveBytes(passwordBytes, salt, Iterations);
using (var aesManaged = new AesManaged())
{
var keyBytes = passwordDeriveBytes.GetBytes(KeySize / 8);
aesManaged.Mode = CipherMode.CBC;
aesManaged.Padding = PaddingMode.PKCS7;
byte[] encrypted;
using (var encryptor = aesManaged.CreateEncryptor(keyBytes, iv))
using (var toMemoryStream = new MemoryStream())
using (var writer = new CryptoStream(toMemoryStream, encryptor, CryptoStreamMode.Write))
{
var valueBytes = Encoding.UTF8.GetBytes(value);
writer.Write(valueBytes, 0, valueBytes.Length);
writer.FlushFinalBlock();
encrypted = new byte[16 + toMemoryStream.Length];
iv.CopyTo(encrypted, 0);
toMemoryStream.ToArray().CopyTo(encrypted, 16);
}
aesManaged.Clear();
return Convert.ToBase64String(encrypted);
}
}
Offline
You're using SHA1 in C# and SHA256 in Delphi. Try to change C# to same. Note that TAESCBC doesn't support SHA1.
Offline
You also use Rfc2898DeriveBytes to get a hash of the password.
In Delphi you use the same password as exact key (which is not the same as the passwordDeriveBytes password hash).
https://9to5answer.com/why-do-i-need-to … -key-or-iv
Rfc2898DeriveBytes is an implementation of PBKDF2. What it does is repeatedly hash the user password along with the salt.
You could look at the function PBKDF2_HMAC_SHA256 after you translated the C# to SHA256 (but I'm not sure if they give the exact same result).
You could also just try to use a exact 32 bytes key in your C# code which is the same as in Delphi (without the Rfc2898DeriveBytes step).
Offline
You also use Rfc2898DeriveBytes to get a hash of the password.
In Delphi you use the same password as exact key (which is not the same as the passwordDeriveBytes password hash).
https://9to5answer.com/why-do-i-need-to … -key-or-ivRfc2898DeriveBytes is an implementation of PBKDF2. What it does is repeatedly hash the user password along with the salt.
You could look at the function PBKDF2_HMAC_SHA256 after you translated the C# to SHA256 (but I'm not sure if they give the exact same result).
You could also just try to use a exact 32 bytes key in your C# code which is the same as in Delphi (without the Rfc2898DeriveBytes step).
Thanks! I will try it.
Offline
Hi,
so I changed my C# code to
var rngCryptoServiceProvider = new RNGCryptoServiceProvider();
// iv
var iv = new byte[16];
rngCryptoServiceProvider.GetNonZeroBytes(iv);
var key64 = "TW4YnFfPEhLeehtwdEAZyJYg/zYxeeaDjlhKIifwGKI=";
using (var aesManaged = new AesManaged())
{
var keyBytes = Convert.FromBase64String(key64);
aesManaged.Mode = CipherMode.CBC;
aesManaged.Padding = PaddingMode.PKCS7;
byte[] encrypted;
using (var encryptor = aesManaged.CreateEncryptor(keyBytes, iv))
using (var toMemoryStream = new MemoryStream())
using (var writer = new CryptoStream(toMemoryStream, encryptor, CryptoStreamMode.Write))
{
var valueBytes = Encoding.UTF8.GetBytes(value);
writer.Write(valueBytes, 0, valueBytes.Length);
writer.FlushFinalBlock();
encrypted = new byte[16 + toMemoryStream.Length];
iv.CopyTo(encrypted, 0);
toMemoryStream.ToArray().CopyTo(encrypted, 16);
}
aesManaged.Clear();
return Convert.ToBase64String(encrypted);
}
And give the same key and the result (WKaCNKYZpF9tb/CLp8fW/mX4r95OfjztavXhycsgDpA=) to Delphi
procedure TTest.DecryptEigenschaften(cryptedString: string);
var
AES: TAESCBC;
sha: TSHA256Digest;
InBytes, OutBytes, Key: TBytes;
s: string;
begin
InBytes := TNetEncoding.Base64.DecodeStringToBytes(cryptedString);
// sha := TNetEncoding.Base64.DecodeStringToBytes(cryptedString);
Key := TNetEncoding.Base64.DecodeStringToBytes('TW4YnFfPEhLeehtwdEAZyJYg/zYxeeaDjlhKIifwGKI=');
AES := TAESCBC.Create(key, 256);
try
OutBytes := AES.DecryptPKCS7(InBytes, True);
s := TNetEncoding.Base64.EncodeBytesToString(OutBytes);
finally
FreeAndNil(AES);
end;
end;
But still get the same error.
Offline
This is a simple Enc/Decrypt for AESCBC, try to replicate it in C#.
var
Temp: RawByteString;
begin
Temp := BinToBase64(TAESCBC.SimpleEncrypt('Lorem ipsum dolor sit amet, con', '123456', True, True));
WriteLn(Temp);
Temp := TAESCBC.SimpleEncrypt(Base64ToBin(Temp), '123456', False, True, True);
WriteLn(Temp);
end;
Offline
I can confirm the C# code is correct (or at least I can decrypt it in FPC/DCPcrypt2).
uses DCPrijndael, DCPcrypt2, base64;
function myDecryptCBC: ansistring;
var
Cipher: TDCP_rijndael;
Data, DataString, Key, IV: ansistring;
begin
Data := DecodeStringBase64('WKaCNKYZpF9tb/CLp8fW/mX4r95OfjztavXhycsgDpA=');
Key := DecodeStringBase64('TW4YnFfPEhLeehtwdEAZyJYg/zYxeeaDjlhKIifwGKI=');
Assert(Length(Key) = 32);
IV := Copy(Data, 1, 16);
DataString := Copy(Data, 17);
Cipher := TDCP_rijndael.Create(nil);
Cipher.CipherMode := cmCBC;
Cipher.Init(Key[1], Length(Key) * 8, @IV[1]);
Cipher.DecryptCBC(DataString[1], DataString[1], Length(DataString));
// PKCS7, last char is #11 which results in 16 - 11 = 5, length of Hallo
DataString := Copy(DataString, 1, Length(DataString) - Ord(DataString[Length(DataString)]));
Result := DataString;
Cipher.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
S: ansistring;
begin
S := myDecryptCBC;
Memo1.Lines.Add(S);
end;
Gives result
Hallo
I'm not sure why TAESCBC gives another result.
Offline
Fixed it. Here the solution for Delphi/TAESCBC.
(pass Key[0] to Create and no need to base-encode the result)
procedure TForm1.Button1Click(Sender: TObject);
const
cryptedString: string = 'WKaCNKYZpF9tb/CLp8fW/mX4r95OfjztavXhycsgDpA=';
keystring: string = 'TW4YnFfPEhLeehtwdEAZyJYg/zYxeeaDjlhKIifwGKI=';
var
AES: TAESCBC;
InBytes, OutBytes, Key: TBytes;
S: ANSIstring;
begin
InBytes := TNetEncoding.Base64.DecodeStringToBytes(cryptedString);
Key := TNetEncoding.Base64.DecodeStringToBytes(keystring);
AES := TAESCBC.Create(Key[0], 256); // Pass the string, not the pointer to string
try
OutBytes := AES.DecryptPKCS7(InBytes, True);
S := TEncoding.ANSI.GetString(OutBytes); // No need to base64 encode again
Memo1.Lines.Add(S);
finally
FreeAndNil(AES);
end;
end;
Result:
Hallo
Last edited by rvk (2022-05-31 09:05:28)
Offline
Pages: 1