My problem is that the created encrypted zip file is unable to open after decrypting it. It says the compressed file is invalid. File it self almost doubled it's initial space after decrypting from 15 KB to 27 KB. The problem occours on zip files, when I encrypted and decryped a xml file it worked just fine. Below my whole code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace EDI
{
public class EncryptionHelper
{
public void Main()
{
var file = #"C:\Temp\test.zip";
AesCryptoServiceProvider AES = new AesCryptoServiceProvider();
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CBC;
AES.BlockSize = 128;
AES.KeySize = 128;
AES.GenerateKey();
AES.GenerateIV();
var key = AES.Key;
var iv = AES.IV;
encryptAES(AES, file, key, iv);
decryptAES(AES, file + ".encrypted", key, iv);
}
public void encryptAES(SymmetricAlgorithm algo, string filePath, byte[] key, byte[] IV)
{
using (FileStream fin = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (FileStream fout = new FileStream(filePath + ".encrypted", FileMode.OpenOrCreate, FileAccess.Write))
{
using (ICryptoTransform crypt = algo.CreateEncryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fout, crypt, CryptoStreamMode.Write))
{
fin.CopyTo(crStream);
}
}
}
}
}
public void decryptAES(SymmetricAlgorithm algo, string filePath, byte[] key, byte[] IV)
{
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (ICryptoTransform crypt = algo.CreateDecryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(crStream))
{
string data = reader.ReadToEnd();
File.WriteAllText(filePath.Replace(".encrypted", ".restored"), data);
}
}
}
}
}
}
}
Edit to show the fix.
using (FileStream writer = new FileStream(filePath + ".decrypted", FileMode.Create, FileAccess.Write))
// using (Read reader = new StreamReader(crStream))
{
// string data = reader.ReadToEnd();
// File.WriteAllText(filePath.Replace(".encrypted", ".restored"), data);
crStream.CopyTo(writer);
}
Related
I have two functions that should encrypt and decrypt a given file:
public static void Encrypt(string name, string skey)
{
using (var sourceStream = File.OpenRead(name))
using (var destinationStream = File.Create(name + ".sav"))
using (var provider = new AesCryptoServiceProvider())
using (var cryptoTransform = provider.CreateEncryptor())
using (var cryptoStream = new CryptoStream(destinationStream, cryptoTransform, CryptoStreamMode.Write))
{
provider.Padding = PaddingMode.None;
List<byte> key = new List<byte>();
key.AddRange(ASCIIEncoding.ASCII.GetBytes(skey));
while (key.Count < 32)
{
key.Add(0);
}
provider.Key = key.ToArray();
destinationStream.Write(provider.IV, 0, provider.IV.Length);
sourceStream.CopyTo(cryptoStream);
}
}
public static void Decrypt(string name, string skey)
{
// Decrypt the source file and write it to the destination file.
using (var sourceStream = File.OpenRead(name + ".sav"))
using (var destinationStream = File.Create(name))
using (var provider = new AesCryptoServiceProvider())
{
provider.Padding = PaddingMode.None;
List<byte> key = new List<byte>();
key.AddRange(ASCIIEncoding.ASCII.GetBytes(skey));
while(key.Count < 32)
{
key.Add(0);
}
var IV = new byte[provider.IV.Length];
sourceStream.Read(IV, 0, IV.Length);
using (var cryptoTransform = provider.CreateDecryptor(key.ToArray(), IV))
using (var cryptoStream = new CryptoStream(sourceStream, cryptoTransform, CryptoStreamMode.Read))
{
cryptoStream.CopyTo(destinationStream);
}
}
}
Using the text document (d):
<?xml version="1.0" encoding="utf-8"?>
<Game xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<username>d</username>
<superSecretString>foo</superSecretString>
</Game>
The following program:
static void Main(string[] args)
{
string pass = "foo";
Encrypt("d", pass);
Decrypt("d", pass);
}
Results in the text document (d):
豄襚釞뮲冋ⵂૠɥ摸▪穨嶾⏘ﳿ僣ꙍ帏પ軆ꝍ遨䄩䰀玢⊟尩㯇Ўꉚ파 駧㪡襻긗몸뵊➯턊鏶㠌늸㗐蕛貣ㆪⲫ咻ꨱ壉뷢䅱眡�׀罹吗㶝�晊垚猰Ġ�淧脽ᣉ赮榑舎㈁쾹͂쵎숵戥힠┻蔦쬦눲ꔲ빬䁔㸻�ⵄ➞ޅ㥿࠾ऱ룮2侚神ヵ튙腶㖮衦ྗ
It seems that decrypting the message is causing the unexpected result however I don't what I should expect in the "*.sav" files besides random noise. Checking the watchlist provider.key is an array that reads out 102, 111, 111, 0 ... 0 in both Encrypt and Decrypt methods.
Okay so your problem is that you are creating Encryptor but never set it's IV.
Change the Encrypt method like so:
public static void Encrypt(string name, string skey)
{
// First, process key
List<byte> key = new List<byte>();
key.AddRange(ASCIIEncoding.ASCII.GetBytes(skey));
while (key.Count < 32)
{
key.Add(0);
}
using (var sourceStream = File.OpenRead(name))
using (var destinationStream = File.Create(name + ".sav"))
using (var provider = new AesCryptoServiceProvider())
using (var cryptoTransform = provider.CreateEncryptor(key.ToArray(), provider.IV)) // when creating Encryptor pass the key and the IV of the provider.
using (var cryptoStream = new CryptoStream(destinationStream, cryptoTransform, CryptoStreamMode.Write))
{
provider.Padding = PaddingMode.None;
provider.Key = key.ToArray();
destinationStream.Write(provider.IV, 0, provider.IV.Length);
sourceStream.CopyTo(cryptoStream);
}
}
I'm doing my homework. It's connected with encryption of file.
I use algorithm Salsa20
Here's my code:
using (var salsa = new Salsa20.Salsa20())
{
using (var fstream_out = new FileStream(filePath, FileMode.Truncate, FileAccess.ReadWrite, FileShare.Write))
{
salsa.Key = key;
salsa.IV = iv;
using (var cstream = new CryptoStream(fstream_out, salsa.CreateEncryptor(), CryptoStreamMode.Write))
{
var bytes = File.ReadAllBytes(filePath);
cstream.Write(bytes, 0, 1000000);
}
}
}
When I try to encrypt file, there's exception "The process cannot access the file because it is being used by another process."
What's wrong?
I am building a application that can encrypt and decrypt files, in c#. The encryption seems like its working (I think its working) however the decryption gives me the exception "The input data is not a complete block." I have tried almost everything I could find online so I thought I should come here. Here is the decryption code:
static void decryptAES (/*byte[] buffer,*/string filePath,byte[] key, byte[] IV)
{
Console.WriteLine("1");
using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
{
AES.Padding = PaddingMode.PKCS7;
AES.Key = key;
AES.BlockSize = 128;
AES.KeySize = 128;
AES.IV = IV;
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
using (ICryptoTransform crypt = AES.CreateDecryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(crStream))
{
//breaks here
string data = reader.ReadToEnd();
File.WriteAllText(filePath, data);
File.Move(filePath, filePath.Replace(".encrypted", ""));
}
}
}
}
}
}
It breaks on the line with the comment //breaks here by the way.
Thanks.
Here is the encrypt function
static void encryptAES(byte[] filesBytes,string
filePath,AesCryptoServiceProvider aes)
{
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
using (ICryptoTransform crypt = aes.CreateEncryptor(aes.Key, aes.IV))
{
using (CryptoStream csStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Write))
{
csStream.Write(filesBytes, 0, filesBytes.Length);
}
try { File.Move(filePath, filePath + ".encrypted"); }
catch (UnauthorizedAccessException)
{
}
}
}
}
And here is the key generation:
static AesCryptoServiceProvider generateAES()
{
AesCryptoServiceProvider a = new AesCryptoServiceProvider();
a.Padding = PaddingMode.PKCS7;
a.BlockSize =128;
a.KeySize = 128;
a.GenerateIV();
a.GenerateKey();
return a;
}
Here is how I stored the IV and AES Key:
private static void dumpKeys(AesCryptoServiceProvider aes)
{
foreach (byte b in aes.Key)
{
Console.Write(b);
}
Console.WriteLine();
foreach (byte b in aes.IV)
{
Console.Write(b);
}
byte[] encryptedKey = encryptRSA(aes.Key);
byte[] encryptedIV = encryptRSA(aes.IV);
Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys");
File.WriteAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys\0000000000000.Key", encryptedKey);
File.WriteAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys\1111111111111.IV", encryptedIV);
}
And here is how I retrieve the key and iv data:
byte[] AESKey = decrypt(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys\0000000000000.Key");
byte[] AESIV = decrypt(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys\1111111111111.IV");
static byte[] decrypt(string path)
{
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
RSA.FromXmlString(Properties.Resources.privateKey);
byte[] unencrypted = RSA.Decrypt(File.ReadAllBytes(path), true);
foreach (byte b in unencrypted)
{
Console.Write(b);
}
Console.WriteLine();
return unencrypted;
}
}
Btw I store a public RSA key in my resources file and I use that to decrypt the key.
Thanks
So far, so good. Do you extract the generated Key and IV? I modified your decryption function to an encryption function...
public static void Main()
{
var f = #"q:\test.txt";
AesCryptoServiceProvider AES = new AesCryptoServiceProvider();
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CBC;
AES.BlockSize = 128;
AES.KeySize = 128;
AES.GenerateKey();
AES.GenerateIV();
var key = AES.Key;
var iv = AES.IV;
encryptAES(AES, f, key, iv);
decryptAES(AES, f + ".encrypted", key, iv);
}
static void encryptAES(SymmetricAlgorithm algo, string filePath, byte[] key, byte[] IV)
{
using (FileStream fin = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (FileStream fout = new FileStream(filePath + ".encrypted", FileMode.OpenOrCreate, FileAccess.Write))
{
using (ICryptoTransform crypt = algo.CreateEncryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fout, crypt, CryptoStreamMode.Write))
{
fin.CopyTo(crStream);
}
}
}
}
}
static void decryptAES(SymmetricAlgorithm algo, string filePath, byte[] key, byte[] IV)
{
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (ICryptoTransform crypt = algo.CreateDecryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(crStream))
{
string data = reader.ReadToEnd();
File.WriteAllText(filePath.Replace(".encrypted", ".restored"), data);
}
}
}
}
}
Tested it with your code, slightly modified (changed FileMode.Open to FileMode.OpenOrCreate, Added File.Delete before File.Move and merged File.WriteAllText with File.Move) and it works. So a) please review your code. b) If it still fails, provide more details, a single codeblock with every function and a Main-method that calls your functions to reproduce your failure...
static AesCryptoServiceProvider generateAES()
{
AesCryptoServiceProvider a = new AesCryptoServiceProvider();
a.Padding = PaddingMode.PKCS7;
a.BlockSize = 128;
a.KeySize = 128;
a.GenerateIV();
a.GenerateKey();
return a;
}
static void encryptAES(byte[] filesBytes, string filePath, AesCryptoServiceProvider aes)
{
using (FileStream fStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (ICryptoTransform crypt = aes.CreateEncryptor(aes.Key, aes.IV))
{
using (CryptoStream csStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Write))
{
csStream.Write(filesBytes, 0, filesBytes.Length);
}
try {
File.Delete(filePath + ".encrypted");
File.Move(filePath, filePath + ".encrypted");
}
catch (UnauthorizedAccessException)
{
}
}
}
}
static void decryptAES(/*byte[] buffer,*/string filePath, byte[] key, byte[] IV)
{
using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
{
AES.Padding = PaddingMode.PKCS7;
AES.Key = key;
AES.BlockSize = 128;
AES.KeySize = 128;
AES.IV = IV;
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
using (ICryptoTransform crypt = AES.CreateDecryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(crStream))
{
//breaks here
string data = reader.ReadToEnd();
File.WriteAllText(filePath.Replace(".encrypted", ""), data);
}
}
}
}
}
}
When encrypting and decrypting text files, the code works fine.
But when encrypting binary and zip files, file size almost doubled after decryption. For example, a 2.06mb bin.exe became 3.69mb after decryption; a 4mb zip file became 7+mb after decryption.
Is this because of the PaddingMode? What PaddingMode should I set to work with all types of files? How to solve this problem?
private async Task RunEncrypt(string srcfile)
{
string data;
using (StreamReader sr = new StreamReader(srcfile))
{
data = sr.ReadToEnd();
}
byte[] enc_data = await Program.myEncrypt(data);
}
static async Task<byte[]> myEncrypt(string toEncStr)
{
byte[] encrypted;
using (Aes encaes = Aes.Create())
{
try
{
//store key to key.txt
FileStream fs = new FileStream("key.txt", FileMode.OpenOrCreate);
fs.Write(encaes.Key, 0, encaes.Key.Length);
fs.Write(encaes.IV, 0, encaes.IV.Length);
fs.Close();
}
catch ( Exception e)
{
Console.WriteLine("Recording encryption keys failed!{0}.", e.Message);
Environment.Exit(0);
}
encaes.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = encaes.CreateEncryptor(encaes.Key, encaes.IV);
try
{
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(toEncStr);
}
}
encrypted = msEncrypt.ToArray();
}
return encrypted;
}
catch (Exception e)
{
Console.WriteLine("Encryption failed!{0}.", e.Message);
return Encoding.UTF8.GetBytes("null");
}
}
}
private async Task RunDecrypt(byte[] inbytes)
{
try
{
string write_data = await myDecrypt(inbytes);
using (StreamWriter sw = new StreamWriter("test.exe", true))
{
sw.Write(write_data);
sw.Close();
}
}
catch (Exception e)
{
}
}
async Task<string> myDecrypt(byte[] toDecBytes)
{
try
{
string decrypted;
using (Aes dec = Aes.Create())
{
byte[] Key = new byte[dec.Key.Length];
byte[] IV = new byte[dec.IV.Length];
//read key from key.txt
FileStream fsread = new FileStream("key.txt", FileMode.Open);
fsread.Read(Key, 0, Key.Length);
fsread.Read(IV, 0, IV.Length);
fsread.Close();
dec.Key = Key;
dec.IV = IV;
dec.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = dec.CreateDecryptor(dec.Key, dec.IV);
using (MemoryStream msDecrypt = new MemoryStream(toDecBytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
decrypted = srDecrypt.ReadToEnd();
return decrypted;
}
}
}
}
}
catch (Exception e)
{
Console.WriteLine("Decryption failed! {0}.", e.Message);
return #"null";
}
}
By using a StreamReader and StreamWriter, you are treating the file content as text. To support binary files, read/write directly from/to the source/target stream instead.
I have a WPF application contains this class:*
{[Serializable]
public class Parametres
{
private string admin_login;
private string admin_pwd;
private string server;
private string db;
private string user;
private string pwd;}
i serialize an object with this function:
public static void Serialize_Parametres(string filename, Parametres obj)
{
using (FileStream fs = File.Open(filename, FileMode.OpenOrCreate))
{
using (CryptoStream cs = new CryptoStream(fs, key.CreateEncryptor(), CryptoStreamMode.Write))
{
XmlSerializer xmlser = new XmlSerializer(typeof(Parametres));
xmlser.Serialize(cs, obj);
}
}
}
it's works fine and it generates a file .txt , but when i try to deserialize this file and get the object parametres whith this function:
public static Parametres DeSerialize_Parametres(string filename)
{
using (FileStream fs = File.Open(filename, FileMode.Open))
{
using (CryptoStream cs = new CryptoStream(fs, key.CreateDecryptor(), CryptoStreamMode.Read))
{
XmlSerializer xmlser = new XmlSerializer(typeof(Parametres));
return (Parametres)xmlser.Deserialize(cs);
}
}
}
i got this error Length of the data to decrypt is invalid in the line return (Parametres)xmlser.Deserialize(cs);
What is exactly the reason of this error? how can i fix it?
When using this techique to serialize an object you have to do in two parts. The length encrypted stream must be stored as part of the final stream and its up to you to do this. However, you should break this up into a more resuable form.
For example, first serialze the graph you want into a byte stream; then
Encrypte the byte stream; then
Save it to a file.
Below is an example on how to Serialize to a file using AES:
public class ObjectXmlSerializer
{
//---------------------------------------------------------------------
public override Byte[] Serialize(Object obj)
{
using (MemoryStream ms = new MemoryStream())
{
new XmlSerializer(obj.GetType()).Serialize(ms, obj);
return ms.ToArray();
}
}
//---------------------------------------------------------------------
public override T Deserialize<T>(Byte[] bObj)
{
using (MemoryStream ms = new MemoryStream(bObj))
{
return (T)new XmlSerializer(typeof(T)).Deserialize(ms);
}
}
//---------------------------------------------------------------------
public override T Deserialize<T>(Stream iostream)
{
return (T)new XmlSerializer(typeof(T)).Deserialize(iostream);
}
}
// next
public static class CryptoSerivces
{
//---------------------------------------------------------------------
public static Byte[] AesEncrypt(Byte[] src, Byte[] key, Byte[] IV)
{
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
try
{
myRijndael.Mode = CipherMode.CBC;
myRijndael.Key = key;
myRijndael.IV = IV;
myRijndael.Padding = PaddingMode.PKCS7;
using (ICryptoTransform encryptor = myRijndael.CreateEncryptor())
using (MemoryStream msEncrypt = new MemoryStream())
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(src, 0, src.Length);
csEncrypt.FlushFinalBlock();
return msEncrypt.ToArray();
}
}
finally
{
myRijndael.Clear();
}
}
}
//---------------------------------------------------------------------
public static Byte[] AesDecrypt(Byte[] src, Byte[] key, Byte[] IV)
{
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
try
{
myRijndael.Mode = CipherMode.CBC;
myRijndael.Key = key;
myRijndael.IV = IV;
myRijndael.Padding = PaddingMode.PKCS7;
using (ICryptoTransform decryptor = myRijndael.CreateDecryptor())
using (MemoryStream msDecrypt = new MemoryStream())
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
{
csDecrypt.Write(src, 0, src.Length);
csDecrypt.FlushFinalBlock();
return msDecrypt.ToArray();
}
}
finally
{
myRijndael.Clear();
}
}
}
}
// put all the peices together
void SaveToFile(String fileName, Parametres obj)
{
ObjectXmlSerializer oxs = new ObjectXmlSerializer();
Byte[] bObj = oxs.Serialize(obj);
Byte[] bEncObj = CryptoSerivces.AesEncrypt(bObj, SomeKey, SomeIV);
using (FileStream fs = File.Open(filename, FileMode.OpenOrCreate))
{
fs.Write(bEncObj, 0, bEncObj.Length);
}
}
// I'll leave the reading up to you.