Padding is invalid when decrypt file - c#

static SymmetricAlgorithm encryption;
static string password = "SBC";
static string salt = "ash";
public Decryption()
{
encryption = new RijndaelManaged();
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(salt));
encryption.Key = key.GetBytes(encryption.KeySize / 8);
encryption.IV = key.GetBytes(encryption.BlockSize / 8);
encryption.Padding = PaddingMode.PKCS7;
}
public void Decrypt(Stream inStream, Stream OutStream)
{
ICryptoTransform encryptor = encryption.CreateDecryptor();
inStream.Position = 0;
CryptoStream encryptStream1 = new CryptoStream(OutStream, encryptor, CryptoStreamMode.Write);
CopyTo(inStream, encryptStream1);
encryptStream1.FlushFinalBlock();
encryptStream1.Close();
inStream.Close();
OutStream.Close();
}
public void CopyTo(Stream input, Stream output)
{
// This method exists only in .NET 4 and higher
byte[] buffer = new byte[4 * 1024];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
{
output.Write(buffer, 0, bytesRead);
}
}
In my windows form load i just create a thread and call the function to decrypt file, this is thread function
Thread objthreadhtml = new Thread(new ThreadStart(JsHtmlDecrypt));
objthreadhtml.IsBackground = true;
objthreadhtml.Name = "HtmlJsDecrypt";
objthreadhtml.Priority = ThreadPriority.Highest;
objthreadhtml.Start();
below function is decrypt function
public static void JsHtmlDecrypt()
{
string startPathForHtml = Application.LocalUserAppDataPath.Replace("\\OfflineApplication\\OfflineApplication\\1.0.0.0", "").ToString() + "\\Apps\\Html\\";
var directoryPathForHtml = new DirectoryInfo(startPathForHtml);
foreach (FileInfo fileForHtml in directoryPathForHtml.GetFiles())
{
FileStream inFsForHtml = fileForHtml.OpenRead();
FileInfo inforFHtml = new FileInfo(fileForHtml.FullName.Replace(fileForHtml.Extension, ".html"));
FileStream outFsForHtml = inforFHtml.Create();
UnZipDecryptionEncryption.Decryption m_decryption1 = new Decryption();
m_decryption1.Decrypt(inFsForHtml, outFsForHtml);
inFsForHtml.Close();
outFsForHtml.Close();
UnZipDecryptionEncryption.DeleteZipandFiles m_delete1 = new DeleteZipandFiles();
m_delete1.DeleteFiles(fileForHtml.FullName);
}
}
Here i get the error padding is invalid in the line
encryptStream1.FlushFinalBlock();
Please help me someone how to solve this i am stuck in it.

Your "decrypt" function is trying to do the opposite of what you want: encrypt the data:
CryptoStream encryptStream1 = new CryptoStream(OutStream, encryptor, CryptoStreamMode.Write);
What you want, I assume, is to decrypt it (my code uses byte arrays as input/output, so you may want to modify that):
ICryptoTransform decryptor = encryption.CreateDecryptor();
// byte[] (cipherText) <-- encryted text
MemoryStream memoryStream = new MemoryStream(cipherText);
// here is the most important part: CryptoStreamMode.Read
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherText.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
// my text uses UTF8 encoding, so to get the plain text as string:
string result = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);

Related

Encode CryptoStream to Base64 String in Chunks in C#

There is a method (Version1) that encodes an input stream and there is a function Decrypt() that successfully decodes encoded data. But when the input data is large there could be an error OutOfMemory (on the line "string textEncrypted = Convert.ToBase64String (ms.ToArray())").
Version1
private static Stream EncryptRijndael1(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] bytesEncrypted;
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] buffer = new byte[16 * 1024];
int readed;
while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readed);
}
}
string textEncrypted = Convert.ToBase64String(ms.ToArray());
bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted);
}
return new MemoryStream(bytesEncrypted);
}
So I modified the method to process an array part by part (chunks).
Here is Version2. It causes an error "offset and length must refer to a position in the string" in the line Convert.ToBase64String (ms.ToArray(), offset, read).
Version2
private static Stream EncryptRijndael2(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] bytesEncrypted;
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
string textEncrypted = String.Empty;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] buffer = new byte[16 * 1024];
int readed;
int offset = 0;
while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readed);
textEncrypted += Convert.ToBase64String(ms.ToArray(), offset, readed);
offset += readed;
}
}
bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted);
}
return new MemoryStream(bytesEncrypted);
}
Then I made Version3. It works without errors but the output data length now is bigger than in Version1 having the same input data.
Decryt() function throws an error "The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters."
Version3
private static Stream EncryptRijndael3(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] bytesEncrypted;
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
using (MemoryStream ms = new MemoryStream())
{
string textEncrypted = String.Empty;
using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] buffer = new byte[16*1024];
int readed;
while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readed);
}
}
byte[] buffer1 = new byte[16*1024];
int readed1;
using (MemoryStream ms1 = new MemoryStream(ms.ToArray()))
{
while ((readed1 = (ms1.Read(buffer1, 0, buffer1.Length))) > 0)
{
if (readed1 < buffer1.Length)
{
var lastBuf = new List<Byte>();
for (int i = 0; i < readed1; i++)
{
lastBuf.Add(buffer1[i]);
}
textEncrypted += Convert.ToBase64String(lastBuf.ToArray());
continue;
}
textEncrypted += Convert.ToBase64String(buffer1);
}
}
bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted);
}
return new MemoryStream(bytesEncrypted);
}
My RijndaelManaged
private static RijndaelManaged RijndaelManagedWithConfig(byte[] key, byte[] iv)
{
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 128;
rjndl.Key = key;
rjndl.IV = iv;
rjndl.Mode = CipherMode.CBC;
rjndl.Padding = PaddingMode.PKCS7;
return rjndl;
}
Please help me to get rid of the errors or tell me how to make the Version1 process Convert.ToBase64String data partially.
I have achieved the decision
private static Stream EncryptRijndael(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] buffer = new byte[5120 * 1024];
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
using (var memoryStream = new MemoryStream())
{
int readedBytes;
using (var cs = new CryptoStream(memoryStream, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
while ((readedBytes = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readedBytes);
}
}
using (var cryptoMemoryStream = new MemoryStream(memoryStream.ToArray()))
{
using (var base64MemoryStream = new MemoryStream())
{
using (ICryptoTransform transform = new ToBase64Transform())
{
using (var cryptStream = new CryptoStream(base64MemoryStream, transform, CryptoStreamMode.Write))
{
while ((readedBytes = cryptoMemoryStream.Read(buffer, 0, buffer.Length)) > 0)
{
cryptStream.Write(buffer, 0, readedBytes);
}
cryptStream.FlushFinalBlock();
}
return new MemoryStream(base64MemoryStream.ToArray());
}
}
}
}
}

Unity C# AES - Can't send IV

I am having a problem with my code and cannot figure out the problem.
With fullMsg set to false it works.
If I change fullMsg to true it no longer works even if I set it back to false.
I have no idea what is going on as the byte[] array remains the same in all the cases.
private void sendIndividualMsg(string msg){
//Debug.Log (msg);
byte[] toSend = PackageMsg (msg);
byte[] decoded = UnPackageMsg (toSend);
Debug.Log( System.Text.Encoding.ASCII.GetString(decoded) );
}
private byte[] UnPackageMsg(byte[] msg){
var toDecrypt = msg;
if (fullMsg) {
toDecrypt = new byte[msg.Length - 16];
var decryptIV = new byte[16];
System.Buffer.BlockCopy (msg, 0, decryptIV, 0, 16);
System.Buffer.BlockCopy (msg, 16, toDecrypt, 0, (msg.Length - 16));
//myAes.IV = decryptIV;
}
PrintByteArray (toDecrypt, "ToDecrypt");
byte[] plaintext;
// Create the streams used for decryption.
{
ICryptoTransform decryptor = myAes.CreateDecryptor (myAes.Key, myAes.IV);
MemoryStream msDecrypt = new MemoryStream ();
CryptoStream csDecrypt = new CryptoStream (msDecrypt, decryptor, CryptoStreamMode.Write);
csDecrypt.Write(msg, 0, msg.Length);
csDecrypt.FlushFinalBlock();
csDecrypt.Close();
plaintext = msDecrypt.ToArray();
msDecrypt.Close ();
decryptor.Dispose();
}
if (plaintext.Length > 16) {
byte[] hash = new byte[16];
byte[] hashCalc = new byte[16];
byte[] payload = new byte[plaintext.Length - 16 ];
System.Buffer.BlockCopy (plaintext, 0, hash, 0, 16);
System.Buffer.BlockCopy (plaintext, 16, payload, 0, plaintext.Length - 16);
hashCalc = md5.ComputeHash(payload);
if(ByteArrayCompare(hash, hashCalc)){
return payload;
}else{
return new byte[0];
}
} else {
return new byte[0];
}
}
private byte[] PackageMsg(string msg){
System.Text.ASCIIEncoding ue = new System.Text.ASCIIEncoding();
byte[] bytes = ue.GetBytes(msg);
byte[] hashBytes = md5.ComputeHash(bytes);
byte[] toEncrypt = new byte[bytes.Length + hashBytes.Length];
System.Buffer.BlockCopy(hashBytes, 0, toEncrypt, 0, hashBytes.Length);
System.Buffer.BlockCopy(bytes, 0, toEncrypt, hashBytes.Length, bytes.Length);
//myAes.GenerateIV();
byte[] encrypted;
{
ICryptoTransform encryptor = myAes.CreateEncryptor (myAes.Key, myAes.IV);
MemoryStream msEncrypt = new MemoryStream ();
CryptoStream csEncrypt = new CryptoStream (msEncrypt, encryptor, CryptoStreamMode.Write);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
csEncrypt.Close();
encrypted = msEncrypt.ToArray();
msEncrypt.Close ();
encryptor.Dispose();
}
PrintByteArray (encrypted, "Encrypted");
//SessionBytes + IV + ENCRYPTED( hash + msg)
byte[] finalMsg = new byte[myAes.IV.Length + encrypted.Length ];
System.Buffer.BlockCopy(myAes.IV, 0, finalMsg, 0 , myAes.IV.Length);
System.Buffer.BlockCopy(encrypted, 0, finalMsg, myAes.IV.Length , encrypted.Length);
if (!fullMsg) {
finalMsg = encrypted;
}
return finalMsg;
}
(I want to send the IV through each message, but until I get this working their is no point.)
Basic explanation of the algorithm for encrypting:
If fullMsg is set the encryption is [session][iv][encryptedmsg]
If fullMsg is not set the encryption is [encryptedmsg]
For Decryption the first part of the code is too extract just the encryptedmsg part.
As show by the screenshot of the logs, in both modes the bytes are the same.
--

Rijndael decryption returns weird ouput

I have used Rijndael Algorithm for Encryption and decryption.
The Decryption works fine when i do it with Encryption.
But when i try to do Decryption alone it returns something like this
J˿m"�e��c4�ħ�dB̵��Dq#W�.
Also i have used two buttons one is for encryption and another one is for decryption and called the methods when button clicks.
I cannot able to get any idea regarding why the output is returning like this. Even i used same convertion(UTF8 Encoding) for both methods.
Please help me to solve this problem.
Below is my code:
public partial class Form1 : Form
{
private RijndaelManaged myRijndael = new RijndaelManaged();
private int iterations;
private byte [] salt;
public Form1(string strPassword)
{
myRijndael.BlockSize = 128;
myRijndael.KeySize = 128;
myRijndael.IV = HexStringToByteArray("e84ad660c4721ae0e84ad660c4721ae0");
myRijndael.Padding = PaddingMode.PKCS7;
myRijndael.Mode = CipherMode.CBC;
iterations = 1000;
salt = System.Text.Encoding.UTF8.GetBytes("cryptography123example");
myRijndael.Key = GenerateKey(strPassword);
}
public string Encrypt(string strPlainText)
{
byte[] strText = new System.Text.UTF8Encoding().GetBytes(strPlainText);
MemoryStream ms = new MemoryStream();
ICryptoTransform transform = myRijndael.CreateEncryptor();
CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write);
cs.Write(strText, 0, strText.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.ToArray());
}
public string Decrypt(string encryptedText)
{
var encryptedBytes = Convert.FromBase64String(encryptedText);
MemoryStream ms = new MemoryStream();
ICryptoTransform transform = myRijndael.CreateDecryptor();
CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write);
cs.Write(encryptedBytes, 0, encryptedBytes.Length);
return System.Text.Encoding.UTF8.GetString(ms.ToArray());
}
public static byte[] HexStringToByteArray(string strHex)
{
dynamic r = new byte[strHex.Length / 2];
for (int i = 0; i <= strHex.Length - 1; i += 2)
{
r[i / 2] = Convert.ToByte(Convert.ToInt32(strHex.Substring(i, 2), 16));
}
return r;
}
private byte[] GenerateKey(string strPassword)
{
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(System.Text.Encoding.UTF8.GetBytes(strPassword), salt, iterations);
return rfc2898.GetBytes(128 / 8);
}
private void button1_Click(object sender, EventArgs e)
{
EncryptOutput.Text = Encrypt(EncryptInput.Text);
}
private void button2_Click(object sender, EventArgs e)
{
DecryptOutput.Text = Decrypt(DecryptInput.Text);
}
}
Try this code:
public string Encrypt(string strPlainText) {
byte[] strText = System.Text.Encoding.UTF8.GetBytes(strPlainText);
using (ICryptoTransform encryptor = myRijndael.CreateEncryptor())
using (MemoryStream input = new MemoryStream(strText))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write)) {
input.CopyTo(cs);
cs.FlushFinalBlock();
return Convert.ToBase64String(output.GetBuffer(), 0, (int)output.Length);
}
}
public string Decrypt(string encryptedText) {
byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
using (ICryptoTransform decryptor = myRijndael.CreateDecryptor())
using (MemoryStream input = new MemoryStream(encryptedBytes))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(input, decryptor, CryptoStreamMode.Read)) {
cs.CopyTo(output);
return System.Text.Encoding.UTF8.GetString(output.GetBuffer(), 0, (int)output.Length);
}
}
public static byte[] HexStringToByteArray(string strHex) {
var r = new byte[strHex.Length / 2];
for (int i = 0; i < strHex.Length; i += 2) {
r[i / 2] = byte.Parse(strHex.Substring(i, 2), NumberStyles.HexNumber);
}
return r;
}
Please, remember using the using pattern... And dynamic should be used only in very special cases.
Note that the Encrypt is doable with one less Stream, in a very similar way to the one you wrote it:
public string Encrypt(string strPlainText) {
byte[] strText = System.Text.Encoding.UTF8.GetBytes(strPlainText);
using (ICryptoTransform encryptor = myRijndael.CreateEncryptor())
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write)) {
cs.Write(strText, 0, strText.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(output.GetBuffer(), 0, (int)output.Length);
}
}
but the Decrypt needs two Stream, because the CryptoStream needs a Stream as a parameter, containing the encrypted data, and it is easier to write its output (of which you don't know the exact lenth, thanks to padding) to another stream.
cs.FlushFinalBlock(); forgotten in Decrypt()? I just round-tripped a test string with your code once I fixed that

C# CryptographicException length of the data to decrypt is invalid

I have this code which is meant to decrypt a file, but if I run it, it throws a CryptographicException (length of the data to decrypt is invalid) at the end of the using statement using (CryptoStream ...) { ... }
public static void DecryptFile(string path, string key, string saltkey, string ivkey)
{
try
{
byte[] cipherTextBytes;
using (StreamReader reader = new StreamReader(path)) cipherTextBytes = Encoding.UTF8.GetBytes(reader.ReadToEnd());
byte[] keyBytes = new Rfc2898DeriveBytes(key, Encoding.ASCII.GetBytes(saltkey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.None };
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(ivkey));
byte[] plainTextBytes;
using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
plainTextBytes = new byte[Encoding.UTF8.GetByteCount((new StreamReader(cryptoStream)).ReadToEnd())];
cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
//plainTextBytes = memoryStream.ToArray();
cryptoStream.FlushFinalBlock();
}
}
string result = Encoding.ASCII.GetString(plainTextBytes, 0, plainTextBytes.Length).TrimEnd("\0".ToCharArray());
using (FileStream writer = new FileStream(path, FileMode.Create)) writer.Write(Encoding.ASCII.GetBytes(result), 0, Encoding.ASCII.GetBytes(result).Length);
MessageBox.Show("Decrypt succesfull");
}
catch (Exception ex)
{
MessageBox.Show("An error while decrypting the file:\n\n" + ex, "Error");
}
}
}
Does anybody know why this is or how I can fix it? (I don't know if it comes from my encrypting method, but I have another program which uses the exact same thing to encrypt strings and that one does work.)
My encrypting method:
public static void EncryptFile(string path, string key, string saltkey, string ivkey)
{
try
{
byte[] TextBytes;
using (StreamReader reader = new StreamReader(path)) TextBytes = Encoding.UTF8.GetBytes(reader.ReadToEnd());
byte[] KeyBytes = new Rfc2898DeriveBytes(key, Encoding.ASCII.GetBytes(saltkey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(KeyBytes, Encoding.ASCII.GetBytes(ivkey));
byte[] CipherTextBytes;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(TextBytes, 0, TextBytes.Length);
cs.FlushFinalBlock();
CipherTextBytes = ms.ToArray();
}
}
using (FileStream writer = new FileStream(path, FileMode.Create)) writer.Write(CipherTextBytes, 0, CipherTextBytes.Length);
MessageBox.Show("Encrypt succesfull");
}
catch (Exception ex)
{
MessageBox.Show("An error while encrypting the file:\n\n" + ex, "Error");
}
}
There are a few issues with your code:
You use a padding mode of Zeroes in Encrypt and None in Decrypt. These need to match
You load the bytes from your file using Encoding.UTF8, you need to read the raw bytes, you can do this by using the following instead:
byte[] cipherTextBytes = File.ReadAllBytes(path);
You call cryptoStream.FlushFinalBlock(); when only using a single iteration of a stream. You don't need this call in Decrypt if you are only doing a single block iteration.
You read the original text from your file in UTF8 and then write it back as ASCII. You should either change the result assignment in decrypt to use UTF8 or (preferably) change both to use raw bytes.
You use Create to interact with the files when you are overwriting in-place. If you know the file already exists (as you are replacing it) you should use truncate or better yet just call File.WriteAllBytes.
Your decrypt is all kinds of messed up. It looks like you're tying yourself into knots over byte retrieval. You should just use the raw bytes out of the CryptoStream and not try using UTF8
Here's a revised set of methods for you:
public static void DecryptFile(string path, string key, string saltkey, string ivkey)
{
byte[] cipherTextBytes = File.ReadAllBytes(path);
byte[] keyBytes = new Rfc2898DeriveBytes(key, Encoding.ASCII.GetBytes(saltkey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CFB, Padding = PaddingMode.PKCS7 };
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(ivkey));
byte[] plainTextBytes;
const int chunkSize = 64;
using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
using (MemoryStream dataOut = new MemoryStream())
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
using (var decryptedData = new BinaryReader(cryptoStream))
{
byte[] buffer = new byte[chunkSize];
int count;
while ((count = decryptedData.Read(buffer, 0, buffer.Length)) != 0)
dataOut.Write(buffer, 0, count);
plainTextBytes = dataOut.ToArray();
}
File.WriteAllBytes(path, plainTextBytes);
}
and:
public static void EncryptFile(string path, string key, string saltkey, string ivkey)
{
byte[] TextBytes = File.ReadAllBytes(path);
byte[] KeyBytes = new Rfc2898DeriveBytes(key, Encoding.ASCII.GetBytes(saltkey)).GetBytes(256 / 8);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CFB, Padding = PaddingMode.PKCS7 };
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(KeyBytes, Encoding.ASCII.GetBytes(ivkey));
byte[] CipherTextBytes;
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(TextBytes, 0, TextBytes.Length);
cs.FlushFinalBlock();
CipherTextBytes = ms.ToArray();
}
File.WriteAllBytes(path, CipherTextBytes);
}
Most likely your problem comes from cipherTextBytes = Encoding.UTF8.GetBytes(reader.ReadToEnd());
You can't use UTF8 to encode arbitrary binary data, you will likely need to fix both your encrypting end decrypting end. You either must use cipherTextBytes = File.ReadAllBytes(path) or if you are forced to use strings you must first encode the bytes to a valid string using Convert.ToBase64String()
In my case it happened because I was decrypting a value which was never encrypted.
I had my values saved in the database without encryption. But when I introduced encryption and decryption routine in my code and executed my program first time, it was actually trying to decrypt a value which was never encrypted, hence the problem.
Simply clearing the existing values from the database for the initial run solved the problem. If you don't want to lose data even during the first run then you should write a separate routine to encrypt the existing values.

Encrypt large files in c#

Please help me modify this code to encrypt/decrypt in blocks instead of huge byte arrays! the code that converts the file and calls the encryption class is:
Console.Write("Enter File Path: ");
docPath = Console.ReadLine();
extension = docPath.Substring(docPath.IndexOf(".")).Trim();
byte[] binarydata = File.ReadAllBytes(docPath);
text = System.Convert.ToBase64String(binarydata, 0, binarydata.Length);
var Encrypted = AESCryptography.Encrypt(text, m.ToString(), extension);
using (FileStream fs = File.Create(docPath.Substring(0,docPath.IndexOf(".")) + ".aent"))
{
Byte[] info = new UTF8Encoding(true).GetBytes(Encrypted);
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
And the class that does the actual encryption is this:
public static class AESCryptography
{
private const int keysize = 256;
public static string Encrypt(string plainText, string passPhrase, string extention)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
{
byte[] keyBytes = password.GetBytes(keysize / 8);
using (RijndaelManaged symmetricKey = new RijndaelManaged())
{
symmetricKey.GenerateIV();
symmetricKey.Mode = CipherMode.CBC;
using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, symmetricKey.IV))
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
return Convert.ToBase64String(cipherTextBytes) + "\n" + Convert.ToBase64String(symmetricKey.IV) + "\n" + extention;
}
}
}
}
}
}
public static string Decrypt(string cipherText, string passPhrase, string initVector)
{
byte[] initVectorBytes = Convert.FromBase64String(initVector);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
{
byte[] keyBytes = password.GetBytes(keysize / 8);
using (RijndaelManaged symmetricKey = new RijndaelManaged())
{
symmetricKey.Mode = CipherMode.CBC;
using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
{
using (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);
}
}
}
}
}
}
}
I need the encryption class to be able to encrypt files as big as ~2.5GB.
I have tried multiple times, most didn't work others didn't even encrypt!
Please Help! I need to present this tomorrow!
You can 'chain' streams to encrypt large files, so you don't need to hold them in memory.
See answer from anton-gogolev https://stackoverflow.com/a/38629596/1776231 for question AES-Encrypt-then-MAC a large file with .NET
using(var encryptedFileStream = File.OpenWrite("..."))
using(var macCryptoStream = new CryptoStream(encryptedFileStream, mac, CryptoStreamMode.Write))
using(var encryptCryptoStream = new CryptoStream(macCryptoStream, encryptor, CryptoStreamMode.Write))
using(var inputFileStream = File.OpenRead("..."))
inputFileStream.CopyTo(encryptCryptoStream);

Categories