I'm new to C #
and I generates a key
myRijndaelManaged.GenerateIV ();
myRijndaelManaged.GenerateKey ();
in Class
public string EncryptText(string plainText)
{
using (myRijndael = new RijndaelManaged())
{
RijndaelManaged myRijndaelManaged = new RijndaelManaged();
myRijndaelManaged.Mode = CipherMode.CBC;
myRijndaelManaged.Padding = PaddingMode.PKCS7;
myRijndaelManaged.GenerateIV();
myRijndaelManaged.GenerateKey();
string newKey = ByteArrayToHexString(myRijndaelManaged.Key);
string newinitVector = ByteArrayToHexString(myRijndaelManaged.IV);
byte[] encrypted = EncryptStringToBytes(plainText, myRijndael.Key, myRijndael.IV);
string encString = Convert.ToBase64String(encrypted);
return encString;
}
}
How to give the same keys in class
public string DecryptText(string encryptedString)
{
using (myRijndael = new RijndaelManaged())
{
myRijndael.Key =newKey;
myRijndael.IV = newinitVector;
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
Byte[] ourEnc = Convert.FromBase64String(encryptedString);
string ourDec = DecryptStringFromBytes(ourEnc, myRijndael.Key, myRijndael.IV);
return ourDec;
}
}
When I give another key I have a problem with
System.Security.Cryptography.CryptographicException: „Padding is invalid and cannot be removed.”
Although I am no expert at encryption but it still makes sense to me. I mean, you should pass the iv and key generated to the function that decrypts.
For example:
public string DecryptText(string encryptedString, string Iv, string Key)
{
using (myRijndael = new RijndaelManaged())
{
myRijndael.Key = Key;
myRijndael.IV = Iv;
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
Byte[] ourEnc = Convert.FromBase64String(encryptedString);
string ourDec = DecryptStringFromBytes(ourEnc, myRijndael.Key, myRijndael.IV);
return ourDec;
}
}
Well, I am not sure what the data types of the Iv and Key are, change them to suit yourself.
Related
how to generate a key and key IV and not write them explicitly?
public sealed class MyCryptoClass
{
protected RijndaelManaged myRijndael;
private static string encryptionKey = "142eb4a7ab52dbfb971e18daed7056488446b4b2167cf61187f4bbc60fc9d96d";
private static string initialisationVector ="26744a68b53dd87bb395584c00f7290a";
I try generate encryptionKey and initialisationVector
protected static readonly MyCryptoClass _instance = new MyCryptoClass();
public static MyCryptoClass Instance
{
get { return _instance; }
}
public string EncryptText(string plainText)
{
using (myRijndael = new RijndaelManaged())
{
myRijndael.Key = HexStringToByte(encryptionKey);
myRijndael.IV = HexStringToByte(initialisationVector);
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
byte[] encrypted = EncryptStringToBytes(plainText, myRijndael.Key, myRijndael.IV);
string encString = Convert.ToBase64String(encrypted);
return encString;
}
}
Let's do it step by step to keep things simple.
You need two methods to achieve your goal. I'll start with encryption method:
static byte[] Encrypt(string input, byte[] Key, byte[] IV)
{
byte[] encryptedBytes;
using (RijndaelManaged rijndael = new RijndaelManaged())
{
rijndael.Key = Key;
rijndael.IV = IV;
ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, rijndael.IV);
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream,
encryptor, CryptoStreamMode.Write))
{
using (var streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(input);
}
encryptedBytes = memoryStream.ToArray();
}
}
}
return encryptedBytes;
}
Then we need a Decrypt method subsequently:
static string Decrypt(byte[] cipher, byte[] Key, byte[] IV)
{
string plaintext = null;
using (RijndaelManaged rijndael = new RijndaelManaged())
{
rijndael.Key = Key;
rijndael.IV = IV;
ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);
using (var memoryStream = new MemoryStream(cipher))
{
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
using (var streamReader = new StreamReader(cryptoStream))
{
plaintext = streamReader.ReadToEnd();
}
}
}
}
return plaintext;
}
Note: It's better to wrap Encrypt and Decrypt methods in a class and then use them.
You can call the methods like below:
string original = "This is what would be encrypted!";
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
myRijndael.GenerateKey(); // this line generates key
myRijndael.GenerateIV(); // this line generates initialization vektor
// This line returns encrypted text
byte[] encryptedBytes = Encrypt(original, myRijndael.Key, myRijndael.IV);
// You can decrypt the encrypted text like so
string decryptedString = Decrypt(encryptedBytes, myRijndael.Key, myRijndael.IV);
}
I have the following lines in a PHP 7 program encrypting/decrypting data:
$key = base64_decode("mykey===");
$iv = substr(hash('sha256', "myiv======"), 0, 16);
printf(base64_encode(openssl_encrypt("hello", "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv)));
printf("<br>");
printf(openssl_decrypt(base64_decode("2XJxQXSbPuJ9LMsZ/FESGw=="), "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv));
This is working, PHP decrypts "hello" to "2XJxQXSbPuJ9LMsZ/FESGw==" and vice versa. However I'm trying to decrypt and encrypt the same data (from a Database) with C# but can't seem to figure it out. I used the following method for decryption (C#):
private string aes_decrypt(string cipherText, string key, string iv)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
aes.Key = Convert.FromBase64String(key);
aes.IV = Encoding.UTF8.GetBytes(iv);
if (aes.Key.Length < 32)
{
var paddedkey = new byte[32];
Buffer.BlockCopy(aes.Key, 0, paddedkey, 0, aes.Key.Length);
aes.Key = paddedkey;
}
var decrypt = aes.CreateDecryptor();
byte[] xBuff = null;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
byte[] xXml = Convert.FromBase64String(cipherText);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = ms.ToArray();
}
String Output = Encoding.UTF8.GetString(xBuff);
return Output;
}
But a call to this method:
string encryptionkey = "mykey===";
string encryptioniv = GenerateSHA256String("myiv======").Substring(0, 16);
string str = aes_decrypt("2XJxQXSbPuJ9LMsZ/FESGw==", encryptionkey, encryptioniv);
Console.WriteLine(#str);
returns: HellO++++??????+
The encryption method doesnt seem to work either (referenced online and modified):
private static String EncryptIt(String s, string akey, string aIV)
{
String result;
byte[] key = Convert.FromBase64String(akey);
byte[] IV = Encoding.UTF8.GetBytes(aIV);
RijndaelManaged rijn = new RijndaelManaged();
rijn.Mode = CipherMode.CBC;
rijn.Padding = PaddingMode.PKCS7;
rijn.KeySize = 256;
rijn.BlockSize = 128;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (ICryptoTransform encryptor = rijn.CreateEncryptor(key, IV))
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(s);
}
}
}
result = Convert.ToBase64String(msEncrypt.ToArray());
}
rijn.Clear();
return result;
}
A call to this method: EncryptIt("hello", encryptionkey, encryptioniv); returns ul0axDR0WWGcpeijPRNusg== and not 2XJxQXSbPuJ9LMsZ/FESGw== which was generated by PHP. Anyone knows what's wrong here?
For reference, I used these methods with the IV, they are working without errors:
private string GenerateSHA256String(string inputString)
{
SHA256 sha256 = SHA256Managed.Create();
byte[] bytes = Encoding.UTF8.GetBytes(inputString);
byte[] hash = sha256.ComputeHash(bytes);
return GetStringFromHash(hash);
}
private string GetStringFromHash(byte[] hash)
{
StringBuilder result = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
result.Append(hash[i].ToString("X2"));
}
return result.ToString();
}
Old question, but I ran into this again recently.
When using PHP 7.2 openssl_decrypt/openssl_encrypt padding as OPENSSL_RAW_DATA, it only worked for me when the chsarp AES padding was set to PaddingMode.PKCS7.
The original post has PaddingMode.None for decrypt and PaddingMode.PKCS7 for encrypt.
public static string Encrypt(this string plainText)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.Zeros;
aes.Mode = CipherMode.CBC;
aes.Key = Encoding.Default.GetBytes(key);
aes.GenerateIV();
ICryptoTransform AESEncrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] buffer = Encoding.ASCII.GetBytes(plainText);
String encryptedText = Convert.ToBase64String(Encoding.Default.GetBytes(Encoding.Default.GetString(AESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length))));
String mac = "";
using (var hmacsha256 = new HMACSHA256(Encoding.Default.GetBytes(key)))
{
hmacsha256.ComputeHash(Encoding.Default.GetBytes(Convert.ToBase64String(aes.IV) + encryptedText));
mac = ByteArrToString(hmacsha256.Hash);
}
var keyValues = new Dictionary<string, object>
{
{ "iv", Convert.ToBase64String(aes.IV) },
{ "value", encryptedText },
{ "mac", mac },
};
JavaScriptSerializer serializer = new JavaScriptSerializer();
//return serializer.Serialize(keyValues);
return Convert.ToBase64String(Encoding.ASCII.GetBytes(serializer.Serialize(keyValues)));
}
public static string Decrypt(this string cipherText)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.Zeros;
aes.Mode = CipherMode.CBC;
aes.Key = Encoding.Default.GetBytes(key);
dynamic payload = GetJsonPayload(cipherText);
//return Encoding.Default.GetString(Convert.FromBase64String(cipherText));
//cipherText = Convert.ToBase64String(Encoding.Default.GetBytes(payload["value"]));
aes.IV = Convert.FromBase64String(payload["iv"]);
ICryptoTransform AESDecrypt = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] buffer = Convert.FromBase64String(payload["value"]);
return (Encoding.Default.GetString(AESDecrypt.TransformFinalBlock(buffer, 0, buffer.Length))).ToString();
}
https://github.com/laravel/framework/blob/5.1/src/Illuminate/Encryption/Encrypter.php
i am using the code above, it works when i decrypt anything from Laravel. problem is when i encrypt a string from c#, i cannot decrypt it in php.
sometimes there are "values" after the decrypted text. encrypting the output, and decrypting it in php works.
changing the padding to PaddingMode.PKCS7 works! in case other people still need this one, full code are posted below.
public static string Encrypt(this string plainText)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = Encoding.Default.GetBytes(key);
aes.GenerateIV();
ICryptoTransform AESEncrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] buffer = Encoding.ASCII.GetBytes(plainText);
String encryptedText = Convert.ToBase64String(Encoding.Default.GetBytes(Encoding.Default.GetString(AESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length))));
String mac = "";
using (var hmacsha256 = new HMACSHA256(Encoding.Default.GetBytes(key)))
{
hmacsha256.ComputeHash(Encoding.Default.GetBytes(Convert.ToBase64String(aes.IV) + encryptedText));
mac = ByteArrToString(hmacsha256.Hash);
}
var keyValues = new Dictionary<string, object>
{
{ "iv", Convert.ToBase64String(aes.IV) },
{ "value", encryptedText },
{ "mac", mac },
};
JavaScriptSerializer serializer = new JavaScriptSerializer();
//return serializer.Serialize(keyValues);
return Convert.ToBase64String(Encoding.ASCII.GetBytes(serializer.Serialize(keyValues)));
}
public static string Decrypt(this string cipherText)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = Encoding.Default.GetBytes(key);
dynamic payload = GetJsonPayload(cipherText);
//return Encoding.Default.GetString(Convert.FromBase64String(cipherText));
//cipherText = Convert.ToBase64String(Encoding.Default.GetBytes(payload["value"]));
aes.IV = Convert.FromBase64String(payload["iv"]);
ICryptoTransform AESDecrypt = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] buffer = Convert.FromBase64String(payload["value"]);
return (Encoding.Default.GetString(AESDecrypt.TransformFinalBlock(buffer, 0, buffer.Length))).ToString();
}
Since Laravel uses base64: in the APP_KEY, the code to achieve the laravel encryption in C# has slightly changed:
private string encrypt(string plainText)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = Convert.FromBase64String(key);
aes.GenerateIV();
ICryptoTransform AESEncrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] buffer = Encoding.ASCII.GetBytes(phpSerialize(plainText));
String encryptedText = Convert.ToBase64String(Encoding.Default.GetBytes(Encoding.Default.GetString(AESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length))));
String mac = "";
using (var hmacsha256 = new HMACSHA256(Convert.FromBase64String(key)))
{
hmacsha256.ComputeHash(Encoding.Default.GetBytes(Convert.ToBase64String(aes.IV) + encryptedText));
mac = ByteToString(hmacsha256.Hash);
}
var keyValues = new Dictionary<string, object>
{
{ "iv", Convert.ToBase64String(aes.IV) },
{ "value", encryptedText },
{ "mac", mac },
};
JavaScriptSerializer serializer = new JavaScriptSerializer();
//return serializer.Serialize(keyValues);
return Convert.ToBase64String(Encoding.ASCII.GetBytes(serializer.Serialize(keyValues)));
}
with $key the APP_KEY without the "base64:" part and
private string phpSerialize(String value)
{
return "s:" + value.Length + ":" + "\"" + value + "\";";
}
for the serialization (only for strings, but there are complete libraries to achieve this)
And finally the ByteToString function:
private string ByteToString(byte[] buff)
{
string sbinary = "";
for (int i = 0; i < buff.Length; i++)
sbinary += buff[i].ToString("x2"); /* hex format */
return sbinary;
}
Why it does get wrong results?
It not pkcs7 supported by the crypto ++?
I would like to know the value of the result to be like what to do.
Iv value is equal to the supposed well-delivered.
// c# code
private byte[] _iv;
private readonly string key = "7794b12op901252bfcea66d6f0521212";
public string decrypt(string Input)
{
string str = "";
RijndaelManaged managed = new RijndaelManaged();
managed.KeySize = 128;
managed.BlockSize = 128;
managed.Mode = CipherMode.CBC;
managed.Padding = PaddingMode.Zeros;
managed.Key = Encoding.UTF8.GetBytes(this.key);
managed.IV = this._iv;
try
{
ICryptoTransform transform = managed.CreateDecryptor();
byte[] bytes = null;
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
byte[] buffer = Convert.FromBase64String(Input);
stream2.Write(buffer, 0, buffer.Length);
}
bytes = stream.ToArray();
}
str = Encoding.ASCII.GetString(bytes);
}
catch (Exception)
{
}
return str;
}
public string encrypt(string Input)
{
RijndaelManaged managed = new RijndaelManaged();
managed.KeySize = 128;
managed.BlockSize = 128;
managed.Mode = CipherMode.CBC;
managed.Padding = PaddingMode.Zeros;
managed.Key = Encoding.ASCII.GetBytes(this.key);
managed.GenerateIV();
this._iv = managed.IV;
ICryptoTransform transform = managed.CreateEncryptor(managed.Key, managed.IV);
byte[] inArray = null;
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
byte[] bytes = Encoding.UTF8.GetBytes(Input);
stream2.Write(bytes, 0, bytes.Length);
}
inArray = stream.ToArray();
}
return Convert.ToBase64String(inArray);
}
Below is qt5 code.
Omit details.
QT code
QString aeskey = "7794b12op901252bfcea66d6f0521212";
QString _iv;
void Cipher::GenerateIV()
{
AutoSeededRandomPool rnd;
byte iv3[AES::BLOCKSIZE];
rnd.GenerateBlock(iv3, AES::BLOCKSIZE);
QByteArray out((char*)iv3, AES::BLOCKSIZE);
_iv = out.toBase64();
}
QString Cipher::AESencrypt(QString Qstr_in)
{
string str_in = Qstr_in.toStdString();
string key = aeskey.toStdString();
GenerateIV();
string iv = _iv.toStdString();
string str_out;
CBC_Mode<AES>::Encryption encryption;
encryption.SetKeyWithIV((byte*)key.c_str(), key.length(), (byte*)iv.c_str());
StringSource encryptor(str_in, true,
new StreamTransformationFilter(encryption,
new Base64Encoder(
new StringSink(str_out)
// ,StreamTransformationFilter::PKCS_PADDING
,StreamTransformationFilter::ZEROS_PADDING
)
)
);
return QString::fromStdString(str_out);
}
QString Cipher::AESdecrypt(QString Qstr_in)
{
string str_in = Qstr_in.toStdString();
string key = aeskey.toStdString();
string iv = _iv.toStdString();
string str_out;
CBC_Mode<AES>::Decryption decryption;
decryption.SetKeyWithIV((byte*)key.c_str(), key.length(), (byte*)iv.c_str());
StringSource decryptor(str_in, true,
new Base64Decoder(
new StreamTransformationFilter(decryption,
new StringSink(str_out)
// ,StreamTransformationFilter::PKCS_PADDING
,StreamTransformationFilter::DEFAULT_PADDING
)
)
);
return QString::fromStdString(str_out);
}
I don't understand really what your question is and I can't really comment so here what I think:
ICryptoTransform transform = managed.CreateEncryptor(managed.Key, managed.IV);
ICryptoTransform transform = managed.CreateDecryptor();
Both need key and IV, or at least need to be the same....
Then you used once Rijndael then AES. You could use AES in you C# too.
A couple things jump out... In C# code, you do this:
private readonly string key = "7794b12op901252bfcea66d6f0521212";
...
managed.Key = Encoding.UTF8.GetBytes(this.key);
In Crypto++ code, you do this:
QString aeskey = "7794b12op901252bfcea66d6f0521212";
...
string key = aeskey.toStdString();
You need to HexDecode the string in Crypto++.
Also, GenerateIV Base64 encodes on the Qt side of things:
AutoSeededRandomPool rnd;
byte iv3[AES::BLOCKSIZE];
rnd.GenerateBlock(iv3, AES::BLOCKSIZE);
QByteArray out((char*)iv3, AES::BLOCKSIZE);
_iv = out.toBase64();
But C# uses a byte[] (presumably not Base64 encoded):
private byte[] _iv;
Every time I run this and encrypt, the output is variable, and when I attempt to decrypt
I get "Padding is invalid and cannot be removed." Been fighting with this for a day or two now and I am at a loss.
private static string strIV = "abcdefghijklmnmo"; //The initialization vector.
private static string strKey = "abcdefghijklmnmoabcdefghijklmnmo"; //The key used to encrypt the text.
public static string Decrypt(string TextToDecrypt)
{
return Decryptor(TextToDecrypt);
}
private static string Encryptor(string TextToEncrypt)
{
//Turn the plaintext into a byte array.
byte[] PlainTextBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToEncrypt);
//Setup the AES providor for our purposes.
AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);
aesProvider.BlockSize = 128;
aesProvider.KeySize = 256;
aesProvider.Padding = PaddingMode.PKCS7;
aesProvider.Mode = CipherMode.CBC;
ICryptoTransform cryptoTransform = aesProvider.CreateEncryptor(aesProvider.Key, aesProvider.IV);
byte[] EncryptedBytes = cryptoTransform.TransformFinalBlock(PlainTextBytes, 0, PlainTextBytes.Length);
return Convert.ToBase64String(EncryptedBytes);
}
private static string Decryptor(string TextToDecrypt)
{
byte[] EncryptedBytes = Convert.FromBase64String(TextToDecrypt);
//Setup the AES provider for decrypting.
AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);
aesProvider.BlockSize = 128;
aesProvider.KeySize = 256;
aesProvider.Padding = PaddingMode.PKCS7;
aesProvider.Mode = CipherMode.CBC;
ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV);
byte[] DecryptedBytes = cryptoTransform.TransformFinalBlock(EncryptedBytes, 0, EncryptedBytes.Length);
return System.Text.Encoding.ASCII.GetString(DecryptedBytes);
}
}
You need to set the BlockSize and the KeySize before you set the Key and the IV. Additionally you should probably be generating a random IV for each message and note that ICryptoTransform implements IDisposable so these objects should be disposed.