Problem with rewrite c# aes method to python? - c#

I'm trying rewrite this method in c# to python, but python and all online crypters are giving me another result than c# gives.
DEMO key: 55BE4F94FFCA8A40CB78ED8E3BEF6FC0
DEMO IV: 2E4F5C8A4E5E8E5F
DEMO data: test
return in c#: x0wOQpG0MpeUdkVjPi/O4Dw+9Mst+lyPzXYC7kryJnY= (in base64)
return in python: xTr+FvQRyUIfbrVq8RIn/Q== (in base64)
public static string encode(string string_0, string string_1, string string_2)
{
UTF8Encoding utf8Encoding = new UTF8Encoding();
byte[] bytes = utf8Encoding.GetBytes(string_1);
byte[] bytes2 = utf8Encoding.GetBytes(string_2);
byte[] inArray;
using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
{
try
{
rijndaelManaged.Padding = PaddingMode.PKCS7;
rijndaelManaged.Mode = CipherMode.CBC;
rijndaelManaged.KeySize = 256;
rijndaelManaged.BlockSize = 256;
rijndaelManaged.Key = bytes;
rijndaelManaged.IV = bytes2;
MemoryStream memoryStream = new MemoryStream();
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateEncryptor(bytes, bytes2), CryptoStreamMode.Write))
{
using (StreamWriter streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(string_0);
}
inArray = memoryStream.ToArray();
var str = System.Text.Encoding.Default.GetString(inArray);
}
}
finally
{
rijndaelManaged.Clear();
}
}
return Convert.ToBase64String(inArray);
}
EDIT:Added python code
import base64
from Cryptodome.Cipher import AES
from pkcs7 import PKCS7Encoder
key = b'55BE4F94FFCA8A40CB78ED8E3BEF6FC0'
IV = b'2E4F5C8A4E5E8E5F'
data = 'test'
aes = AES.new(key, AES.MODE_CBC, IV)
print(base64.b64encode(aes.encrypt(bytes(PKCS7Encoder().encode(data), "utf8"))))

Related

AES encryption/decryption between php and c#

I'm trying to make encryption and decryption between php and c# using AES-128-ECB
I found a way to encrypt in php and decrypt in c#.
the problem now i'm trying to do the opposite I'm facing problem trying to understand how c# working with Cryptography
the code I used I found it on this question
PHP and C# AES256 encryption -> decryption
I'm using the same code it's easy to do it on php for decryption but my problem with c#
I found this docs cryptography using rijadealManaged I coudn't understand it
c# code :
public String Decryptions(String text, String key)
{
//decode cipher text from base64
byte[] cipher = Convert.FromBase64String(text);
//get key bytes
byte[] btkey = Encoding.ASCII.GetBytes(key);
//init AES 128
RijndaelManaged aes128 = new RijndaelManaged();
aes128.Mode = CipherMode.ECB;
aes128.Padding = PaddingMode.PKCS7;
//decrypt
ICryptoTransform decryptor = aes128.CreateDecryptor(btkey, null);
MemoryStream ms = new MemoryStream(cipher);
CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
byte[] plain = new byte[cipher.Length];
int decryptcount = cs.Read(plain, 0, plain.Length);
ms.Close();
cs.Close();
//return plaintext in String
return Encoding.UTF8.GetString(plain, 0, decryptcount);
}
php code :
function encryption($json) {
$encrypted= '';
$plaintext = $json;
$cipher = 'AES-128-ECB';
$key = '1234567891123456';
$encrypted = openssl_encrypt($plaintext, $cipher, $key, 0);
return $encrypted;
echo $encrypted;
}
UPDATE :
tried this code from answers :
public string Encryption(string text,string key,string privatekey)
{
byte[] inputtextbyteArray = System.Text.Encoding.UTF8.GetBytes(text);
using RijndaelManaged aes128 = new RijndaelManaged { Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
using var memstr = new MemoryStream();
using var crystr = new CryptoStream(memstr, aes128.CreateDecryptor(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(privatekey)), CryptoStreamMode.Write);
crystr.Write(inputtextbyteArray, 0, inputtextbyteArray.Length);
return Convert.ToBase64String(memstr.ToArray());
}
public string Decryption(string base64, string key, string privatekey)
{
try
{
byte[] inputtextbyteArray = Convert.FromBase64String(base64.Replace(" ", "+"));
using RijndaelManaged aes128 = new RijndaelManaged { Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
using var memstr = new MemoryStream();
using var crystr = new CryptoStream(memstr, aes128.CreateDecryptor(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(privatekey)), CryptoStreamMode.Write);
crystr.Write(inputtextbyteArray, 0, inputtextbyteArray.Length);
return Encoding.UTF8.GetString(memstr.ToArray());
}
catch (Exception ex)
{
throw new Exception("LOL NO HACKING!");
}
}
I understand how code work but the Errors I'm getting confusing :
public string Encryption(string text,string key,string privatekey)
{
byte[] inputtextbyteArray = System.Text.Encoding.UTF8.GetBytes(text);
using RijndaelManaged aes128 = new RijndaelManaged { Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
using var memstr = new MemoryStream();
using var crystr = new CryptoStream(memstr, aes128.CreateDecryptor(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(privatekey)), CryptoStreamMode.Write);
crystr.Write(inputtextbyteArray, 0, inputtextbyteArray.Length);
return Convert.ToBase64String(memstr.ToArray());
}
public string Decryption(string base64, string key, string privatekey)
{
try
{
byte[] inputtextbyteArray = Convert.FromBase64String(base64.Replace(" ", "+"));
using RijndaelManaged aes128 = new RijndaelManaged { Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
using var memstr = new MemoryStream();
using var crystr = new CryptoStream(memstr, aes128.CreateDecryptor(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(privatekey)), CryptoStreamMode.Write);
crystr.Write(inputtextbyteArray, 0, inputtextbyteArray.Length);
return Encoding.UTF8.GetString(memstr.ToArray());
}
catch (Exception ex)
{
throw new Exception("LOL NO HACKING!");
}
}
I didn't test it
remeber by use "using" you dont need to use ms.Close();
And aes128.CreateDecryptor(btkey, null); why you use null
just make a private key
and btw i just choice "key" in my code but easy to call it chiper

256 AES Encryption C# .Net Core not working as expected

I have a couple of projects in different languages that encrypt/decrypt string, for example, a php project can encrypt a string and store in a database and a c# project should be able to pull it out of the database and decrypt it.
I have a c# .net core project which I've successfully made the decryption method to decrypt string that are encrypted from other projects, but I now need a method that also does the encryption.
I have implemented a method which isn't throwing any errors but the encryption string it returns is completely wrong.
Below is my implementation of the encryption
public string encrypt(string decryptedString)
{
string encrypted;
byte[] key = Encoding.UTF8.GetBytes(CipherKey);
System.Security.Cryptography.Aes aes = System.Security.Cryptography.Aes.Create();
aes.KeySize = 256;
aes.Padding = PaddingMode.PKCS7;
aes.Key = key;
aes.IV = Encoding.UTF8.GetBytes(CipherIv);
aes.Mode = CipherMode.CBC;
ICryptoTransform decipher = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, decipher, CryptoStreamMode.Write))
{
using (StreamWriter sr = new StreamWriter(cs))
{
sr.Write(decryptedString);
var encryptedString = ms.ToArray();
var result = new byte[aes.IV.Length + encryptedString.Length];
Buffer.BlockCopy(aes.IV, 0, result, 0, aes.IV.Length);
Buffer.BlockCopy(encryptedString, 0, result, aes.IV.Length, encryptedString.Length);
return Convert.ToBase64String(result);
}
}
}
}
And the equivalent method to decrypt (the decryption works fine) is below
public string decrypt(string encryptedPassword, bool throwException = false)
{
try
{
string decrypted;
byte[] key = Encoding.UTF8.GetBytes(CipherKey);
System.Security.Cryptography.Aes aes = System.Security.Cryptography.Aes.Create();
aes.KeySize = 256;
aes.Padding = PaddingMode.PKCS7;
aes.Key = key;
aes.IV = Encoding.UTF8.GetBytes(CipherIv);
aes.Mode = CipherMode.CBC;
byte[] base64decodeBytes = System.Convert.FromBase64String(encryptedPassword);
string base64Decode = Encoding.UTF8.GetString(base64decodeBytes);
ICryptoTransform decipher = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream ms = new MemoryStream(base64decodeBytes))
{
using (CryptoStream cs = new CryptoStream(ms, decipher, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
{
decrypted = sr.ReadToEnd();
}
}
return decrypted;
}
catch (Exception ex)
{
return encryptedPassword;
}
}
UPDATE
From the advice in the comment by 500 - Internal Server Error I have made a change which seems to have resolved the issue somewhat but I am now getting junk at the start of the string in the decryption.
For example I am doing the following to test:
string encryptionString = encryption.encrypt("Hello World");
Console.WriteLine("Encrypted String: {0}", encryptionString);
string decodedString = encryption.decrypt(encryptionString);
Console.WriteLine("Decrypted String: {0}", decodedString);
Encrypted String: Z3BmenhibnNmZ1tqa2xhZgs/GYMu49dNPNGoRROTWz4=
Decrypted String: �u�D'���);�
SKHHello World

Unrecognized unicode result from AES decryption

I try to build simple AES encryption helper to encrypt/decrypt some strings
Fist, I have an issue with Padding mode wherein decryption it only accepts if Zero otherwise an error about padding occurs!
The second issue is when I try to encrypt simple string "Hello World," it got encrypted, and I have the base64 string, but when trying to decrypt, there's no error, but a weird unknown character is shown! like 㡲啁䎰廾ử靱힩㡲啁䎰廾ử靱힩
My code:
private static int keySizes = 256;
private static int blockSize = 128;
private static PaddingMode pMode = PaddingMode.Zeros;
private static CipherMode cMode = CipherMode.ECB;
private static byte[] key = GenEncryptionKey();
private const string passphrase = #"StartYourMorningWithASmile";
private static byte[] GenEncryptionKey()
{
HashAlgorithm hash = MD5.Create();
return hash.ComputeHash(Encoding.Unicode.GetBytes(passphrase));
}
private static AesManaged CreateCryptor()
{
AesManaged cryptor = new AesManaged();
cryptor.KeySize = keySizes;
cryptor.BlockSize = blockSize;
cryptor.Padding = pMode;
cryptor.Key = key;
cryptor.Mode = cMode;
cryptor.GenerateIV();
return cryptor;
}
public static string EncryptParams(string reqVal)
{
string cipherText = "";
if (string.IsNullOrEmpty(reqVal) || reqVal.Length < 1)
throw new ArgumentNullException();
byte[] plainBytes = Encoding.Unicode.GetBytes(reqVal);
using (var cryptor = CreateCryptor())
{
ICryptoTransform encryptor = cryptor.CreateEncryptor();
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(plainBytes, 0, plainBytes.Length);
}
byte[] cipherBytes = ms.ToArray();
cipherText = Convert.ToBase64String(cipherBytes);
}
cryptor.Clear();
}
return cipherText;
}
public static string DecryptParams(string resVal)
{
var data = Convert.FromBase64String(resVal);
byte[] cipherBytes = new byte[data.Length];
string plainText = "";
using (var crypto = CreateCryptor())
{
ICryptoTransform Dec = crypto.CreateDecryptor();
using (MemoryStream ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
plainText = Encoding.Unicode.GetString(ms.ToArray());
}
}
crypto.Clear();
}
return plainText;
}
UPDATE 1:
Please set also the IV yourself to achieve successful decryption, as #maarten-bodewes pointed out. I missed that part and the decryption somehow worked (?) with your existing code, but you always should provide the same key and IV to a symmetric encryption algorithm to have it work both ways.
ORIGINAL ANSWER:
Your decryption fails (produces incorrect results) because you implemented the decryption part incorrectly (by using CryptoStreamMode.Write instead of CryptoStreamMode.Read) and besides feeding the decryption stream all zero bytes
At the point of execution of
cs.Write(cipherBytes, 0, cipherBytes.Length);
the variable cipherBytes is all zero. The real encrypted buffer is in the data variable which you only use to set the length of cipherBytes
So change your decryption method to this.
BONUS: After correcting the decryption part, you can specify the padding as you wish! I tested with PKCS7 and it is ok.
public static string DecryptParams(string resVal)
{
var cipherBytes = Convert.FromBase64String(resVal);
string plainText = "";
using (var crypto = CreateCryptor())
{
ICryptoTransform Dec = crypto.CreateDecryptor();
using (MemoryStream ms = new MemoryStream(cipherBytes))
{
using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Read))
{
byte[] decryptBlock = new byte[4096];
MemoryStream decryptStream = new MemoryStream();
int readBytes;
while ((readBytes = cs.Read(decryptBlock, 0, 4096)) > 0)
{
decryptStream.Write(decryptBlock, 0, readBytes);
}
plainText = Encoding.Unicode.GetString(decryptStream.ToArray());
}
}
crypto.Clear();
}
return plainText;
}
Hope this helps.
Thanks to Oguz
Below is my description method after edit
public static string DecryptParams(string resVal)
{
var data = Convert.FromBase64String(resVal);
byte[] cipherBytes = new byte[data.Length];
string plainText = "";
using (var crypto = CreateCryptor())
{
ICryptoTransform Dec = crypto.CreateDecryptor();
using (MemoryStream ms = new MemoryStream(data))
{
using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Read))
{
cs.Read(cipherBytes, 0, cipherBytes.Length);
plainText = Encoding.Unicode.GetString(cipherBytes.ToArray());
}
}
crypto.Clear();
}
return plainText;
}
one more thing about the return result after the decryption I got the original string plus \0\0\0\0 so I use myString.TrimEnd('\0') to solve that.

Encrypt data on reactjs and decrpt it in c# app

I have to encrypt some data on reactjs side and decrypt data in c# app.
I am trying rijndael-js in reactjs. And on c# side i am using RijndaelManaged. Own each one codes like below.
reactjs codes;
import Rijndael from "rijndael-js"
class ServiceRequester{
getCrypto()
{
let original = "tolga";
let key = "00000000000000000000000000000000"; // 32 length
let iv = "0000000000000000"; // 16 length
let cipher = new Rijndael(key, "cbc");
let ciphertext = cipher.encrypt(original, 128, iv);
console.log(ciphertext.toString("base64"));
console.log(cipher.decrypt(ciphertext, 128, iv).toString());
return ciphertext.toString("base64");
}
}
c# code;
public static string Decrypt(string encryptedText)
{
if (encryptedText == null)
{
return null;
}
var bytesToBeDecrypted = Convert.FromBase64String(encryptedText);
var bytesDecrypted = Decrypt(bytesToBeDecrypted);
return Encoding.UTF8.GetString(bytesDecrypted);
}
private static byte[] Decrypt(byte[] bytesToBeDecrypted)
{
byte[] decryptedBytes = null;
using (var ms = new MemoryStream())
{
using (var AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Key = new byte[32];
AES.IV = new byte[16];
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
c# app been throwing an error. Error is
System.Security.Cryptography.CryptographicException: 'Padding is invalid and cannot be removed.

C# - Problem with AES Decryption - always get null

I am trying to implement image steganography with LSB and everything works except decrypting.
There is my class responsible for encryption and decryption of strings below. Encrypting works fine but Decrypt method always returns null:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApp1
{
class Encryptor {
//text to encrypt or already decrypted
private String decryptedText = "";
//text to decrypt or already encrypted
private String encryptedText = "";
private String key = "";
public Encryptor setDecryptedText(String text)
{
decryptedText = text;
return this;
}
public Encryptor setEncryptedText(String text)
{
encryptedText = text;
return this;
}
public Encryptor setKey(String text)
{
key = text;
return this;
}
Byte[] getHash(Byte[] hash)
{
Byte[] newHash = new Byte[32];
for (int i = 0; i < 32; i++)
{
newHash[i] = hash[i];
}
return newHash;
}
Byte[] getIV(Byte[] hash)
{
Byte[] newHash = new Byte[16];
int j = 0;
for (int i = 32; i < 48; i++)
{
newHash[j++] = hash[i];
}
return newHash;
}
String EncryptAesManaged()
{
SHA512 shaM = new SHA512Managed();
Byte[] data = Encoding.UTF8.GetBytes(key);
Byte[] hash = shaM.ComputeHash(data);
try
{
return Encrypt(decryptedText, getHash(hash), getIV(hash));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}
String DecryptAesManaged()
{
SHA512 shaM = new SHA512Managed();
var data = Encoding.UTF8.GetBytes(key);
Byte[] hash = shaM.ComputeHash(data);
try
{
return Decrypt(Convert.FromBase64String(encryptedText), getHash(hash), getIV(hash));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return "";
}
String Encrypt(string plainText, byte[] Key, byte[] IV)
{
Byte[] encrypted;
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs)) {
sw.Write(Encoding.UTF8.GetBytes(plainText));
cs.FlushFinalBlock();
encrypted = ms.ToArray();
}
}
}
aes.Clear();
}
return Convert.ToBase64String(encrypted);
}
string Decrypt(byte[] cipherText, byte[] Key, byte[] IV)
{
string plaintext = null;
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform decryptor = aes.CreateDecryptor(Key, IV);
try
{
using (MemoryStream ms = new MemoryStream(cipherText))
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
using (StreamReader reader = new StreamReader(cs))
{
plaintext = reader.ReadToEnd(); //Here get null
}
aes.Clear();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return plaintext;
}
public String getEncrypted()
{
return EncryptAesManaged();
}
public String getDecrypted()
{
return DecryptAesManaged();
}
}
}
Why is Decrypt() returning null rather than the originally encrypted string?
You don't show how you use your Encryptor class, so your question doesn't quite include a Minimal, Complete, and Verifiable example. I was able to reproduce the problem with the following test harness:
public static void Test()
{
var key = "my key";
var plainText = "hello";
var encryptor = new Encryptor();
encryptor.setDecryptedText(plainText);
encryptor.setKey(key);
var encrypted = encryptor.getEncrypted();
Console.WriteLine(encrypted);
var deecryptor = new Encryptor();
deecryptor.setEncryptedText(encrypted);
deecryptor.setKey(key);
var decrypted = deecryptor.getDecrypted();
Console.WriteLine(decrypted);
Assert.IsTrue(plainText == decrypted);
}
Demo fiddle #1 here.
Given that, your code has 2 problems, both of which are actually in encryption rather than decryption.
Firstly, in Encrypt(string plainText, byte[] Key, byte[] IV), you are writing to the StreamWriter sw, then flushing the CryptoStream and returning the MemoryStream contents -- but you never flush or dispose sw, so its buffered contents are never forwarded to the underlying stream(s).
To fix this, your code should looks something like:
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(Encoding.UTF8.GetBytes(plainText));
}
}
encrypted = ms.ToArray();
}
Now getDecrypted() no longer returns a null result -- but instead returns a wrong result of "System.Byte[]", as shown in demo fiddle #2 here.
Secondly, again in Encrypt(...), you are effectively encoding your plainText twice at this line:
sw.Write(Encoding.UTF8.GetBytes(plainText));
Encoding.UTF8.GetBytes(plainText) converts the plain text to a byte array, but the StreamWriter is also intended to do this job, converting strings to bytes and passing them to the underlying stream. So, since you are not passing a string to Write(), the overload that gets called is StreamWriter.Write(Object):
Writes the text representation of an object to the text string or stream by calling the ToString() method on that object.
Thus what actually gets encrypted is the ToString() value of a byte array, which is "System.Byte[]".
To fix this, simply remove the call to Encoding.UTF8.GetBytes(plainText) and write the string directly. Thus your Encrypt() method should now look like:
static String Encrypt(string plainText, byte[] Key, byte[] IV)
{
string encrypted;
using (var aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write, true))
{
using (var sw = new StreamWriter(cs))
{
sw.Write(plainText);
}
}
// Calling GetBuffer() avoids the extra allocation of ToArray().
encrypted = Convert.ToBase64String(ms.GetBuffer(), 0, checked((int)ms.Length));
}
aes.Clear();
}
return encrypted;
}
Demo fiddle #3 here that now passes successfully.
Disclaimer: this answer does not attempt to to review your code for security best practices such as secure setup of salt and IV.

Categories

Resources