I'm trying to encrypt and decrypt streams using CryptoStream (Aes). These are the method I'm using:
public void Encrypt(Stream input, Stream output)
{
Aes aes = Aes.Create();
aes.Key = Key;
aes.IV = IV;
aes.Padding = PaddingMode.PKCS7;
//aes.Mode = CipherMode.CBC;
//aes.BlockSize = 128;
ICryptoTransform aesEncryptor = aes.CreateEncryptor();
using (CryptoStream cryptoStream = new(output, aesEncryptor, CryptoStreamMode.Write))
{
input.CopyTo(cryptoStream);
//cryptoStream.FlushFinalBlock();
cryptoStream.Flush();
cryptoStream.Close();
}
}
end
public void Decrypt(Stream input, Stream output)
{
Aes aes = Aes.Create();
aes.Key = Key;
aes.IV = IV;
aes.Padding = PaddingMode.PKCS7;
//aes.Mode = CipherMode.CBC;
//aes.BlockSize = 128;
ICryptoTransform aesDecryptor = aes.CreateDecryptor();
using (CryptoStream cryptoStream = new(input, aesDecryptor, CryptoStreamMode.Read))
{
cryptoStream.CopyTo(output);
cryptoStream.Flush();
cryptoStream.Close(); }
}
What I'm doing:
I generate a random text file. It has several lines, and the last one is "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMOPQRSTUVWXYZ_1234567890_0987654321"
I encrypt the file using the Encrypt method, passing FileStream(s) in input and output.
I decrypt the result using the Decrypt method, passing FileStream(s) in input and output.
What I obtain are files with the last line not equal (compared using the old but gold WinMerge): the original file, as I wrote, has the "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMOPQRSTUVWXYZ_1234567890_0987654321" line, while the result file has "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMOPQRSTUVWXYZ_1234567890_0987" (note that six final characters are missing).
Any idea on how to solve the problem?
Thanks to Mathias R. Jassen for the suggestion. Following the working code:
public void Encrypt(Stream input, Stream output)
{
Aes aes = Aes.Create();
aes.Key = Key;
aes.IV = IV;
aes.Padding = PaddingMode.PKCS7;
//aes.Mode = CipherMode.CBC;
//aes.BlockSize = 128;
ICryptoTransform aesEncryptor = aes.CreateEncryptor();
using (CryptoStream cryptoStream = new(output, aesEncryptor, CryptoStreamMode.Write))
{
input.CopyTo(cryptoStream);
cryptoStream.FlushFinalBlock();
}
}
and
public void Decrypt(Stream input, Stream output)
{
Aes aes = Aes.Create();
aes.Key = Key;
aes.IV = IV;
aes.Padding = PaddingMode.PKCS7;
//aes.Mode = CipherMode.CBC;
//aes.BlockSize = 128;
ICryptoTransform aesDecryptor = aes.CreateDecryptor();
using (CryptoStream cryptoStream = new(input, aesDecryptor, CryptoStreamMode.Read))
{
cryptoStream.CopyTo(output);
cryptoStream.Close();
}
output.Flush();
}
Please, note the
output.Flush()
command!
Related
I am trying to work out why a C# DLL I have is crashing since I added in AES encryption.
I initially put managed rijndael encryption in with a 256 bit key and 256 bit blocksize and the DLL worked, but I found out that the dotnet base receiving end only supports 128 bit blocksize.
However, when I changed the blocksize to 128 bits the DLL simply crashes when I encrypt. I also read the rijndael managed should not be used for new projects and so I tied other examples of AES for C#. All of THESE OTHER EXAMPLES once again crash the DLL as soon as the encrypt function is called.
I am generating both a 64 bit version of the DLL and a 32 bit version of the DLL, both crash as soon as I try to encrypt a string of around 1000 characters.
Is there some sort of initialisation I am missing, or do I need to increase memory / Stack size to use AES in the DLL? Would really value some suggestions as to why this doesn't work.
This worked for 256 bit blocksize, but crashes for 128 bit blocksize
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
Various other ways I have tried so far are below:
byte[] ivBytes = ComputeSHA256(iVphrase);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = ComputeSHA256(password);
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.Key = keyBytes;
aes.IV = ivBytes;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
ICryptoTransform crypto1 = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] encrypteddata = crypto1.TransformFinalBlock(plainTextBytes, 0, plainTextBytes.Length);
crypto1.Dispose();
return Convert.ToBase64String(encrypteddata);
byte[] encryptedData;
byte[] ivBytes = ComputeSHA256(iVphrase);
byte[] keyBytes = ComputeSHA256(password);
using (Aes aesAlgorithm = new AesManaged())
{
ICryptoTransform encryptor = aesAlgorithm.CreateEncryptor(keyBytes, ivBytes);
//Encryption will be done in a memory stream through a CryptoStream object
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(plainText);
}
encryptedData = ms.ToArray();
}
}
return Convert.ToBase64String(encryptedData);
}
byte[] ivBytes = ComputeSHA256(iVphrase);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = ComputeSHA256(password);
using (var symmetricKey = Aes.Create("AesManaged"))
{
symmetricKey.BlockSize = 128;
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.PKCS7;
symmetricKey.Key = keyBytes;
symmetricKey.IV = ivBytes;
using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
{
using (var memoryStream = new MemoryStream())
{
using (var cs = new CryptoStream(memoryStream, symmetricKey.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(plainTextBytes, 0, plainTextBytes.Length);
cs.Close();
}
var cipherBytes = memoryStream.ToArray();
memoryStream.Close();
return Convert.ToBase64String(cipherBytes);
}
}
}
I finally managed to get an exception output which identified the issue as being a 32 byte IV being passed in to a 128 bit Block size which generated an exception. On windows server machines the exception didn't return any result code, it simply crashed the machine. Testing on another windows 10 device correctly logged the incorrect IV length as an exception.
I am trying to decrypt a byte[] the length of 30601 with the following method
public static byte[] DecryptObject(byte[] recObj, byte[] aesKey, byte[] aesIV) {
using (Aes aes = Aes.Create()) {
aes.BlockSize = 128;
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.PKCS7;
aes.Key = aesKey;
aes.IV = aesIV;
using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV)) {
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write)) {
cs.Write(recObj, 0, recObj.Length);
cs.FlushFinalBlock();
return ms.ToArray();
}
}
}
}
I have confirmed the key and iv is the same in which I used to encrypt with, but its throwing the error on cs.FlushFinalBlock(); with error
System.Security.Cryptography.CryptographicException: 'The input data is not a complete block.'
I have tried other methods to get this resolved but they are not working.
I am using this to encrypt
public static byte[] EncryptAes(byte[] data, byte[] key, byte[] iv) {
using (var aes = Aes.Create()) {
aes.Padding = PaddingMode.PKCS7;
aes.Key = key;
aes.IV = iv;
using (var ms = new MemoryStream()) {
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write)) {
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
return ms.ToArray();
}
}
}
}
I am trying to decrypt Aes that was created from the JavaScript AES Encryptor from the CryptoJS library. I am trying to read a string that was encrypted by that library and decrypt it within my C# project using the following:
public static string Decrypt(string message, string secret, string salt = "zAvR2NI87bBx746n") {
return Encoding.UTF8.GetString(AESDecryptBytes(
Encoding.UTF8.GetBytes(message),
Encoding.UTF8.GetBytes(secret),
Encoding.UTF8.GetBytes(salt)
));
}
private static byte[] AESDecryptBytes(byte[] cryptBytes, byte[] passBytes, byte[] saltBytes) {
byte[] clearBytes = null;
// create a key from the password and salt, use 32K iterations
// var key = new Rfc2898DeriveBytes(passBytes, saltBytes, 32768);
var key = new Rfc2898DeriveBytes(passBytes, saltBytes, 1000);
using (Aes aes = new AesManaged()) {
// set the key size to 256
aes.KeySize = 256;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
using (MemoryStream ms = new MemoryStream()) {
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write)) {
cs.Write(cryptBytes, 0, cryptBytes.Length);
cs.Close();
}
clearBytes = ms.ToArray();
}
}
return clearBytes;
}
The data was encrypted in JavaScript as follows:
// data is a JSON string
// gs.cryptoSecret is a string of random characters
let saveData = CryptoJS.AES.encrypt(data || '', gs.cryptoSecret).toString()
When I attempt to use my method to decrypt the data I get the following error message:
CryptographicException: Invalid input block size.
Which is triggered by cs.Close();. It could be that secret hasn't been implemented, which I am not exactly sure where that would go in this...
How can I implement this decryptor to work alongside the JavaScript Library?
At the moment, I'm working on a project that involves encryption. Therefore, I have a class, which worked fine in .NET 4.0, but now that I changed it so it would work in .NET 2.0, it fails to encrypt almost any string... I don't know why, but it fails every time and throws a CryptographicException. Decrypting works fine as far as I can tell, and everything else too.
Anyway, here's the code:
public class Encryption
{
static readonly string PasswordHash = "P##Sw0rd";
static readonly string SaltKey = "S#LT&KEY";
static readonly string VIKey = "#1B2c3D4e5F6g7H8";
public static string Encrypt(string plainText, string passwordHash)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = new Rfc2898DeriveBytes(passwordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.None;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
byte[] cipherTextBytes;
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memoryStream.ToArray();
cryptoStream.Close();
}
memoryStream.Close();
}
return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string encryptedText, string passwordHash)
{
byte[] cipherTextBytes = Convert.FromBase64String(encryptedText);
byte[] keyBytes = new Rfc2898DeriveBytes(passwordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.None;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
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).TrimEnd("\0".ToCharArray());
}
}
The error message is (translated from German):
CryptographicException: Length of the data to encrypt is invalid. at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) at System.Security.Cryptography.CryptoStream.FlushFinalBlock() at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
Encryption.Encrypt("Client connected!", "elit3Nase") does not work
"Client connected!" is not long enough to fully fill a block (16 bytes) and you are not using padding:
symmetricKey.Padding = PaddingMode.None;
Change to symmetricKey.Padding = PaddingMode.PKCS7; to ensure padding is applied.
I am trying to encrypt a string of text using the RijndaelManaged class in .NET. However, I keep getting a CryptographicException ("Length of the data to decrypt is invalid"). This message isn't exactly helpful, especially since its happening when I attempt to ENCRYPT data, not decrypt. Below is the code.
public static string EncryptKMSToken(string valueToEncrypt, string encryptionKey)
{
string results = string.Empty;
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.BlockSize = 128;
aes.KeySize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
UTF8Encoding byteTransform = new UTF8Encoding();
aes.Key = byteTransform.GetBytes(encryptionKey);
ICryptoTransform encryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream encryptStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter writer = new StreamWriter(encryptStream))
{
writer.Write(valueToEncrypt);
}
byte[] encryptedBytes = stream.ToArray();
results = byteTransform.GetString(encryptedBytes);
}
}
}
return results;
}
The error happens when the 3rd using statement closes (i.e. the line after writer.Write(valueToEncrypt). If I try to move the two lines below that inside the third using block, I end up with an empty string (and the error still happens). I pulled this code directly off of this site (http://stackoverflow.com/questions/273452/using-aes-encryption-in-c-sharp) but it doesn't seem to work. Does anyone have any ideas?
Yes, but I think you will too if you reread your code:
ICryptoTransform encryptor = aes.CreateDecryptor(aes.Key, aes.IV);
That's a decryptor named as an encryptor...