I can read an write my serialized class fine until I try to encrypt / decrypt... here is a snippet of my code:
public class ShelfCache
{
public Shelf Data;
public ShelfCache()
{
Data = new Shelf();
}
public void Write(string Filename)
{
XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
TextWriter xslWriter = new StreamWriter(Filename);
xsl.Serialize(xslWriter, Data);
xslWriter.Flush();
xslWriter.Close();
}
public void Read(string Filename)
{
Data = new Shelf();
XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
TextReader xslReader = new StreamReader(Filename);
Data = (Shelf)xsl.Deserialize(xslReader);
xslReader.Close();
}
public void WriteEncrypted(string Filename, string EncryptionKey = "")
{
string _Key = EncryptionKey + Environment.ExpandEnvironmentVariables("%USERNAME%%COMPUTERNAME%123456789ABCDEF0123456789abcdef").Substring(0, 32);
string _IV = Environment.ExpandEnvironmentVariables("%COMPUTERNAME%123456789abcdef").Substring(0, 16);
byte[] Key = Encoding.UTF8.GetBytes(_Key);
byte[] IV = Encoding.UTF8.GetBytes(_IV);
FileStream CacheStream = new FileStream(Filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
RijndaelManaged CryptoProvider = new RijndaelManaged();
ICryptoTransform CacheTransform = CryptoProvider.CreateEncryptor(Key, IV);
CryptoStream EncryptionStream = new CryptoStream(CacheStream, CacheTransform, CryptoStreamMode.Write);
XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
xsl.Serialize(EncryptionStream, Data);
EncryptionStream.Flush();
CacheStream.Close();
}
public void ReadEncrypted(string Filename, string EncryptionKey = "")
{
string _Key = EncryptionKey + Environment.ExpandEnvironmentVariables("%USERNAME%%COMPUTERNAME%123456789ABCDEF0123456789abcdef").Substring(0, 32);
string _IV = Environment.ExpandEnvironmentVariables("%COMPUTERNAME%123456789abcdef").Substring(0, 16);
byte[] Key = Encoding.UTF8.GetBytes(_Key);
byte[] IV = Encoding.UTF8.GetBytes(_IV);
FileStream CacheStream = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
RijndaelManaged CryptoProvider = new RijndaelManaged();
ICryptoTransform CacheTransform = CryptoProvider.CreateEncryptor(Key, IV);
CryptoStream DecryptionStream = new CryptoStream(CacheStream, CacheTransform, CryptoStreamMode.Read);
XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
Data = (Shelf)xsl.Deserialize(DecryptionStream);
CacheStream.Close();
}
}
I get the exception "There is an error in XML document (1 1)." with an inner exception "Data at the root level is invalid. Line 1, position 1." on the line:
Data = (Shelf)xsl.Deserialize(DecryptionStream);
This is what I ended up doing (I don't like the solution, but it works)...
public class ShelfCache
{
public Shelf Data;
public ShelfCache()
{
Data = new Shelf();
}
public void Write(string Filename)
{
XmlSerializer CacheSerializer = new XmlSerializer(typeof(Shelf));
TextWriter CacheWriter = new StreamWriter(Filename);
CacheSerializer.Serialize(CacheWriter, Data);
CacheWriter.Flush();
CacheWriter.Close();
}
public void Read(string Filename)
{
Data = new Shelf();
XmlSerializer CacheSerializer = new XmlSerializer(typeof(Shelf));
TextReader CacheReader = new StreamReader(Filename);
Data = (Shelf)CacheSerializer.Deserialize(CacheReader);
CacheReader.Close();
}
public void WriteEncrypted(string Filename, string EncryptionKey = "")
{
string TempFile = System.IO.Path.GetTempFileName();
Write(TempFile);
EncryptFile(TempFile, Filename, EncryptionKey);
File.Delete(TempFile);
}
public void ReadEncrypted(string Filename, string EncryptionKey = "")
{
string TempFile = System.IO.Path.GetTempFileName();
DecryptFile(Filename, TempFile, EncryptionKey);
Read(TempFile);
File.Delete(TempFile);
}
private RijndaelManaged GetEncryptor(string Key = "", string Salt = "")
{
Key += Environment.ExpandEnvironmentVariables("%USERNAME%");
Salt += Environment.ExpandEnvironmentVariables("%COMPUTERNAME%");
Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(Key, Encoding.Unicode.GetBytes(Salt));
RijndaelManaged rijndaelCSP = new RijndaelManaged();
rijndaelCSP.Key = derivedKey.GetBytes(rijndaelCSP.KeySize / 8);
rijndaelCSP.IV = derivedKey.GetBytes(rijndaelCSP.BlockSize / 8);
return rijndaelCSP;
}
private void EncryptFile(string Source, string Target, string EncryptionKey)
{
RijndaelManaged EncryptionProvider = GetEncryptor(EncryptionKey);
ICryptoTransform Encryptor = EncryptionProvider.CreateEncryptor();
FileStream SourceStream = new FileStream(Source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
byte[] SourceBytes = new byte[(int)SourceStream.Length];
SourceStream.Read(SourceBytes, 0, (int)SourceStream.Length);
FileStream TargetStream = new FileStream(Target, FileMode.Create, FileAccess.Write);
CryptoStream EncryptionStream = new CryptoStream(TargetStream, Encryptor, CryptoStreamMode.Write);
EncryptionStream.Write(SourceBytes, 0, (int)SourceStream.Length);
EncryptionStream.FlushFinalBlock();
EncryptionProvider.Clear();
EncryptionStream.Close();
SourceStream.Close();
TargetStream.Close();
}
private void DecryptFile(string Source, string Target, string EncryptionKey)
{
RijndaelManaged EncryptionProvider = GetEncryptor(EncryptionKey);
ICryptoTransform Decryptor = EncryptionProvider.CreateDecryptor();
FileStream SourceStream = new FileStream(Source, FileMode.Open, FileAccess.Read);
CryptoStream DecryptionStream = new CryptoStream(SourceStream, Decryptor, CryptoStreamMode.Read);
byte[] SourceBytes = new byte[(int)SourceStream.Length];
int DecryptionLength = DecryptionStream.Read(SourceBytes, 0, (int)SourceStream.Length);
FileStream TargetStream = new FileStream(Target, FileMode.Create, FileAccess.Write);
TargetStream.Write(SourceBytes, 0, DecryptionLength);
TargetStream.Flush();
EncryptionProvider.Clear();
DecryptionStream.Close();
SourceStream.Close();
TargetStream.Close();
}
}
Related
I'm studying encryption in C# and I'm having trouble. I have some Rijndael encryption code and it's working perfectly with strings. But now I'm studying serialization and the BinaryWriter writes the data of classes without any protection. I'm using this code to test; is there a way to "encrypt the class", or something similar?
To clarify the question, here is my code:
FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Create);
using (BinaryWriter sw = new BinaryWriter(file))
{
byte[] byt = ConverteObjectEmByte(myVarClass);
sw.Write(byt);
}
And this is how I read it:
MyClass newMyVarClass;
FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Open);
using (BinaryReader sr = new BinaryReader(file))
{
// 218 is the size of the byte array that I've tested (byt)
myNewVarClass = (MyClass)ConverteByteEmObject(sr.ReadBytes(218));
}
Thanks!
Rather than converting to byte[] as an intermediate step when passing to different stream objects you can chain multiple streams together, passing the output from one to the input of another.
This approach makes sense here, as you are chaining together
Binary Serialization => Encryption => Writing to File.
With this in mind, you can change ConvertObjectEmByte to something like:
public static void WriteObjectToStream(Stream outputStream, Object obj)
{
if (object.ReferenceEquals(null, obj))
{
return;
}
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(outputStream, obj);
}
and similarly, ConvertByteEmObject can become:
public static object ReadObjectFromStream(Stream inputStream)
{
BinaryFormatter binForm = new BinaryFormatter();
object obj = binForm.Deserialize(inputStream);
return obj;
}
To add in the encryption/decryption, we can write functions that create CryptoStream objects that we can chain with these binary serialization functions. My example functions below look a bit different from the Encrypt/Decrypt functions in the article you linked to because the IV (Initialization Vector) is now generated randomly and written to the stream (and read from the stream on the other end). It's important that the IV is unique for each chunk of data you encrypt for security, and you should also use a random number generator intended for cryptographic purposes like RNGCryptoServiceProvider, rather than a pseudo-random number generator like Random.
public static CryptoStream CreateEncryptionStream(byte[] key, Stream outputStream)
{
byte[] iv = new byte[ivSize];
using (var rng = new RNGCryptoServiceProvider())
{
// Using a cryptographic random number generator
rng.GetNonZeroBytes(iv);
}
// Write IV to the start of the stream
outputStream.Write(iv, 0, iv.Length);
Rijndael rijndael = new RijndaelManaged();
rijndael.KeySize = keySize;
CryptoStream encryptor = new CryptoStream(
outputStream,
rijndael.CreateEncryptor(key, iv),
CryptoStreamMode.Write);
return encryptor;
}
public static CryptoStream CreateDecryptionStream(byte[] key, Stream inputStream)
{
byte[] iv = new byte[ivSize];
if (inputStream.Read(iv, 0, iv.Length) != iv.Length)
{
throw new ApplicationException("Failed to read IV from stream.");
}
Rijndael rijndael = new RijndaelManaged();
rijndael.KeySize = keySize;
CryptoStream decryptor = new CryptoStream(
inputStream,
rijndael.CreateDecryptor(key, iv),
CryptoStreamMode.Read);
return decryptor;
}
Finally, we can glue it together:
byte[] key = Convert.FromBase64String(cryptoKey);
using (FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Create))
using (CryptoStream cryptoStream = CreateEncryptionStream(key, file))
{
WriteObjectToStream(cryptoStream, myVarClass);
}
MyClass newMyVarClass;
using (FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Open))
using (CryptoStream cryptoStream = CreateDecryptionStream(key, file))
{
newMyVarClass = (MyClass)ReadObjectFromStream(cryptoStream);
}
Note that we pass the file stream object to CreateEncryptionStream (and CreateDecryptionStream), and then pass the cryptoStream object to WriteObjectToStream (and ReadObjectfromStream). You'll also notice that the streams are scoped inside using blocks, so that they'll automatically be cleaned up when we're finished with them.
Here's the full test program:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
namespace CryptoStreams
{
class Program
{
[Serializable]
public class MyClass
{
public string TestValue
{
get;
set;
}
public int SomeInt
{
get;
set;
}
}
public static void WriteObjectToStream(Stream outputStream, Object obj)
{
if (object.ReferenceEquals(null, obj))
{
return;
}
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(outputStream, obj);
}
public static object ReadObjectFromStream(Stream inputStream)
{
BinaryFormatter binForm = new BinaryFormatter();
object obj = binForm.Deserialize(inputStream);
return obj;
}
private const string cryptoKey =
"Q3JpcHRvZ3JhZmlhcyBjb20gUmluamRhZWwgLyBBRVM=";
private const int keySize = 256;
private const int ivSize = 16; // block size is 128-bit
public static CryptoStream CreateEncryptionStream(byte[] key, Stream outputStream)
{
byte[] iv = new byte[ivSize];
using (var rng = new RNGCryptoServiceProvider())
{
// Using a cryptographic random number generator
rng.GetNonZeroBytes(iv);
}
// Write IV to the start of the stream
outputStream.Write(iv, 0, iv.Length);
Rijndael rijndael = new RijndaelManaged();
rijndael.KeySize = keySize;
CryptoStream encryptor = new CryptoStream(
outputStream,
rijndael.CreateEncryptor(key, iv),
CryptoStreamMode.Write);
return encryptor;
}
public static CryptoStream CreateDecryptionStream(byte[] key, Stream inputStream)
{
byte[] iv = new byte[ivSize];
if (inputStream.Read(iv, 0, iv.Length) != iv.Length)
{
throw new ApplicationException("Failed to read IV from stream.");
}
Rijndael rijndael = new RijndaelManaged();
rijndael.KeySize = keySize;
CryptoStream decryptor = new CryptoStream(
inputStream,
rijndael.CreateDecryptor(key, iv),
CryptoStreamMode.Read);
return decryptor;
}
static void Main(string[] args)
{
MyClass myVarClass = new MyClass
{
SomeInt = 1234,
TestValue = "Hello"
};
byte[] key = Convert.FromBase64String(cryptoKey);
using (FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Create))
{
using (CryptoStream cryptoStream = CreateEncryptionStream(key, file))
{
WriteObjectToStream(cryptoStream, myVarClass);
}
}
MyClass newMyVarClass;
using (FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Open))
using (CryptoStream cryptoStream = CreateDecryptionStream(key, file))
{
newMyVarClass = (MyClass)ReadObjectFromStream(cryptoStream);
}
Console.WriteLine("newMyVarClass.SomeInt: {0}; newMyVarClass.TestValue: {1}",
newMyVarClass.SomeInt,
newMyVarClass.TestValue);
}
}
}
I'm not sure whether the .Net Library had changed or just the code is wrong. I can't directly run the code written by softwariness.
Since that, I changed the code based on the answer so that it can be used correctly. Here's an example.
public class CryptoSerialization
{
public static void WriteObjectToStream(Stream outputStream, object obj)
{
if (obj is null) throw new ArgumentNullException("obj can't be null");
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(outputStream, obj);
}
public static object ReadObjectFromStream(Stream inputStream)
{
BinaryFormatter bf = new BinaryFormatter();
return bf.Deserialize(inputStream);
}
public static CryptoStream CreateEncryptionStream(Stream outputStream, byte[] Key, byte[] IV)
{
Rijndael rijndael = new RijndaelManaged();
return new CryptoStream(outputStream, rijndael.CreateEncryptor(Key, IV), CryptoStreamMode.Write);
}
public static CryptoStream CreateDecryptionStream(Stream inputStream, byte[] Key, byte[] IV)
{
Rijndael rijndael = new RijndaelManaged();
return new CryptoStream(inputStream, rijndael.CreateDecryptor(Key, IV), CryptoStreamMode.Read);
}
public static void EncryptObjectToFile(object obj, string path, byte[] Key, byte[] IV)
{
using FileStream file = new FileStream(path, FileMode.Create);
using (CryptoStream cryptoStream = CreateEncryptionStream(file, Key, IV))
{
WriteObjectToStream(cryptoStream, obj);
}
}
public static object DecryptObjectFromFile(string path, byte[] Key, byte[] IV)
{
using FileStream file = new FileStream(path, FileMode.Open);
using (CryptoStream cryptoStream = CreateDecryptionStream(file, Key, IV))
{
return ReadObjectFromStream(cryptoStream);
}
}
}
[Serializable]
public class Student
{
public string Name;
public int Age;
}
static async Task Main(string[] args)
{
// the original string "[This is an example key string!]";
// I don't know if the length of the string has to be 32, but when I tried 64, it went wrong.
string cryptoKey = "W1RoaXMgaXMgYW4gZXhhbXBsZSBrZXkgc3RyaW5nIV0=";
byte[] Key = Convert.FromBase64String(cryptoKey);
byte[] IV = new byte[16];
using (RNGCryptoServiceProvider rngcsp = new RNGCryptoServiceProvider())
{
rngcsp.GetBytes(IV);
}
//same as
//Rijndael rijndael = new RijndaelManaged();
//rijndael.GenerateIV();
//byte[] iv = rijndael.IV;
List<Student> students = new List<Student>() { new Student { Name = "John", Age = 10 }, new Student { Name = "Marry", Age = 15 } };
CryptoSerialization.EncryptObjectToFile(students, Environment.CurrentDirectory + #"\testCrypto.dat", Key, IV);
List<Student> newStudents = (List<Student>)CryptoSerialization.DecryptObjectFromFile(Environment.CurrentDirectory + #"\testCrypto.dat", Key, IV);
newStudents.ForEach((stu) =>
{
Console.WriteLine(stu.Name + ", " + stu.Age);
});
Console.ReadKey();
}
I'm trying to encrypt image files using Rijndael encryption and I must be doing something wrong because the decrypted files are coming out with extra data at the front of the file any maybe a little extra at the end. I'm fairly new to this encryption algorithm so I'm pretty sure I'm just missing something simple.
Examples using text files
Input file
"the quick brown fox jumped over the lazy yellow dog"
Output file when I try to put a generated IV at the front of the file(\0=null)
"ÚñjÐæƒÊW®ï¡_Ü&ßthe\0 quick brown fox jumped over the lazy yellow dog"
Output file when I try to put an IV that is equal to my Key at front
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0the\0\0\0\0\0\0 quick brown fox jumped over the lazy yellow dog"
Output file when I use an IV that is equal to my Key and put nothing at front of file
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0the\0\0\0\0\0\0 quick brown fox jumped over the lazy yellow dog"
CODE
private RijndaelManaged GetCipher(byte[] key, bool forEncrypt)
{
RijndaelManaged rijndaelCipher;
rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
rijndaelCipher.Key = key;
/* if (forEncrypt)
rijndaelCipher.GenerateIV();
else
rijndaelCipher.IV = new byte[16];*/
rijndaelCipher.IV = _imageKey;
return rijndaelCipher;
}
public void DecryptStamp(Stamp stampToDecrypt, string decrpytedStampFilePath)
{
RijndaelManaged rijndaelCipher;
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block;
int numberRead;
ICryptoTransform transform;
if (!File.Exists(stampToDecrypt.Path))
throw new FileNotFoundException(stampToDecrypt.Path + " does not exist");
rijndaelCipher = this.GetCipher(_imageKey, false);
block = new byte[16];
try
{
inputStream = File.Open(stampToDecrypt.Path, FileMode.Open, FileAccess.Read);
outputStream = File.Open(decrpytedStampFilePath, FileMode.Create, FileAccess.Write);
//inputStream.Read(rijndaelCipher.IV, 0, rijndaelCipher.IV.Length);
transform = rijndaelCipher.CreateDecryptor();
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
Console.WriteLine(numberRead.ToString());
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
}
public Stamp EncryptStampToStampFolder(string stampFileToEncrpyt)
{
Configuration config;
Stamp stampToEncrypt;
RijndaelManaged rijndaelCipher;
string encryptedFilePath;
if (!File.Exists(stampFileToEncrpyt))
throw new FileNotFoundException(stampFileToEncrpyt + " does not exist");
config = Configuration.GetProgramInstance();
encryptedFilePath = Path.Combine(config.StampFolder, Path.GetFileNameWithoutExtension(stampFileToEncrpyt) + ".stmp");
stampToEncrypt = new Stamp(Path.GetFileNameWithoutExtension(stampFileToEncrpyt), encryptedFilePath);
rijndaelCipher = this.GetCipher(_imageKey, true);
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block = new byte[16];
int numberRead;
try
{
inputStream = File.Open(stampFileToEncrpyt, FileMode.Open, FileAccess.Read);
outputStream = File.Open(encryptedFilePath, FileMode.Create, FileAccess.Write);
//outputStream.Write(rijndaelCipher.IV, 0, 16);
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
encryptSteam.Write(block, 0, block.Length);
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
return stampToEncrypt;
}
public struct Stamp
{
public string Name,
Path;
public Stamp(string StampName, string StampPath)
{
Name = StampName;
Path = StampPath;
}
}
CODE post fix
private RijndaelManaged GetCipher(byte[] key, bool forEncrypt)
{
RijndaelManaged rijndaelCipher;
rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
rijndaelCipher.Key = key;
if (forEncrypt)
rijndaelCipher.GenerateIV();
else
rijndaelCipher.IV = new byte[16];
//rijndaelCipher.IV = _imageKey;
return rijndaelCipher;
}
public void DecryptStamp(Stamp stampToDecrypt, string decrpytedStampFilePath)
{
RijndaelManaged rijndaelCipher;
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block;
int numberRead;
ICryptoTransform transform;
if (!File.Exists(stampToDecrypt.Path))
throw new FileNotFoundException(stampToDecrypt.Path + " does not exist");
rijndaelCipher = this.GetCipher(_imageKey, false);
block = new byte[16];
try
{
inputStream = File.Open(stampToDecrypt.Path, FileMode.Open, FileAccess.Read);
outputStream = File.Open(decrpytedStampFilePath, FileMode.Create, FileAccess.Write);
inputStream.Read(rijndaelCipher.IV, 0, rijndaelCipher.IV.Length);
transform = rijndaelCipher.CreateDecryptor();
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
}
public Stamp EncryptStampToStampFolder(string stampFileToEncrpyt)
{
Configuration config;
Stamp stampToEncrypt;
RijndaelManaged rijndaelCipher;
string encryptedFilePath;
if (!File.Exists(stampFileToEncrpyt))
throw new FileNotFoundException(stampFileToEncrpyt + " does not exist");
config = Configuration.GetProgramInstance();
encryptedFilePath = Path.Combine(config.StampFolder, Path.GetFileNameWithoutExtension(stampFileToEncrpyt) + ".stmp");
stampToEncrypt = new Stamp(Path.GetFileNameWithoutExtension(stampFileToEncrpyt), encryptedFilePath);
rijndaelCipher = this.GetCipher(_imageKey, true);
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block = new byte[16];
int numberRead;
try
{
inputStream = File.Open(stampFileToEncrpyt, FileMode.Open, FileAccess.Read);
outputStream = File.Open(encryptedFilePath, FileMode.Create, FileAccess.Write);
outputStream.Write(rijndaelCipher.IV, 0, 16);
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
//encryptSteam.Write(block, 0, block.Length); this line was the problem in the orginal code
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
return stampToEncrypt;
}
public struct Stamp
{
public string Name,
Path;
public Stamp(string StampName, string StampPath)
{
Name = StampName;
Path = StampPath;
}
}
New Code's output
"7p¶¼oò¾½G€¢9±hfox\0\0 jumped over the lazy yellow dog"
The problem was three fold.
1)Extra data being written during encryption
2)The IV at the beginning of the file was being overwritten
3)The IV was not being read properly on decryption
CODE Fixed
private RijndaelManaged GetCipher(byte[] key, bool forEncrypt)
{
RijndaelManaged rijndaelCipher;
rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
rijndaelCipher.Key = key;
if (forEncrypt)
rijndaelCipher.GenerateIV();
else
rijndaelCipher.IV = new byte[16];
//rijndaelCipher.IV = _imageKey;
return rijndaelCipher;
}
public void DecryptStamp(Stamp stampToDecrypt, string decrpytedStampFilePath)
{
RijndaelManaged rijndaelCipher;
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block;
int numberRead;
ICryptoTransform transform;
if (!File.Exists(stampToDecrypt.Path))
throw new FileNotFoundException(stampToDecrypt.Path + " does not exist");
rijndaelCipher = this.GetCipher(_imageKey, false);
block = new byte[16];
try
{
inputStream = File.Open(stampToDecrypt.Path, FileMode.Open, FileAccess.Read);
outputStream = File.Open(decrpytedStampFilePath, FileMode.Create, FileAccess.Write);
//This line was wrong because rijndaelCipher.IV never filled
//inputStream.Read(rijndaelCipher.IV, 0, rijndaelCipher.IV.Length);
inputStream.Read(block, 0, block.Length);
rijndaelCipher.IV = block;
block = new byte[16];
transform = rijndaelCipher.CreateDecryptor();
encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
{
encryptSteam.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
}
public Stamp EncryptStampToStampFolder(string stampFileToEncrpyt)
{
Configuration config;
Stamp stampToEncrypt;
RijndaelManaged rijndaelCipher;
string encryptedFilePath;
if (!File.Exists(stampFileToEncrpyt))
throw new FileNotFoundException(stampFileToEncrpyt + " does not exist");
config = Configuration.GetProgramInstance();
encryptedFilePath = Path.Combine(config.StampFolder, Path.GetFileNameWithoutExtension(stampFileToEncrpyt) + ".stmp");
stampToEncrypt = new Stamp(Path.GetFileNameWithoutExtension(stampFileToEncrpyt), encryptedFilePath);
rijndaelCipher = this.GetCipher(_imageKey, true);
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
FileStream inputStream = null;
FileStream outputStream = null;
CryptoStream encryptSteam = null;
byte[] block = new byte[16];
int numberRead;
try
{
inputStream = File.Open(stampFileToEncrpyt, FileMode.Open, FileAccess.Read);
outputStream = File.Open(encryptedFilePath, FileMode.Create, FileAccess.Write);
outputStream.Write(rijndaelCipher.IV, 0, IV.Length);
//This had to be changed so that the IV was not overwitten
//encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
encryptSteam = new CryptoStream(inputStream, transform, CryptoStreamMode.Read);
//this line was a problem in the orginal code that caused extra data to be added to the encrypted file
//encryptSteam.Write(block, 0, block.Length);
while ((numberRead = encryptSteam.Read(block, 0, block.Length)) > 0)
{
outputStream.Write(block, 0, numberRead);
}
}
finally
{
rijndaelCipher.Clear();
rijndaelCipher.Dispose();
if (encryptSteam != null)
encryptSteam.Dispose();
if (outputStream != null)
outputStream.Dispose();
if (inputStream != null)
inputStream.Dispose();
}
return stampToEncrypt;
}
public struct Stamp
{
public string Name,
Path;
public Stamp(string StampName, string StampPath)
{
Name = StampName;
Path = StampPath;
}
}
Here's what I do to decrypt:
private RijndaelManaged GetAesProvider(Stream stm, bool isEncryption)
{
byte[] finalKey = GetFinalKey();
// GetIV either gets salt on encryption and writes it into stm
// or reads it from stm if it's decryption
byte[] iv = GetIV(stm, isEncryption);
RijndaelManaged aes = new RijndaelManaged();
aes.BlockSize = kAesBlockSizeInBytes * 8;
aes.IV = iv;
aes.Key = finalKey;
aes.Mode = CipherMode.CBC;
return aes;
}
public override Stream GetDecryptionStream(Stream source)
{
if (source.Length <= kIVSize)
{
return new EmptyStream();
}
RijndaelManaged aes = GetAesProvider(source, false);
ICryptoTransform xform = aes.CreateDecryptor(aes.Key, aes.IV);
return new CryptoStream(source, xform, CryptoStreamMode.Read);
}
I know doubleDES is not used sine of Meet-in-the-middle Attack but i need to create a program that does that kind of encryption. I tried this but i think im stuck and just cannot figure out what am i missing..
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Mode = CipherMode.ECB;
DES.Padding = PaddingMode.Zeros;
// *****ENKRIPTIMI*****
DES.Key = utf8.GetBytes(textBox1.Text.Substring(0, 8));
StreamReader sr = new StreamReader(textBox2.Text);
string permbajtja = sr.ReadToEnd();
sr.Close();
FileStream fs1 = new FileStream(textBox2.Text, FileMode.Create, FileAccess.Write);
CryptoStream cs = new CryptoStream(fs1, DES.CreateEncryptor(), CryptoStreamMode.Write);
StreamWriter sw = new StreamWriter(cs);
sw.Write(permbajtja); sw.Flush();
sw.Close();
StreamReader stream = new StreamReader(textBox2.Text);
string msg = stream.ReadToEnd();
stream.Close();
MessageBox.Show(msg);
//*****DEKRIPTIMI*****
DES.Key = utf8.GetBytes(textBox1.Text.Substring(8, 8));
FileStream fs2 = new FileStream(textBox2.Text, FileMode.Open, FileAccess.Read);
CryptoStream cs1 = new CryptoStream(fs2, DES.CreateDecryptor(), CryptoStreamMode.Read);
StreamReader sr1 = new StreamReader(cs1);
string permbajtja1 = sr1.ReadToEnd();
// MessageBox.Show(permbajtja1);
sr1.Close();
fs2.Dispose();
fs2.Close();
StreamWriter sw1 = new StreamWriter(textBox2.Text);
sw1.Write(permbajtja1);
sw1.Flush();
sw1.Close();
**** THE PART ABOVE IS JUST FOR ENCRYPTING *****
The decryption part
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Mode = CipherMode.ECB;
DES.Padding = PaddingMode.Zeros;
// *****ENKRIPTIMI*****
DES.Key = utf8.GetBytes(textBox1.Text.Substring(8,8));
StreamReader sr = new StreamReader(textBox2.Text);
string permbajtja = sr.ReadToEnd();
sr.Close();
FileStream fs1 = new FileStream(textBox2.Text, FileMode.Create, FileAccess.Write);
CryptoStream cs = new CryptoStream(fs1, DES.CreateEncryptor(), CryptoStreamMode.Write);
StreamWriter sw = new StreamWriter(cs);
sw.Write(permbajtja); sw.Flush();
sw.Close();
StreamReader lexo = new StreamReader(textBox2.Text);
MessageBox.Show(lexo.ReadToEnd());
lexo.Close();
////*****DEKRIPTIMI*****
DES.Key = utf8.GetBytes(textBox1.Text.Substring(0, 8));
FileStream fs2 = new FileStream(textBox2.Text, FileMode.Open, FileAccess.Read);
CryptoStream cs1 = new CryptoStream(fs2, DES.CreateDecryptor(), CryptoStreamMode.Read);
StreamReader sr1 = new StreamReader(cs1);
string permbajtja1 = sr1.ReadToEnd();
MessageBox.Show(permbajtja1);
sr1.Close();
fs2.Dispose();
fs2.Close();
StreamWriter sw1 = new StreamWriter(textBox2.Text);
sw1.Write(permbajtja1);
sw1.Flush();
sw1.Close();
First of all you should write the encrypt and the decrypt method:
public static string Encrypt(string originalString, byte[] key)
{
DESCryptoServiceProvider cryptoServiceProvider = new DESCryptoServiceProvider();
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream,
cryptoServiceProvider.CreateEncryptor(key, key),
CryptoStreamMode.Write);
using (StreamWriter streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(originalString);
streamWriter.Flush();
cryptoStream.FlushFinalBlock();
streamWriter.Flush();
return Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
}
}
public static string Decrypt(string cryptedString, byte[] key)
{
DESCryptoServiceProvider cryptoServiceProvider = new DESCryptoServiceProvider();
MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(cryptedString));
CryptoStream cryptoStream = new CryptoStream(memoryStream,
cryptoServiceProvider.CreateDecryptor(key, key),
CryptoStreamMode.Read);
using (StreamReader streamReader = new StreamReader(cryptoStream))
{
return streamReader.ReadToEnd();
}
}
Now you can apply twice the encryption method (and of course twice the decryption one) to your string:
byte[] key1 = ASCIIEncoding.ASCII.GetBytes("12345678");
byte[] key2 = ASCIIEncoding.ASCII.GetBytes("abcdefgh");
string originalString = "A secret string";
string cryptedString = Encrypt(Encrypt(originalString, key1), key2);
Console.WriteLine("Encrypt message: {0}", cryptedString);
Console.WriteLine("Decrypt message: {0}", Decrypt(Decrypt(cryptedString, key2), key1));
Take a look to my code, it may help you.
I'm studying encryption in C# and I'm having trouble. I have some Rijndael encryption code and it's working perfectly with strings. But now I'm studying serialization and the BinaryWriter writes the data of classes without any protection. I'm using this code to test; is there a way to "encrypt the class", or something similar?
To clarify the question, here is my code:
FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Create);
using (BinaryWriter sw = new BinaryWriter(file))
{
byte[] byt = ConverteObjectEmByte(myVarClass);
sw.Write(byt);
}
And this is how I read it:
MyClass newMyVarClass;
FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Open);
using (BinaryReader sr = new BinaryReader(file))
{
// 218 is the size of the byte array that I've tested (byt)
myNewVarClass = (MyClass)ConverteByteEmObject(sr.ReadBytes(218));
}
Thanks!
Rather than converting to byte[] as an intermediate step when passing to different stream objects you can chain multiple streams together, passing the output from one to the input of another.
This approach makes sense here, as you are chaining together
Binary Serialization => Encryption => Writing to File.
With this in mind, you can change ConvertObjectEmByte to something like:
public static void WriteObjectToStream(Stream outputStream, Object obj)
{
if (object.ReferenceEquals(null, obj))
{
return;
}
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(outputStream, obj);
}
and similarly, ConvertByteEmObject can become:
public static object ReadObjectFromStream(Stream inputStream)
{
BinaryFormatter binForm = new BinaryFormatter();
object obj = binForm.Deserialize(inputStream);
return obj;
}
To add in the encryption/decryption, we can write functions that create CryptoStream objects that we can chain with these binary serialization functions. My example functions below look a bit different from the Encrypt/Decrypt functions in the article you linked to because the IV (Initialization Vector) is now generated randomly and written to the stream (and read from the stream on the other end). It's important that the IV is unique for each chunk of data you encrypt for security, and you should also use a random number generator intended for cryptographic purposes like RNGCryptoServiceProvider, rather than a pseudo-random number generator like Random.
public static CryptoStream CreateEncryptionStream(byte[] key, Stream outputStream)
{
byte[] iv = new byte[ivSize];
using (var rng = new RNGCryptoServiceProvider())
{
// Using a cryptographic random number generator
rng.GetNonZeroBytes(iv);
}
// Write IV to the start of the stream
outputStream.Write(iv, 0, iv.Length);
Rijndael rijndael = new RijndaelManaged();
rijndael.KeySize = keySize;
CryptoStream encryptor = new CryptoStream(
outputStream,
rijndael.CreateEncryptor(key, iv),
CryptoStreamMode.Write);
return encryptor;
}
public static CryptoStream CreateDecryptionStream(byte[] key, Stream inputStream)
{
byte[] iv = new byte[ivSize];
if (inputStream.Read(iv, 0, iv.Length) != iv.Length)
{
throw new ApplicationException("Failed to read IV from stream.");
}
Rijndael rijndael = new RijndaelManaged();
rijndael.KeySize = keySize;
CryptoStream decryptor = new CryptoStream(
inputStream,
rijndael.CreateDecryptor(key, iv),
CryptoStreamMode.Read);
return decryptor;
}
Finally, we can glue it together:
byte[] key = Convert.FromBase64String(cryptoKey);
using (FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Create))
using (CryptoStream cryptoStream = CreateEncryptionStream(key, file))
{
WriteObjectToStream(cryptoStream, myVarClass);
}
MyClass newMyVarClass;
using (FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Open))
using (CryptoStream cryptoStream = CreateDecryptionStream(key, file))
{
newMyVarClass = (MyClass)ReadObjectFromStream(cryptoStream);
}
Note that we pass the file stream object to CreateEncryptionStream (and CreateDecryptionStream), and then pass the cryptoStream object to WriteObjectToStream (and ReadObjectfromStream). You'll also notice that the streams are scoped inside using blocks, so that they'll automatically be cleaned up when we're finished with them.
Here's the full test program:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
namespace CryptoStreams
{
class Program
{
[Serializable]
public class MyClass
{
public string TestValue
{
get;
set;
}
public int SomeInt
{
get;
set;
}
}
public static void WriteObjectToStream(Stream outputStream, Object obj)
{
if (object.ReferenceEquals(null, obj))
{
return;
}
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(outputStream, obj);
}
public static object ReadObjectFromStream(Stream inputStream)
{
BinaryFormatter binForm = new BinaryFormatter();
object obj = binForm.Deserialize(inputStream);
return obj;
}
private const string cryptoKey =
"Q3JpcHRvZ3JhZmlhcyBjb20gUmluamRhZWwgLyBBRVM=";
private const int keySize = 256;
private const int ivSize = 16; // block size is 128-bit
public static CryptoStream CreateEncryptionStream(byte[] key, Stream outputStream)
{
byte[] iv = new byte[ivSize];
using (var rng = new RNGCryptoServiceProvider())
{
// Using a cryptographic random number generator
rng.GetNonZeroBytes(iv);
}
// Write IV to the start of the stream
outputStream.Write(iv, 0, iv.Length);
Rijndael rijndael = new RijndaelManaged();
rijndael.KeySize = keySize;
CryptoStream encryptor = new CryptoStream(
outputStream,
rijndael.CreateEncryptor(key, iv),
CryptoStreamMode.Write);
return encryptor;
}
public static CryptoStream CreateDecryptionStream(byte[] key, Stream inputStream)
{
byte[] iv = new byte[ivSize];
if (inputStream.Read(iv, 0, iv.Length) != iv.Length)
{
throw new ApplicationException("Failed to read IV from stream.");
}
Rijndael rijndael = new RijndaelManaged();
rijndael.KeySize = keySize;
CryptoStream decryptor = new CryptoStream(
inputStream,
rijndael.CreateDecryptor(key, iv),
CryptoStreamMode.Read);
return decryptor;
}
static void Main(string[] args)
{
MyClass myVarClass = new MyClass
{
SomeInt = 1234,
TestValue = "Hello"
};
byte[] key = Convert.FromBase64String(cryptoKey);
using (FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Create))
{
using (CryptoStream cryptoStream = CreateEncryptionStream(key, file))
{
WriteObjectToStream(cryptoStream, myVarClass);
}
}
MyClass newMyVarClass;
using (FileStream file = new FileStream(Environment.CurrentDirectory + #"\class.dat", FileMode.Open))
using (CryptoStream cryptoStream = CreateDecryptionStream(key, file))
{
newMyVarClass = (MyClass)ReadObjectFromStream(cryptoStream);
}
Console.WriteLine("newMyVarClass.SomeInt: {0}; newMyVarClass.TestValue: {1}",
newMyVarClass.SomeInt,
newMyVarClass.TestValue);
}
}
}
I'm not sure whether the .Net Library had changed or just the code is wrong. I can't directly run the code written by softwariness.
Since that, I changed the code based on the answer so that it can be used correctly. Here's an example.
public class CryptoSerialization
{
public static void WriteObjectToStream(Stream outputStream, object obj)
{
if (obj is null) throw new ArgumentNullException("obj can't be null");
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(outputStream, obj);
}
public static object ReadObjectFromStream(Stream inputStream)
{
BinaryFormatter bf = new BinaryFormatter();
return bf.Deserialize(inputStream);
}
public static CryptoStream CreateEncryptionStream(Stream outputStream, byte[] Key, byte[] IV)
{
Rijndael rijndael = new RijndaelManaged();
return new CryptoStream(outputStream, rijndael.CreateEncryptor(Key, IV), CryptoStreamMode.Write);
}
public static CryptoStream CreateDecryptionStream(Stream inputStream, byte[] Key, byte[] IV)
{
Rijndael rijndael = new RijndaelManaged();
return new CryptoStream(inputStream, rijndael.CreateDecryptor(Key, IV), CryptoStreamMode.Read);
}
public static void EncryptObjectToFile(object obj, string path, byte[] Key, byte[] IV)
{
using FileStream file = new FileStream(path, FileMode.Create);
using (CryptoStream cryptoStream = CreateEncryptionStream(file, Key, IV))
{
WriteObjectToStream(cryptoStream, obj);
}
}
public static object DecryptObjectFromFile(string path, byte[] Key, byte[] IV)
{
using FileStream file = new FileStream(path, FileMode.Open);
using (CryptoStream cryptoStream = CreateDecryptionStream(file, Key, IV))
{
return ReadObjectFromStream(cryptoStream);
}
}
}
[Serializable]
public class Student
{
public string Name;
public int Age;
}
static async Task Main(string[] args)
{
// the original string "[This is an example key string!]";
// I don't know if the length of the string has to be 32, but when I tried 64, it went wrong.
string cryptoKey = "W1RoaXMgaXMgYW4gZXhhbXBsZSBrZXkgc3RyaW5nIV0=";
byte[] Key = Convert.FromBase64String(cryptoKey);
byte[] IV = new byte[16];
using (RNGCryptoServiceProvider rngcsp = new RNGCryptoServiceProvider())
{
rngcsp.GetBytes(IV);
}
//same as
//Rijndael rijndael = new RijndaelManaged();
//rijndael.GenerateIV();
//byte[] iv = rijndael.IV;
List<Student> students = new List<Student>() { new Student { Name = "John", Age = 10 }, new Student { Name = "Marry", Age = 15 } };
CryptoSerialization.EncryptObjectToFile(students, Environment.CurrentDirectory + #"\testCrypto.dat", Key, IV);
List<Student> newStudents = (List<Student>)CryptoSerialization.DecryptObjectFromFile(Environment.CurrentDirectory + #"\testCrypto.dat", Key, IV);
newStudents.ForEach((stu) =>
{
Console.WriteLine(stu.Name + ", " + stu.Age);
});
Console.ReadKey();
}
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.