How to get the generated IV from encryption to decryption method - c#

I didn't want to seed the IV with the user given password. The question is if I've created the method of encrypting with a generated IV, is there anyway I could save the generated IV, to get it into the decryption method, without saving it into a database.
private void EncryptFile(string inputFile,string outputFile, string pass_input){
try
{
MessageBox.Show("FLAG 1");
UTF8Encoding UE = new UTF8Encoding();
//Represents a UTF-8 encoding of unicode characters
string password = pass_input;
// passed password through user input
byte[] key = UE.GetBytes(password);
//password parsed into bytes
string cryptFile = outputFile;
FileStream FScrypt = new FileStream(cryptFile, FileMode.Create);
//FScrypt is created where it creates a file to save output
RijndaelManaged RMcrypto = new RijndaelManaged();
//RMcrypto is created where new instance of RijndaelManaged Class is initialized
RMcrypto.GenerateIV();
CryptoStream cs = new CryptoStream(FScrypt, RMcrypto.CreateEncryptor(key,RMcrypto.IV), CryptoStreamMode.Write);
//CreateEncryptor from RMcrypto creates a symmetric Rijndael Encryptor object with specified key
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
//fsIn Opens the input file
MessageBox.Show("FLAG 2");
int data;
while ((data = fsIn.ReadByte()) != -1)
//will read input file opened by fsIn
cs.WriteByte((byte)data);
MessageBox.Show("FLAG 3");
fsIn.Close();
cs.Close();
FScrypt.Close();
catch(Exception ex)
{
MessageBox.Show("Failed");
}
}
private void DecryptFile(string inputFile, string outputFile, string pass_input)
{
try
{
string password = pass_input; // Taking password input and storing in local string.
UTF8Encoding UE = new UTF8Encoding() //UnicodeEncoding Object UTF8
byte[] key = UE.GetBytes(password); // converting password to bytes
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open); // Opens the file
RijndaelManaged RMCrypto = new RijndaelManaged(); //new RijndaelMaaged object
CryptoStream cs = new CryptoStream(fsCrypt, RMCrypto.CreateDecryptor(key, **"RMCrypto.IV"**), CryptoStreamMode.Read);
FileStream fsOut = new FileStream(outputFile, FileMode.Create);
int data;
while ((data = cs.ReadByte()) != -1)
fsOut.WriteByte((byte)data);
fsOut.Close();
cs.Close();
fsCrypt.Close();
}
catch (Exception ex)
{
MessageBox.Show("Failed");
}
}

One well used/accepted method is to prepend the IV to the encrypted data, the IV does not need to be secret.

Related

word file (doc, docx) damaged after encryption and decryption

i have tried the following code to encrypt and decrypt files using asp.net c# rijndael managed. all of the images notepad is encrypted and decrypted successfully, when it comes to doc or docx file it always showing damaged file when i tried to open. but if i click resolve this issue in microsoft word, then the file is back. what could go wrong in the code. please help me
public void EncryptFile(string password, string inputFile, string outputFile)
{
try
{
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password.Trim());
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream cs = new CryptoStream(fsCrypt,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
cs.WriteByte((byte)data);
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
catch(Exception err)
{
System.Diagnostics.Debug.WriteLine(err);
}
}
public void DecryptFile(string password, string inputFile, string outputFile)
{
try
{
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password.Trim());
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream cs = new CryptoStream(fsCrypt,
RMCrypto.CreateDecryptor(key, key),
CryptoStreamMode.Read);
FileStream fsOut = new FileStream(outputFile, FileMode.Create);
int data;
while ((data = cs.ReadByte()) != -1)
fsOut.WriteByte((byte)data);
fsOut.Close();
cs.Close();
fsCrypt.Close();
}
catch(Exception err)
{
System.Diagnostics.Debug.WriteLine(err);
}
}

Admin credential issue when encrypting files

I am using rijndael encryption method to encrypt configuration file to keep it safe in client system. But after encryption, when a new file is generated, it comes with admin credential and i am not able to read it.
public void EncryptFile(string inputFile, string outputFile)
{
try
{
string password = #"myKey"; // Your Key Here
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream cs = new CryptoStream(fsCrypt,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
cs.WriteByte((byte)data);
fsIn.Close();
cs.Close();
fsCrypt.Close();
FileInfo fi = new FileInfo(inputFile);
fi.Delete();
}
catch
{
Console.WriteLine("Encryption failed!", "Error");
}
}
I am using this method. When i run it in build mode it works perfectly but when i create a setup it fails and creates encrypted file with admin credential which i am not able to read. I am Using Install Shield 2013 limited edition.

CryptographicException: Length of the data to decrypt is invalid

I get "Length of the data to decrypt is invalid" when I try to decrypt my file.
public class EncryptDecrypt
{
// Call this function to remove the key from memory after use for security
[System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint = "RtlZeroMemory")]
public static extern bool ZeroMemory(IntPtr Destination, int Length);
// Function to Generate a 64 bits Key.
public static string GenerateKey()
{
// Create an instance of Symetric Algorithm. Key and IV is generated automatically.
DESCryptoServiceProvider desCrypto = (DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
// Use the Automatically generated key for Encryption.
return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
}
public static void EncryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
FileStream fsInput = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
FileStream fsEncrypted = new FileStream(sOutputFilename,
FileMode.Create,
FileAccess.Write);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
CryptoStream cryptostream = new CryptoStream(fsEncrypted,
desencrypt,
CryptoStreamMode.Write);
byte[] bytearrayinput = new byte[fsInput.Length];
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Close();
fsInput.Close();
fsEncrypted.Close();
}
public static void DecryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
//A 64 bit key and IV is required for this provider.
//Set secret key For DES algorithm.
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
//Set initialization vector.
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
//Create a file stream to read the encrypted file back.
FileStream fsread = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
//Create a DES decryptor from the DES instance.
ICryptoTransform desdecrypt = DES.CreateDecryptor();
//Create crypto stream set to read and do a
//DES decryption transform on incoming bytes.
CryptoStream cryptostreamDecr = new CryptoStream(fsread,
desdecrypt,
CryptoStreamMode.Read);
//Print the contents of the decrypted file.
StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
fsDecrypted.Flush();
fsDecrypted.Close();
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// Must be 64 bits, 8 bytes.
// Distribute this key to the user who will decrypt this file.
string sSecretKey;
//ExportCSV.EncryptDecrypt c = new EncryptDecrypt();
// Get the Key for the file to Encrypt.
sSecretKey = EncryptDecrypt.GenerateKey();
// For additional security Pin the key.
GCHandle gch = GCHandle.Alloc(sSecretKey, GCHandleType.Pinned);
// Encrypt the file.
EncryptDecrypt.EncryptFile(#"C:\Test\Sample.xml",
#"C:\Test\Encrypted.xml",
sSecretKey);
// Decrypt the file.
EncryptDecrypt.DecryptFile(#"C:\Test\Sample.xml",
#"C:\Test\Decrypted.xml",
sSecretKey);
// Remove the Key from memory.
EncryptDecrypt.ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2);
gch.Free();
}
I get the error while trying to write the decrypted data to file
fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
Please let me know what I am missing.

Exception while encrypting audio file

while encrypting an audio file using C#, i got an exception that "Specified inetialisation vector(IV) does not match the block size of the algorithm". and i'm using Rijndael algorithm provided by the cryptography class. what i'm supposed to do to solve this exception?
my code is given below:
public void EncryptFile(string inputFile, string outputFile)
{
try
{
inputFile = textBox_path.Text;
String password = "keykey";
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream cs = new CryptoStream(fsCrypt, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
cs.WriteByte((byte)data);
fsIn.Close();
cs.Close();
fsCrypt.Close();
MessageBox.Show("encryption is completed!!");
}
catch(Exception e)
{
MessageBox.Show(e.Message);
}
}
and my function call is:
There is a similar question here.
With Rijndael, you can choose the block sizes 128, 160, 192, 224, or 256 bits. Then you must choose an initialization vector of the same length:
using (RijndaelManaged rm = new RijndaelManaged())
{
rm.BlockSize = 128;
Rfc2898DeriveBytes keyDerivator = new Rfc2898DeriveBytes(password, salt, KeyGenIterationCount); //derive key and IV from password and salt using the PBKDF2 algorithm
rm.IV = keyDerivator.GetBytes(16); //16 bytes (128 bits, same as the block size)
rm.Key = keyDerivator.GetBytes(32);
//(encrypt here)
}
In any case, I would recommend using the AesCryptoServiceProvider class instead, since it's FIPS-compilant. Read more about the differences here: http://blogs.msdn.com/b/shawnfa/archive/2006/10/09/the-differences-between-rijndael-and-aes.aspx

How to decrypt an AES-256-CBC encrypted string

I'm new to C# and I really need help. I need to encrypt/decrypt a string with AES-256-CBC in C#, I found this to encrypt a string:
public static string EncryptString(string message, string KeyString, string IVString)
{
byte[] Key = ASCIIEncoding.UTF8.GetBytes(KeyString);
byte[] IV = ASCIIEncoding.UTF8.GetBytes(IVString);
string encrypted = null;
RijndaelManaged rj = new RijndaelManaged();
rj.Key = Key;
rj.IV = IV;
rj.Mode = CipherMode.CBC;
try
{
MemoryStream ms = new MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(message);
sw.Close();
}
cs.Close();
}
byte[] encoded = ms.ToArray();
encrypted = Convert.ToBase64String(encoded);
ms.Close();
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
rj.Clear();
}
return encrypted;
}
I tried to write a decrypt function base on the above code, the following code is what I did:
// Decrypt a byte array into a byte array using a key and an IV
private byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV)
{
byte[] decryptedData;
//string plaintext = null;
//MemoryStream ms = new MemoryStream(cipherData);
RijndaelManaged alg = new RijndaelManaged();
alg.KeySize = 256;
alg.BlockSize = 128;
alg.Key = Key;
alg.IV = IV;
alg.Mode = CipherMode.CBC;
alg.Padding = PaddingMode.Zeros;
//Array.Copy(Key, 0, IV, 0, IV.Length);
ICryptoTransform decryptor = alg.CreateDecryptor(alg.Key, alg.IV);
using(MemoryStream ms = new MemoryStream(cipherData))
{
using (CryptoStream csDecrypt = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader sw = new StreamReader(csDecrypt))
{
sw.ReadToEnd();
sw.Close();
}
csDecrypt.Close();
decryptedData = ms.ToArray();
}
}
//byte[] decryptedData = System.Text.Encoding.Unicode.GetBytes(plaintext);
return decryptedData;
}
But it's nonsense, it can't decrypt anything. I'm really confused and need help. Thank you for any help!
P/s: Please don't give me other similar answered questions, I already take a look at them. Their encrypt function doesn't have the same output like the above encrypt function, while I need to decrypt string which MUST be encrypt by the above function. I have two friend who wrote decrypt function in PHP and objective-C, which matched with the above encrypt function, it's bad to have them do it again.
Looking at your encryption, something like this should do it, passing the resulting string from your encryption in should give the original string back;
// Decrypt a string into a string using a key and an IV
public static string Decrypt(string cipherData, string keyString, string ivString)
{
byte[] key = Encoding.UTF8.GetBytes(keyString);
byte[] iv = Encoding.UTF8.GetBytes(ivString);
try
{
using (var rijndaelManaged =
new RijndaelManaged {Key = key, IV = iv, Mode = CipherMode.CBC})
using (var memoryStream =
new MemoryStream(Convert.FromBase64String(cipherData)))
using (var cryptoStream =
new CryptoStream(memoryStream,
rijndaelManaged.CreateDecryptor(key, iv),
CryptoStreamMode.Read))
{
return new StreamReader(cryptoStream).ReadToEnd();
}
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
// You may want to catch more exceptions here...
}
A small note; you're getting the key using UTF8 encoding from the key string, UTF8 encoding may give you multiple bytes back for international characters, which may give a key or IV of the wrong length for encryption/decryption. Also, using the small range of passwords/keys with 8 characters and printable characters will not give you very secure encryption, you may want to run the string though SHA1 or similar before using it as a key (which will sadly make it incompatible with the current encryption)

Categories