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
Related
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.
I have legacy server uses TripleDES encryption in .NET/C#.
Need to decrypt text by using PHP.
I wrote PHP code but it's not able to decrypt message generated form C#.
C# Code
using System;
using System.Data;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace testns
{
class Program
{
static void Main(string[] args)
{
string key = "123456789012345678901234";
string iv = "12345678";
string text = "this is just test string";
string e = Program.EncryptTripleDES(text, key, iv);
Console.WriteLine(e);
string d = Program.DecryptTripleDES(e, key, iv);
Console.WriteLine(d);
// Return
// QDIRAeQ/O1hhjN4XqgcETG7IChnybCqZ
// this is just test string
}
private static string EncryptTripleDES(string neqs, string nafKeyCode, string nafIvCode)
{
byte[] rgbKey = Encoding.UTF8.GetBytes(nafKeyCode);
byte[] rgbIV = Encoding.UTF8.GetBytes(nafIvCode);
string sEncrypted = string.Empty;
if (!String.IsNullOrEmpty(neqs))
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
cryptoProvider.Mode = CipherMode.CBC;
cryptoProvider.Padding = PaddingMode.None;
byte[] buffer = Encoding.UTF8.GetBytes(neqs);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, cryptoProvider.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
cs.Write(buffer, 0, buffer.Length);
cs.FlushFinalBlock();
sEncrypted = Convert.ToBase64String(ms.ToArray());
}
return sEncrypted;
}
private static string DecryptTripleDES(string neqs, string nafKeyCode, string nafIvCode)
{
byte[] rgbKey = Encoding.UTF8.GetBytes(nafKeyCode);
byte[] rgbIV = Encoding.UTF8.GetBytes(nafIvCode);
string decryptedText = string.Empty;
if (!String.IsNullOrEmpty(neqs))
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
cryptoProvider.Mode = CipherMode.CBC;
cryptoProvider.Padding = PaddingMode.None;
byte[] buffer = Convert.FromBase64String(neqs);
MemoryStream ms = new MemoryStream(buffer);
CryptoStream cs = new CryptoStream(ms, cryptoProvider.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cs);
decryptedText = sr.ReadToEnd();
//(new Logs()).LogException(decryptedText);
}
return decryptedText;
}
}
}
PHP Code
$key = '123456789012345678901234';
$iv = '12345678';
$text = 'this is just test string';
$e = openssl_encrypt($text, 'des-ede3-cbc', $key, 0, $iv);
echo $e . "<br /><br />";
$d = openssl_decrypt($e, 'des-ede3-cbc', $key, 0, $iv);
echo $d . "<br /><br />";
// Return
// QDIRAeQ/O1hhjN4XqgcETG7IChnybCqZqN3DpVbYFwk=
// this is just test string
Got from PHP
QDIRAeQ/O1hhjN4XqgcETG7IChnybCqZqN3DpVbYFwk=
Got from C#
QDIRAeQ/O1hhjN4XqgcETG7IChnybCqZ
As you an see it's almost the same for PHP has extra qN3DpVbYFwk= characters.
What I am doing wrong? It is something to do with padding?
Thanks
It looks like the problem is that you have turned padding off (PaddingMode.None) in your C# code and Padding is turned on (by default) in your PHP code.
The OpenSSL library methods openssl_encrypt and openssl_decrypt have padding turned on by default when you pass 0 as the options parameter. The default padding is PKCS#7.
So to solve your issue you will either need to add PaddingMode.PKCS7 to your C# code (which I personally recommend):
cryptoProvider.Padding = PaddingMode.PKCS7;
Or you turn off the padding in PHP using OPENSSL_ZERO_PADDING. Remember that in PHP you will need to add the flag OPENSSL_ZERO_PADDING to both openssl_encrypt and openssl_decrypt.
example:
$e = openssl_encrypt($text, 'des-ede3-cbc', $key, OPENSSL_ZERO_PADDING, $iv);
Important
Remember the padding options must be set on both encrypt and decrypt modes.
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.
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"))))
I have already implemented Rijandael 256 encryption on C# side which looks like this:
public static string EncryptPasswordForWordpressPlugin(string message)
{
const string Ivstring = "W4jlzx2XaqQTtbd67813xys4133tl2S7";
string keystring = "I7R9VdkzGQ215iCkC0940ST01Wk58Mr9";
byte[] key = ASCIIEncoding.UTF8.GetBytes(keystring);
byte[] iv = ASCIIEncoding.UTF8.GetBytes(Ivstring);
string encrypted = null;
var rj = new RijndaelManaged {BlockSize = 256};
rj.Key = key;
rj.IV = iv;
rj.Mode = CipherMode.CBC;
try
{
var ms = new MemoryStream();
using (var cs = new CryptoStream(ms, rj.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
using (var sw = new StreamWriter(cs))
{
sw.Write(message);
sw.Close();
}
cs.Close();
}
byte[] encoded = ms.ToArray();
encrypted = Convert.ToBase64String(encoded);
ms.Close();
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
rj.Clear();
}
return encrypted;
}
And in PHP I had decryption implementation with mcrypt:
class Decrypt {
protected $mcrypt_cipher = MCRYPT_RIJNDAEL_256;
protected $mcrypt_mode = MCRYPT_MODE_CBC;
protected $key = "I7R9VdkzGQ215iCkC0940ST01Wk58Mr9";
protected $iv = "W4jlzx2XaqQTtbd67813xys4133tl2S7";
public function decrypt($encrypted){
$iv_utf = mb_convert_encoding($this->iv, 'UTF-8');
return mcrypt_decrypt($this->mcrypt_cipher, $this->key, base64_decode($encrypted), $this->mcrypt_mode, $iv_utf);
}
}
Now with PHP 7.2 mcrypt is removed and I am looking for a way to implement decryption in PHP without changing C# side.
I am not really good with encryption/decryption and was not able to find properly solution.
Is it possible to implement this decryption using openssl in PHP or is there another way.
Thank you.