TripleDES encryption in c# and php is not same - c#

PHP code
define('SECRET', 'Your key here');
$data = 'test';
$enc = mcrypt_cbc(MCRYPT_TRIPLEDES, SECRET, $data, MCRYPT_ENCRYPT, '12345678');
$url .= urlencode($password);
C# code
byte[] key = ec.GetBytes("Your key here");
byte[] iv = ec.GetBytes("12345678");
byte[] data = ec.GetBytes("test");
byte[] enc = new byte[0];
TripleDES tdes = TripleDES.Create();
tdes.IV = iv;
tdes.Key = key;
tdes.Mode = CipherMode.CBC;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform ict = tdes.CreateEncryptor();
enc = ict.TransformFinalBlock(data, 0, data.Length);
string szEnc = HttpContext.Current.Server.UrlEncode(
Encoding.ASCII.GetString(enc)
);
My problem: The value of $url in PHP and szEnc in c# is not same.
Question: what wrong in my c# code?

A lot of things can go wrong - but I've seen quite a lot of encoding (i.e. non cryptographic) issue when dealing with string and byte[].
Never assume they will convert into anything, including ASCII.
Encoding.ASCII.GetString(enc)
If you have unprintable characters, NUL... then this will not be part of the returned string and won't be url-encoded. This is ask true for PHP but it does not means it follows the same rule in every case.
Also I can't tell you what code like:
ec.GetBytes("Your key here");
will do ?!? If you're using an Unicode encoder then it won't give you the same as an ASCII encoder.
Beside encoding also check that the PaddingMode you use match the one used by PHP.

Related

Encrypt Decrypt in C# Decrypt is not working [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I had a java code and I had to transform it in C# which is as below
Encryption:
public String encrypt(String value)
{
System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
AesManaged tdes = new AesManaged();
tdes.Key = UTF8.GetBytes(securityKey);
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform crypt = tdes.CreateEncryptor();
byte[] plain = Encoding.UTF8.GetBytes(value);
byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length);
String encryptedText = Convert.ToBase64String(cipher);
return encryptedText;
}
Now I am trying to write the reversal process
public String decrypt(String value)
{
System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
AesManaged tdes = new AesManaged();
tdes.Key = UTF8.GetBytes(securityKey);
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform crypt = tdes.CreateDecryptor();
byte[] plain = Encoding.UTF8.GetBytes(value);
byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length);
String encryptedText = Convert.ToBase64String(cipher);
return encryptedText;
}
But the reversal is not working.
Error: An exception of type
'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll but was not handled in user code
Additional information: Padding is invalid and cannot be removed.
Stack Trace:
System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)
at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at redis2.Crypto.AESECBPKCS5PaddingEncryptor.decrypt(String value) in e:\TestApplication\Redis\redis2\redis2\Crypto\AESECBPKCS5PaddingEncryptor.cs:line 53
at redis2.WebForm1.Page_Load(Object sender, EventArgs e) in e:\TestApplication\Redis\redis2\redis2\WebForm1.aspx.cs:line 14
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
update 1
public String decrypt(String value)
{
System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
AesManaged tdes = new AesManaged();
tdes.Key = UTF8.GetBytes(securityKey);
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform crypt = tdes.CreateDecryptor();
// value = Convert.FromBase64String(value);
byte[] plain = Convert.FromBase64String(value);
byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length);
String encryptedText = Convert.ToBase64String(cipher);
return encryptedText;
}
With encryption and decryption code, it's not uncommon for you to perform at least one other conversion of the data along it's way through the encryption code. When writing the decryption code, you need to make sure you apply the reverse of each transformation in the reverse order.
So, in your encryption code, we have
[string] --UTF8--> [byte[]] --Encrypt--> [byte[]] --Base64--> [string]
With your original decryption code, we have
[string] --UTF8--> [byte[]] --Decrypt--> [byte[]] --Base64--> [string]
But that's not doing the reverse transforms in the reverse order. Lets put them alongside each other with the decryption one reversed:
[string] --UTF8--> [byte[]] --Encrypt--> [byte[]] --Base64--> [string] --|
|
[gnirts] <--46esaB-- [[]etyb] <--tpyrceD-- [[]etyb] <--8FTU-- [gnirts] <-|
(The extra arrow at the end shows the transfer of the string by some other code from the return from encrypt to supplying it as a parameter to decrypt).
We can see that we're doing something UTF8 related when we should be doing something to undo Base 64 encoding, and we're doing something Base64 related when we should be doing something UTF8 related.
So the correction is to base 64 decode the passed in string to decrypt and to UTF8 decode the result after decryption:
public String decrypt(String value)
{
System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
AesManaged tdes = new AesManaged();
tdes.Key = UTF8.GetBytes(securityKey);
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform crypt = tdes.CreateDecryptor();
byte[] plain = Convert.FromBase64String(value);
byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length);
String encryptedText = Encoding.UTF8.GetString(cipher);
return encryptedText;
}
I'd usually recommend that when people are working with decryption, they start as simple as possible and then build up from there. The simplest thing to have gotten right first here would have been something that accepted a byte[] and returned a byte[] (for both methods) and can successfully round trip a byte array. Then add string encoding support for either the plaintext or the ciphertext but not both. Confirm that round trips. Then add another encoding. A zip layer. etc.
(This is also my recommended strategy for encrypt with language 1, decrypt with language 2. First write methods that can round trip successfully in both languages with all necessary transformations, then do the work of making them interoperate)
tdes.Key = UTF8.GetBytes(securityKey);
Is always the wrong way to get a key from a string.
When you have a password, use Rfc2898DeriveBytes
when you need to pass a random binary key, use Convert.FromBase64String()
String encryptedText = Encoding.UTF8.GetString(cipher);
Is the wrong way to transport binary data as text. This won't even round-trip because UTF8 has escape sequences to encode non-ASCII tokens. And you can't break those up.
Use Convert.ToBase64String(byte[])

c# MCRYPT_RIJNDAEL_256 Encryption Decryption Class in php

I am trying to convert c# application into php but I stuck at a place where C# provides Security class for Encryption and decryption based on RIJNDAEL algo. I am trying to convert into php.
Note: I am Using php 7.2 so mcrypt is deprecated for this version.
C# code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace pharmarackencryption
{
class Program
{
private const string initVector = "aw90rela942f65u2";
// This constant is used to determine the keysize of the encryption algorithm.
private const int keysize = 256;
public static string Encrypt(string plainText, string passPhrase = "testing")
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string cipherText, string passPhrase = "testing")
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
static void Main(string[] args)
{
Program p = new Program();
string enc_password = Encrypt("437217");
string dec_password = Decrypt("C9xJGa03dRQx9ePm0nLnHg==");
Console.WriteLine(enc_password);
Console.WriteLine(dec_password);
}
}
}
Encryption : C9xJGa03dRQx9ePm0nLnHg==
I found some what similar code in php like
PHP code:
<?php
// key/iv in ASCII binary data, $str base64
function decrypt_stuff($key, $str, $iv) {
// $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($str), MCRYPT_MODE_CBC, $iv);
$plaintext_dec = openssl_decrypt(base64_decode($str), "aes-256-cbc", $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
return $plaintext_dec;
}
// key/iv in ascii binary data, $str ascii
function encrypt_stuff($key, $str, $iv) {
// $ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $str, MCRYPT_MODE_CBC, $iv));
if (($l = (strlen($str) & 15)) > 0) { $str .= str_repeat(chr(0), 16 - $l); }
$ciphertext = base64_encode(openssl_encrypt($str, "aes-256-cbc", $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv));
return $ciphertext;
}
echo encrypt_stuff("testing","437217","aw90rela942f65u2");
//Result : LTbhEHjFgfa5PDJQXJEdKQ==
Both are going same thing but still result is different
Your PHP code produces different results because you're not using the same key. In your C# code you're using PasswordDeriveBytes to create the key, which is Microsoft's implementation of PBKDF1.
PHP doesn't support PBKDF1, but we could write a function that is compatible with C#. The code below is inspired from this great answer by Maarten Bodewes, translated to PHP.
function passwordDeriveBytes($password, $salt, $iterations = 100, $len = 32) {
$key = $password . $salt;
for($i = 0; $i < $iterations; $i++) {
$key = sha1($key, true);
}
if (strlen($key) < $len) {
$hx = passwordDeriveBytes($password, $salt, $iterations - 1, 20);
$counter = 0;
while (strlen($key) < $len) {
$counter += 1;
$key .= sha1($counter . $hx, true);
}
}
return substr($key, 0, $len);
}
Also, you're bese64 encoding and padding your data manually. You're preforming zero byte padding, but in your C# code you're using PKCS7 (the default and preferred) padding. It's best to let openssl pad and encode your data.
function encrypt_stuff($key, $str, $iv) {
return openssl_encrypt($str, "aes-256-cbc", $key, 0, $iv);
}
function decrypt_stuff($key, $str, $iv) {
return openssl_decrypt($str, "aes-256-cbc", $key, 0, $iv);
}
Using the key derived from passwordDeriveBytes, this PHP code produces the same results as your C# code.
$key = passwordDeriveBytes("testing", null);
$enc = encrypt_stuff($key,"437217","aw90rela942f65u2");
echo $enc;
//C9xJGa03dRQx9ePm0nLnHg==
However, I don't recommend using this code for the following reasons.
It's best to use PBKDF2 for your key. You can use Rfc2898DeriveBytes in C#:
Rfc2898DeriveBytes kdf = new Rfc2898DeriveBytes(password, salt, iterations);
byte[] key = kdf.GetBytes(32);
and hash_pbkdf2 in PHP:
$key = hash_pbkdf2("sha1", $password, $salt, $iterations, 32, true);
The salt should be at least 8 bytes long, and the number of iterations should be at least 10,000.
You're not using a salt. You should use a random salt for each password, it makes your keys stronger.
You're using a static IV. The IV should be unique and unpredictable. You can create a random IV with RNGCryptoServiceProvider:
byte[] iv = new byte[16];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(iv);
and openssl_random_pseudo_bytes:
$iv = openssl_random_pseudo_bytes(16);
You could use this code for the salt too.
You're not using authenticated encryption. If you're using PHP 7 you could use GCM, but unfortunately .NET doesn't provide any AEAD algorithms. However, you could use bouncycastle, if you choose to use authenticated encryption.
But your encryption code should produce different results every time you use it, because you should be using a random IV. You can decrypt the ciphertext correctly if you have the IV. The IV doesn't have to be secret; you could store it next to the ciphertext.
If you were using mcrypt with MCRYPT_RIJNDAEL_256, you could still make your PHP code compatible with C#, as RijndaelManaged supports 256 bit block size.
symmetricKey.BlockSize = 256;
However you shouldn't use mcrypt because it's not maintained, and it's deprecated in PHP 7.
I am not familiar with the C# end of this question. However I will point out some information that may be relevant to your problem.
The descriptions in the RIJNDAEL functions refer to the block size, not the key size. For example MCRYPT_RIJNDAEL_256 states that you are using a block size of 256. It is not specifying a key size.
For the openssl AES functions you are specifying a key size. As an example aes-256-cbc specifies you are using a 256 bit key.
The block size for all the AES functions is a 128 bit. So you can use MCRYPT_RIJNDAEL_128 which matches the AES block size. You can use a 256 bit key with both the MCRYPT_RIJNDAEL_128 and the aes-256-cbc as they are both using the 128 bit block size.
So for these reasons aes-256-cbc can not be used with MCRYPT_RIJNDAEL_256. They simply are not the same thing.
This one is redundant. If you are using the aes-256-cbcyou need to make sure that you are using a 256 bit key. Obviously make sure that your are using the same key to encrypt and decrypt. Make sure your IV is the correct IV. I would make them both static for testing. Once you get it working tinker around with adding the IV to the cipher string on encrypt and separating the IV from the cipher text on decrypt
Use openssl_random_pseudo_bytes() to generate your 256 bit(32 byte)key. You can also use openssl_random_pseudo_bytes() to generate your IV.
On a side note. I would highly recommend using the LibSodium library. It is now native on the latest versions of PHP and has a C# library as well. You can find it on Github easy enough.
Once you get this going I would look at learning how to Authenticate/Verify your encryption. Here is a good starting link for that. Authentication Read
Hope that helps.
It is not recommended to store passwords at the database using an reversible algo, passwords should be stored using expensive hashes. You should consider switching your password storage to a hash like Argon2.
Check this: http://php.net/manual/en/function.password-hash.php
mcrypt has been moved. not removed. you may try installing this
sudo apt-get -y install gcc make autoconf libc-dev pkg-config
sudo apt-get -y install php7.2-dev
sudo apt-get -y install libmcrypt-dev
sudo pecl install mcrypt-1.0.1
PS: not tested

convert C# code to php for encrypt and decrypt [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I try to convert this code to php, but i can't and always i get different result in C# and PHP
Here is my C# code for encrypt and decrypt :
private static readonly byte[] initVectorBytes = Encoding.ASCII.GetBytes("1234567812345678");
private const int keysize = 256;
private string pass = "sample";
public static string Encrypt(string plainText, string passPhrase)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string cipherText, string passPhrase)
{
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
and this is my php code :
$iv = "1234567812345678";
$out = null;
$key = "sample";
foreach ($iv as $i) { $out .= chr(ord(substr($i,0,1))); }
$res = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_CBC, implode($out));
The keys are not the same. C# is extending the key with PasswordDeriveBytes which is a good method. PHP mcrypt is extending they key with nulls. You need the extended (256-bit) keys to be the same.
The padding is not the same. Unencrypted data needs to be a multiple of the block size (128-bits for AES) and if it isn't always that padding must to be added. C# is not specifying any padding and will expect the data to be a multiple of the block size (128-bits). PHP will by default add null padding which is non-standard and will not work for binary data. You need to add common padding, the standard is PKCS#7 (aka PKCS#5), See PKCS#7 padding. C# supports PKCS#5 but for mcrypt you will have to do it in your code (the mcrypt developers were Bozos and did not provide standard padding).
Rijndael supports multiple bock sizes, it is not clear what the C# default block size is. If what you want is AES (it should be) the block size needs to be 128-bits.
Given that the MSDN documentation does not specify defaults it is best to explicitly set the block size, key size, mode and padding.
Your PHP code will not run on PHP 5.6 as the key size is wrong, it must be 32 bytes.
Said that, on previous versions PHP was padding the key with \0's to reach the correct key length, but in C# you're creating derived bytes (what indeed is correct) to get enough bytes for your key, which ends in different keys used on C# and PHP.
As a proof, create a key with 32 bytes (32 chars) and use directly those 32 bytes as key, both in PHP and C#, in that way it should work.
But at the end you will need a common way to derive the bytes both on PHP and C# to finally have a consistent keying code, an example can be to use a SHA-256 hash to generate the key.

AES/CBC/NoPadding between C# and Java

I'm using some encryption functions in C# and Java whose output doesn't seem to match. I'm feeding in the same key and IV strings as a test.
Input string: "&app_version=1.0.0.0"
Java:
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes("UTF-8"));
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8"));
// Then I convert encrypted to hex by building a string of encrypted[i] & 0xFF
Output:
60f73a575b647263d75011bb974a90e85201b8dfeec6ec8ffba04c75ab5649b3
C#:
SymmetricKeyAlgorithmProvider alg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbc);
BinaryStringEncoding encoding = BinaryStringEncoding.Utf8;
// Create key and IV buffers
IBuffer keyBuffer = CryptographicBuffer.ConvertStringToBinary(key, encoding);
CryptographicKey cKey = alg.CreateSymmetricKey(keyBuffer);
IBuffer ivBuffer = CryptographicBuffer.ConvertStringToBinary(iv, encoding);
// Create input text buffer
IBuffer inputBuffer = CryptographicBuffer.ConvertStringToBinary(input, encoding);
// Do the encryption
IBuffer encryptedBuffer = CryptographicEngine.Encrypt(cKey, inputBuffer, ivBuffer);
// Convert encrypted back to hex
string encryptedStr = CryptographicBuffer.EncodeToHexString(encryptedBuffer);
Output:
4b6fd83c35565fc30a9ce56134c277cbea74d14886cf99e11f4951075d4f4505
I am using a Java decrypter to check and it decrypts the Java-encrypted string correctly but the C# string is read as "&app_version=1Q0.0.0" so it seems close but slightly off.
I have checked that the bytes of the key, input, and IV match before the encryption step. Are there any other differences that would cause a discrepancy?
EDIT
With all-zero key "00000000000000000000000000000000" and IV "0000000000000000" I got the same output for both Java and C#:
081821ab6599650b4a31e29994cb130203e0d396a1d375c7d1c05af73b44a86f
So perhaps there is something wrong with the key or IV that one is reading...
I feel like a fool...my IV contained a zero in one and a capital O in another!! Well, at least I know this code is equivalent.

C# AES Function not returning expected results

I'm using this function to Encrypt/Decrypt data using AES because it looked simple and clean (googl'ed code)
public static string Encrypt(string toEncrypt)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes("3a8114db34d5623d4fd1ee0fb0ga7a73"); // 256-AES key
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.CBC;
rDel.Padding = PaddingMode.PKCS7; // better lang support
ICryptoTransform cTransform = rDel.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string toDecrypt)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes("3a8114db34d5623d4fd1ee0fb0ga7a73"); // AES-256 key
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.CBC;
rDel.Padding = PaddingMode.PKCS7; // better lang support
ICryptoTransform cTransform = rDel.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return UTF8Encoding.UTF8.GetString(resultArray);
}
I'm trying to encrypt the data "test garbage" and thats what i receive back:
YfhyS3GE/liPCaXR0cMHfQ==
However, I tried the same key/phrase on a lot of online-aes encrypt/decrypt and all of them are returning
U2FsdGVkX184u0/vPgA/B0rxofp5Iuqm7hfn4+QZAhg=
Can anyone actually tell me whats wrong?
"3a8114db34d5623d4fd1ee0fb0ga7a73" is hex encoded 128 bit key not a utf8 encoded 256 bit key.
That said simple and clean doesn't necessarily mean correct. For example, the code your using does use a random IV, but doesn't include it in the wire format, you'll never be able to decrypt what you encrypt.
I have a cut and paste style simple code sample that I try to keep up to date and reviewed that uses authenticated encryption using AES:
Modern Examples of Symmetric Authenticated Encryption of a string. C#
First a few issues with your code. Apparently Google doesn't always return the best code on top.
You are getting a key through the UTF8 encoding, which is silly. This produces a very weak key:
// 256-AES key
byte[] keyArray = UTF8Encoding.UTF8.GetBytes("3a8114db34d5623d4fd1ee0fb0ga7a73");
You are using CBC mode but the IV is not (explicitly) set.
Then you compare to some online-aes encrypt/decrypt services and you see a difference. That's because they probably (hopefully) work different.
The main thing here is that your 2 methods are a match and you can round-trip your data. But a good encryption would use a different way to get Key and IV.
I'm not exactly sure why you see a different (smaller) length encrypted data but that's up to a whole list of settings : Key length, Padding mode etc.

Categories