I am storing my DataTable in a file using the function given below which i had taken from a website. The code works well.
The problem is:
I want to apply some sort of encryption here. How can i achieve that?
public void SerializeObject<T>(T serializableObject, string fileName)
{
if (serializableObject == null) { return; }
try
{
XmlDocument xmlDocument = new XmlDocument();
XmlSerializer serializer = new XmlSerializer(serializableObject.GetType());
using (MemoryStream stream = new MemoryStream())
{
serializer.Serialize(stream, serializableObject);
stream.Position = 0;
xmlDocument.Load(stream);
xmlDocument.Save(fileName);
stream.Close();
}
}
catch (Exception ex)
{
//Log exception here
}
}
Any help is highly appreciated.
Thanks
Encrypt/Decrypt your streamed XML file with the given below class:
You can use another encryption strategy it is depending on your requirements.
public static class EncryptionManagement
{
private static SymmetricAlgorithm encryption;
private const string password = "admin";
private const string Mkey = "MY SECRET KEY";
private static void Init()
{
encryption = new RijndaelManaged();
var key = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(Mkey));
encryption.Key = key.GetBytes(encryption.KeySize / 8);
encryption.IV = key.GetBytes(encryption.BlockSize / 8);
encryption.Padding = PaddingMode.PKCS7;
}
public static void Encrypt(Stream inStream, Stream OutStream)
{
Init();
var encryptor = encryption.CreateEncryptor();
inStream.Position = 0;
var encryptStream = new CryptoStream(OutStream, encryptor, CryptoStreamMode.Write);
inStream.CopyTo(encryptStream);
encryptStream.FlushFinalBlock();
}
public static void Decrypt(Stream inStream, Stream OutStream)
{
Init();
var encryptor = encryption.CreateDecryptor();
inStream.Position = 0;
var encryptStream = new CryptoStream(inStream, encryptor, CryptoStreamMode.Read);
encryptStream.CopyTo(OutStream);
OutStream.Position = 0;
}
}
Related
Running into error on the void Encryption().
public void Encryption()
{
#region PGP Encryption
PgpEncryptionKeys encryptionKeys = new PgpEncryptionKeys(#"C:\Keys\PGPPublicKey.asc", #"C:\Keys\PGPPrivateKey.asc", "password");
PgpEncrypt encrypter = new PgpEncrypt(encryptionKeys);
using (Stream outputStream = File.Create("C:\\Keys\\EncryptData.txt"))
{
encrypter.EncryptAndSign(outputStream, new FileInfo(#"D:\Keys\PlainText.txt"));
}
Console.WriteLine("Encryption Done !");
#endregion
}
I used https://code.msdn.microsoft.com/vstudio/Pretty-Good-Privacy-using-4f473c67
as a reference.
I am confused about the parameters in the PgpEncryptionKeys.
Does anyone have a working example or help? This is my first time encrypting so I am little lost.
I'm using by this way:
I think can help you!
Helper:
public static void EncryptPgpFile(string inputFile, string outputFile, string publicKeyFile, bool armor, bool withIntegrityCheck)
{
using (Stream publicKeyStream = File.OpenRead(publicKeyFile))
{
PgpPublicKey pubKey = ReadPublicKey(publicKeyStream);
using (MemoryStream outputBytes = new MemoryStream())
{
PgpCompressedDataGenerator dataCompressor = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
PgpUtilities.WriteFileToLiteralData(dataCompressor.Open(outputBytes), PgpLiteralData.Binary, new FileInfo(inputFile));
dataCompressor.Close();
PgpEncryptedDataGenerator dataGenerator = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
dataGenerator.AddMethod(pubKey);
byte[] dataBytes = outputBytes.ToArray();
using (Stream outputStream = File.Create(outputFile))
{
if (armor)
{
using (ArmoredOutputStream armoredStream = new ArmoredOutputStream(outputStream))
using (Stream outputStream = dataGenerator.Open(armoredStream, dataBytes.Length))
outputStream.Write(dataBytes, 0, dataBytes.Length);
}
else
{
using (Stream outputStream = dataGenerator.Open(armoredStream, dataBytes.Length))
outputStream.Write(dataBytes, 0, dataBytes.Length);
}
}
}
}
}
private static PgpPublicKey ReadPublicKey(Stream inputStream)
{
inputStream = PgpUtilities.GetDecoderStream(inputStream);
PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle(inputStream);
foreach (PgpPublicKeyRing keyRing in pgpPub.GetKeyRings())
{
foreach (PgpPublicKey key in keyRing.GetPublicKeys())
{
if (key.IsEncryptionKey)
return key;
}
}
throw new ArgumentException("Can't find encryption key in key ring.");
}
Usage:
EncryptPgpFile(inputFile, outputFile, publicKeyPath, true, true);
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
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.
I have following code that works fine when I use a four letter word as input, E.g. “Test”. When the input is not a multiple of 4, it fails E.g. “MyTest”.
Eexception: Invalid length for a Base-64 char array.
QUESTIONS
Is it guaranteed that the encrypted result will be always compatible to a Unicode string (without any loss). If yes I can use UTF encoding instead of Base64? What's the difference between UTF8/UTF16 and Base64 in terms of encoding
How can add padding so that we get correct result (after decryption) even if the input is not a multiple of 4?
MAIN PRGORAM
class Program
{
static void Main(string[] args)
{
string valid128BitString = "AAECAwQFBgcICQoLDA0ODw==";
string inputValue = "MyTest";
string keyValue = valid128BitString;
byte[] byteValForString = Convert.FromBase64String(inputValue);
EncryptResult result = Aes128Utility.EncryptData(byteValForString, keyValue);
EncryptResult encyptedValue = new EncryptResult();
string resultingIV = "4uy34C9sqOC9rbV4GD8jrA==";
if (String.Equals(resultingIV,result.IV))
{
int x = 0;
}
encyptedValue.IV = resultingIV;
encyptedValue.EncryptedMsg = result.EncryptedMsg;
string finalResult = Convert.ToBase64String(Aes128Utility.DecryptData(encyptedValue, keyValue));
Console.WriteLine(finalResult);
if (String.Equals(inputValue, finalResult))
{
Console.WriteLine("Match");
}
else
{
Console.WriteLine("Differ");
}
Console.ReadLine();
}
}
AES Crypto UTILITY
public static class Aes128Utility
{
private static byte[] key;
public static EncryptResult EncryptData(byte[] rawData, string strKey)
{
EncryptResult result = null;
if (key == null)
{
if (!String.IsNullOrEmpty(strKey))
{
key = Convert.FromBase64String((strKey));
result = Encrypt(rawData);
}
}
else
{
result = Encrypt(rawData);
}
return result;
}
public static byte[] DecryptData(EncryptResult encryptResult, string strKey)
{
byte[] origData = null;
if (key == null)
{
if (!String.IsNullOrEmpty(strKey))
{
key = Convert.FromBase64String(strKey);
origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
}
}
else
{
origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
}
return origData;
}
private static EncryptResult Encrypt(byte[] rawData)
{
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
aesProvider.Key = key;
aesProvider.Mode = CipherMode.CBC;
aesProvider.Padding = PaddingMode.PKCS7;
aesProvider.IV = Convert.FromBase64String("4uy34C9sqOC9rbV4GD8jrA==");
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream encStream = new CryptoStream(memStream, aesProvider.CreateEncryptor(), CryptoStreamMode.Write);
encStream.Write(rawData, 0, rawData.Length);
encStream.FlushFinalBlock();
EncryptResult encResult = new EncryptResult();
encResult.EncryptedMsg = Convert.ToBase64String(memStream.ToArray());
encResult.IV = Convert.ToBase64String(aesProvider.IV);
return encResult;
}
}
}
private static byte[] Decrypt(byte[] encryptedMsg, byte[] iv)
{
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
aesProvider.Key = key;
aesProvider.IV = iv;
aesProvider.Mode = CipherMode.CBC;
aesProvider.Padding = PaddingMode.PKCS7;
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream decStream = new CryptoStream(memStream, aesProvider.CreateDecryptor(), CryptoStreamMode.Write);
decStream.Write(encryptedMsg, 0, encryptedMsg.Length);
decStream.FlushFinalBlock();
return memStream.ToArray();
}
}
}
}
DTO
public class EncryptResult
{
public string EncryptedMsg { get; set; }
public string IV { get; set; }
}
REFERENCES:
How to create byte[] with length 16 using FromBase64String
Getting incorrect decryption value using AesCryptoServiceProvider
If you are encrypting, then encoding Base64 for me doesn't add anything useful, instead it brings the problems you face.
As for the padding, a solution i have seen is to create a new byte[] that is indeed a multiple of 4 and copy the source byte[] to that new byte[].
So, something like this:
if (rawdata.Length % 16 !=0)
{
newSource = new byte[source.Length + 16 - source.Length % 16];
Array.Copy(source, newSource, source.Length);
}
Base64 is a way of representing binary values as text so that you do not conflict with common control codes like \x0A for newline or \0 for a string terminator. It is NOT for turning typed text in to binary.
Here is how you should be passing the text in and getting it back out. You can replace UTF8 with whatever encoding you want, but you will need to make sure the Encoding.Whatever.GetBytes is the same encoding as the Encoding.Whatever.GetString
class Program
{
static void Main(string[] args)
{
string valid128BitString = "AAECAwQFBgcICQoLDA0ODw==";
string inputValue = "MyTest";
string keyValue = valid128BitString;
//Turns our text in to binary data
byte[] byteValForString = Encoding.UTF8.GetBytes(inputValue);
EncryptResult result = Aes128Utility.EncryptData(byteValForString, keyValue);
EncryptResult encyptedValue = new EncryptResult();
//(Snip)
encyptedValue.IV = resultingIV;
encyptedValue.EncryptedMsg = result.EncryptedMsg;
string finalResult = Encoding.UTF8.GetString(Aes128Utility.DecryptData(encyptedValue, keyValue));
Console.WriteLine(finalResult);
if (String.Equals(inputValue, finalResult))
{
Console.WriteLine("Match");
}
else
{
Console.WriteLine("Differ");
}
Console.ReadLine();
}
}
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();
}
}