Ok, last one. Made more general to handle all currently supported symmetric
algos. Also changed to use Streams instead of just files, so can do with
any stream and added helpers over the stream overloads to work with files
and buffers. Also makes IV required.
using System;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Text;
namespace Demo
{
public enum CryptoAlgo
{
DES,
RC2,
Rijndael,
TripleDES
}
public class Crypto : IDisposable
{
// Call this function to remove the key from memory after use for
security
[System.Runtime.InteropServices.DllImport("KERNEL32 .DLL", EntryPoint
= "RtlZeroMemory")]
private static extern bool ZeroMemory(IntPtr Destination, int
Length);
private SymmetricAlgorithm cAlgo;
private readonly int BufSize = 1024;
public Crypto(CryptoAlgo algo) : this(algo, null, null)
{
}
public Crypto(CryptoAlgo algo, string key, string iv)
{
switch (algo)
{
case CryptoAlgo.DES:
cAlgo = DES.Create();
break;
case CryptoAlgo.RC2:
cAlgo = RC2.Create();
break;
case CryptoAlgo.Rijndael:
cAlgo = Rijndael.Create();
break;
case CryptoAlgo.TripleDES:
cAlgo = TripleDES.Create();
break;
default:
throw new ArgumentOutOfRangeException("algo");
}
if (key != null)
{
cAlgo.Key = Convert.FromBase64String(key);
cAlgo.IV = Convert.FromBase64String(iv);
}
}
/// <summary>
/// Gets the key for the algorithm as a Base64 string.
/// </summary>
public string Key
{
get
{
return Convert.ToBase64String(cAlgo.Key);
}
}
/// <summary>
/// Gets the IV for the algorithm as a Base64 string.
/// </summary>
public string IV
{
get { return Convert.ToBase64String(cAlgo.IV); }
}
public void EncryptFile(string inPath, string outPath)
{
using (FileStream inStream = File.OpenRead(inPath))
using (FileStream outStream = new FileStream(outPath,
FileMode.Create, FileAccess.Write))
{
EncryptStream(inStream, outStream);
}
}
public void DecryptFile(string inPath, string outPath)
{
using (FileStream inStream = File.OpenRead(inPath))
using (FileStream outStream = new FileStream(outPath,
FileMode.Create, FileAccess.Write))
{
DecryptStream(inStream, outStream);
}
}
public byte[] EncryptBytes(byte[] buffer)
{
using (MemoryStream inStream = new MemoryStream(buffer))
using (MemoryStream outStream = new MemoryStream())
{
EncryptStream(inStream, outStream);
return outStream.ToArray();
}
}
public byte[] DecryptBytes(byte[] buffer)
{
using (MemoryStream inStream = new MemoryStream(buffer))
using (MemoryStream outStream = new MemoryStream())
{
DecryptStream(inStream, outStream);
return outStream.ToArray();
}
}
public void EncryptStream(Stream inStream, Stream outStream)
{
using (ICryptoTransform encryptor = cAlgo.CreateEncryptor())
using (CryptoStream cryptoStream = new CryptoStream(outStream,
encryptor, CryptoStreamMode.Write))
{
// Read from in file until EOF and write to crypto stream.
byte[] buf = new byte[BufSize];
int read = 0;
while ((read = inStream.Read(buf, 0, buf.Length)) 0)
{
cryptoStream.Write(buf, 0, read);
}
cryptoStream.Flush();
outStream.Flush();
}
}
public void DecryptStream(Stream inStream, Stream outStream)
{
using (ICryptoTransform decryptor = cAlgo.CreateDecryptor())
using (CryptoStream cryptoStream = new CryptoStream(inStream,
decryptor, CryptoStreamMode.Read))
{
// Read from the cryptoStream until EOF and write decrypted
bytes to outFile.
byte[] ba = new byte[BufSize];
int read = 0;
while ((read = cryptoStream.Read(ba, 0, ba.Length)) 0)
{
outStream.Write(ba, 0, read);
}
outStream.Flush();
}
}
public static void Test()
{
Crypto crypto = new Crypto(CryptoAlgo.DES);
string key = crypto.Key;
string iv = crypto.IV;
crypto.EncryptFile("c:\\mydata.txt", "c:\\encrypted.txt");
crypto.DecryptFile("c:\\encrypted.txt", "c:\\decrypted.txt");
Console.WriteLine("Decrypted.txt:");
Console.WriteLine(File.ReadAllText("c:\\decrypted. txt")); //
Will work for text files.
// Test decrypting with stored key.
crypto = new Crypto(CryptoAlgo.DES, key, iv);
crypto.DecryptFile("c:\\encrypted.txt", "c:\\decrypted.txt");
Console.WriteLine("Decrypted.txt:");
Console.WriteLine(File.ReadAllText("c:\\decrypted. txt")); //
Will work for text files.
}
public void Dispose()
{
this.cAlgo.Clear();
}
}
}
--
William Stacey [C# MVP]
PCR concurrency library:
www.codeplex.com/pcr
PSH Scripts Project
www.codeplex.com/psobject
"William Stacey [C# MVP]" <wi************@gmail.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
| Actually, here is a better one that handles any size file in buffer size
| chunks.
|
| using System;
| using System.IO;
| using System.Security;
| using System.Security.Cryptography;
| using System.Runtime.InteropServices;
| using System.Text;
|
| namespace Demo
| {
| public class Class1
| {
| // 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);
|
| const int BufSize = 1024;
|
| // Function to Generate a 64 bits Key.
| public static string GenerateKey()
| {
| // Create an instance of Symetric Algorithm. Key and IV is
| generated automatically.
| DES des = DES.Create();
| return Encoding.ASCII.GetString(des.Key);
| }
|
| public static void EncryptFile(string inPath, string outPath,
string
| sKey)
| {
| DES des = DES.Create();
|
| using (FileStream inFile = File.OpenRead(inPath))
| using (FileStream outFile = new FileStream(outPath,
| FileMode.Create, FileAccess.Write))
| using (ICryptoTransform desencrypt =
| des.CreateEncryptor(Encoding.ASCII.GetBytes(sKey),
| Encoding.ASCII.GetBytes(sKey)))
| using (CryptoStream cryptoStream = new CryptoStream(outFile,
| desencrypt, CryptoStreamMode.Write))
| {
| // Read from in file until EOF and write to crypto stream.
| byte[] buf = new byte[BufSize];
| int read = 0;
| while ((read = inFile.Read(buf, 0, buf.Length)) 0)
| {
| cryptoStream.Write(buf, 0, read);
| }
| cryptoStream.Flush();
| outFile.Flush();
| }
| }
|
| public static void DecryptFile(string inPath, string outPath,
string
| sKey)
| {
| //A 64 bit key and IV is required for this provider.
| //Set secret key For DES algorithm.
| DES des = DES.Create();
|
| using (FileStream inFile = new FileStream(inPath,
FileMode.Open,
| FileAccess.Read))
| using (FileStream outFile = File.OpenWrite(outPath))
| using (ICryptoTransform desdecrypt =
| des.CreateDecryptor(Encoding.ASCII.GetBytes(sKey),
| Encoding.ASCII.GetBytes(sKey)))
| using (CryptoStream cryptoStream = new CryptoStream(inFile,
| desdecrypt, CryptoStreamMode.Read))
| {
| // Read from the cryptoStream until EOF and write decrypted
| bytes to outFile.
| byte[] ba = new byte[BufSize];
| int read = 0;
| while ((read = cryptoStream.Read(ba, 0, ba.Length)) 0)
| {
| outFile.Write(ba, 0, read);
| }
| outFile.Flush();
| }
| }
|
| public static void DoCrypto()
| {
| // Must be 64 bits, 8 bytes.
| // Distribute this key to the user who will decrypt this file.
| string sSecretKey;
|
| // Get the Key for the file to Encrypt.
| sSecretKey = GenerateKey();
|
| // For additional security Pin the key.
| GCHandle gch = GCHandle.Alloc(sSecretKey, GCHandleType.Pinned);
|
| // Encrypt the file.
| EncryptFile(@"C:\MyData.txt", @"C:\Encrypted.txt", sSecretKey);
| Console.WriteLine("Encrypted");
|
| // Decrypt the file.
| DecryptFile(@"C:\Encrypted.txt",
| @"C:\Decrypted.txt",sSecretKey);
| Console.WriteLine("Decrypted.");
|
| // Remove the Key from memory.
| ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2);
| gch.Free();
|
| Console.WriteLine("Done.");
| Console.WriteLine("Cat Decrypted.txt:");
| Cat(@"c:\decrypted.txt");
| }
|
| public static void Cat(string path)
| {
| Console.WriteLine(File.ReadAllText(path));
| }
| }
| }
|
| --
| William Stacey [C# MVP]
| PCR concurrency library:
www.codeplex.com/pcr
| PSH Scripts Project
www.codeplex.com/psobject
|
|
| "William Stacey [C# MVP]" <wi************@gmail.comwrote in message
| news:O3**************@TK2MSFTNGP06.phx.gbl...
|| Works over here. Well with text files. It is not a good sample. Try
|| something more like:
||
|| using System;
|| using System.IO;
|| using System.Security;
|| using System.Security.Cryptography;
|| using System.Runtime.InteropServices;
|| using System.Text;
||
|| namespace Demo
|| {
|| public class Class1
|| {
|| // 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)
|| {
|| DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
||
|| using (FileStream inFile = new FileStream(sInputFilename,
|| FileMode.Open, FileAccess.Read) )
|| using (FileStream outFile = new FileStream(sOutputFilename,
|| FileMode.Create, FileAccess.Write))
|| using (ICryptoTransform desencrypt =
|| DES.CreateEncryptor(Encoding.ASCII.GetBytes(sKey),
|| Encoding.ASCII.GetBytes(sKey)))
|| using (CryptoStream cryptoStream = new CryptoStream(outFile,
|| desencrypt, CryptoStreamMode.Write))
|| {
|| byte[] bytearrayinput = new byte[inFile.Length];
|| inFile.Read(bytearrayinput, 0, bytearrayinput.Length);
|| cryptoStream.Write(bytearrayinput, 0,
|| bytearrayinput.Length);
|| cryptoStream.Flush();
|| outFile.Flush();
|| }
|| }
||
|| public static void DecryptFile(string sInputFilename, string
|| sOutputFilename, string sKey)
|| {
|| //A 64 bit key and IV is required for this provider.
|| //Set secret key For DES algorithm.
|| DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
||
|| using (FileStream inFile = new FileStream(sInputFilename,
|| FileMode.Open, FileAccess.Read))
|| using (FileStream outFile = File.OpenWrite(sOutputFilename))
|| using (ICryptoTransform desdecrypt =
|| DES.CreateDecryptor(Encoding.ASCII.GetBytes(sKey),
|| Encoding.ASCII.GetBytes(sKey)))
|| using (CryptoStream cryptoStream = new CryptoStream(inFile,
|| desdecrypt, CryptoStreamMode.Read))
|| {
|| // Read from the cryptoStream until EOF and write
decrypted
|| bytes to outFile.
|| byte[] ba = new byte[1024];
|| int count = 0;
|| while ((count = cryptoStream.Read(ba, 0, ba.Length)) 0)
|| {
|| outFile.Write(ba, 0, count);
|| }
|| outFile.Flush();
|| }
|| }
||
|| public static void DoCrypto()
|| {
|| // Must be 64 bits, 8 bytes.
|| // Distribute this key to the user who will decrypt this file.
|| string sSecretKey;
||
|| // Get the Key for the file to Encrypt.
|| sSecretKey = GenerateKey();
||
|| // For additional security Pin the key.
|| GCHandle gch = GCHandle.Alloc(sSecretKey,
GCHandleType.Pinned);
||
|| // Encrypt the file.
|| EncryptFile(@"C:\MyData.txt", @"C:\Encrypted.txt",
sSecretKey);
|| Console.WriteLine("Encrypted");
||
|| // Decrypt the file.
|| DecryptFile(@"C:\Encrypted.txt",
|| @"C:\Decrypted.txt",sSecretKey);
|| Console.WriteLine("Decrypted.");
||
|| // Remove the Key from memory.
|| ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2);
|| gch.Free();
||
|| Console.WriteLine("Done.");
|| Console.WriteLine("Cat Decrypted.txt:");
|| Cat(@"c:\decrypted.txt");
|| }
||
|| public static void Cat(string path)
|| {
|| Console.WriteLine(File.ReadAllText(path));
|| }
|| }
|| }
||
||
|| --
|| William Stacey [C# MVP]
|| PCR concurrency library:
www.codeplex.com/pcr
|| PSH Scripts Project
www.codeplex.com/psobject
||
||
|| "JDeats" <Je**********@gmail.comwrote in message
|| news:11**********************@n76g2000hsh.googlegr oups.com...
|||I have some .NET 1.1 code that utilizes this technique for encrypting
||| and decrypting a file.
|||
http://support.microsoft.com/kb/307010
|||
||| In .NET 2.0 this approach is not fully supported (a .NET 2.0 build
||| with these methods, will appear to encrypt and decrypt, but the
||| resulting decrypted file will be corrupted. I tried encrypting a .bmp
||| file and then decrypting, the resulting decrypted file under .NET 2.0
||| is garbage, the .NET 1.1 build works as expected).
|||
||| I would like to know why this approach is no longer supported, aside
||| from building a .NET 1.1 class library and referencing it in my .NET
||| 2.0 project, what is the proper way to encrypt and decrypt a file
||| using ,NET 2.0 and the DES encryption algorithm.
|||
||
||
|
|