using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.IO;
private string EncryptionKey = "eggheadcafekey";
private string LocalPath = @"\My Documents\";
#region Encrypt String To File
private void button1_Click(object sender, System.EventArgs e)
{
string MyStringToEncrypt = "this is a normal string for encryption";
string MyFile = this.LocalPath + "encryptstringtofile.dat";
try
{
NullSkull.DataTransfer oTransfer = new NullSkull.DataTransfer();
if (oTransfer.EncryptStringToFile(MyFile,MyStringToEncrypt,EncryptionKey) == true)
{
MessageBox.Show("String encrypted to: " + MyFile);
}
else
{
MessageBox.Show("Failed to encrypt string to: " + MyFile);
}
}
catch (Exception err) { MessageBox.Show(err.Message); }
}
#endregion
#region Decrypt A File To String
private void button2_Click(object sender, System.EventArgs e)
{
string MyString = "";
string MyFile = this.LocalPath + "encryptstringtofile.dat";
try
{
NullSkull.DataTransfer oTransfer = new NullSkull.DataTransfer();
MyString = oTransfer.DecryptFileReturnString(MyFile,EncryptionKey);
MessageBox.Show(MyString);
}
catch (Exception err) { MessageBox.Show(err.Message); }
}
#endregion
#region Encrypt Normal File to Encrypted File
private void button3_Click(object sender, System.EventArgs e)
{
string MyNormalFile = this.LocalPath + "normalfile.txt";
string MyFile = this.LocalPath + "encrypted.dat";
try
{
StreamWriter oLocalFile = new StreamWriter(MyNormalFile);
oLocalFile.Write("this is a test string for the file");
oLocalFile.Close();
NullSkull.DataTransfer oTransfer = new NullSkull.DataTransfer();
if (oTransfer.EncryptFile(MyNormalFile,MyFile,EncryptionKey) == true)
{
// oTransfer.RemoveFile(MyNormalFile);
MessageBox.Show("Encrypted " + MyNormalFile + " to " + MyFile);
}
else
{
MessageBox.Show("Failed to encrypt " + MyNormalFile);
}
}
catch (Exception err) { MessageBox.Show(err.Message); }
}
#endregion
#region Decrypt File
private void button4_Click(object sender, System.EventArgs e)
{
string MyNormalFile = this.LocalPath + "normalfile.txt";
string MyFile = this.LocalPath + "encrypted.dat";
try
{
NullSkull.DataTransfer oTransfer = new NullSkull.DataTransfer();
if (oTransfer.DecryptFile(MyFile,MyNormalFile,EncryptionKey) == true)
{
// oTransfer.RemoveFile(MyFile);
MessageBox.Show("Decrypted " + MyFile + " to " + MyNormalFile);
}
else
{
MessageBox.Show("Failed to decrypt " + MyFile);
}
}
catch (Exception err) { MessageBox.Show(err.Message); }
}
#endregion
#region Upload File
private void button5_Click(object sender, System.EventArgs e)
{
NullSkull.DataTransfer oTransfer = new NullSkull.DataTransfer();
try
{
// Remember, the mobile device doesn't know what localhost is
// in relationship to your PC
string Url="http://192.168.0.100/fileupload.ashx";
string FileName="";
int FilesSent=0;
string[] oFiles = Directory.GetFiles(this.LocalPath,"*.dat");
if (oFiles.Length == 0)
{
MessageBox.Show("There are no encrypted files to transmit.");
return;
}
oTransfer.Hourglass(true);
for(int i=0;i<oFiles.Length;i++)
{
FileName = oTransfer.StripFileNameFromFolder(oFiles[i].ToString());
if (oTransfer.Upload(this.LocalPath,FileName,Url) == true)
{
FilesSent++;
}
}
MessageBox.Show(FilesSent.ToString() + " encrypted files transmitted successfully.");
}
catch (Exception err)
{
if (err.Message == "WebException")
{
MessageBox.Show("Please connect this device to the network.");
}
else
{
MessageBox.Show("Transmit: " + err.Message);
}
}
finally { oTransfer.Hourglass(false); }
}
#endregion
|
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Diagnostics;
namespace NullSkull
{
public class DataTransfer
{
public DataTransfer()
{
}
#region Encrypt File
public bool EncryptFile(string Filename1,string Filename2,string EncryptionKey)
{
bool Ret = false;
string Contents="";
ASCIIEncoding encoding = new ASCIIEncoding();
try
{
if (File.Exists(Filename1) == false) { return false; }
StreamReader oLocalFile = new StreamReader(Filename1);
Contents = oLocalFile.ReadToEnd();
oLocalFile.Close();
byte[] encryptData = Common.Crypto.Encrypt(EncryptionKey,encoding.GetBytes(Contents));
FileStream fs = new FileStream(Filename2, FileMode.Create);
BinaryWriter w = new BinaryWriter(fs);
w.Write(encryptData);
w.Close();
fs.Close();
Ret = true;
}
catch (Exception) { throw; }
return Ret;
}
#endregion
#region Encrypt String To File
public bool EncryptStringToFile(string Filename,string FileContents,string EncryptionKey)
{
bool Ret = false;
ASCIIEncoding encoding = new ASCIIEncoding();
try
{
if (File.Exists(Filename) == true) { File.Delete(Filename); }
byte[] encryptData = Common.Crypto.Encrypt(EncryptionKey,encoding.GetBytes(FileContents));
FileStream fs = new FileStream(Filename, FileMode.Create);
BinaryWriter w = new BinaryWriter(fs);
w.Write(encryptData);
w.Close();
fs.Close();
Ret = true;
}
catch (Exception) { throw; }
return Ret;
}
#endregion
#region Decrypt File
public bool DecryptFile(string Filename1,string Filename2,string EncryptionKey)
{
bool Ret = false;
ASCIIEncoding encoding = new ASCIIEncoding();
try
{
if (File.Exists(Filename1) == false) { return false; }
FileStream fr = new FileStream(Filename1, FileMode.Open);
BinaryReader r = new BinaryReader(fr);
byte[] decryptedData = Common.Crypto.Decrypt(EncryptionKey,r.ReadBytes((int)fr.Length));
r.Close();
fr.Close();
StreamWriter oLocalFile = new StreamWriter(Filename2);
oLocalFile.Write(encoding.GetString(decryptedData,0,decryptedData.Length));
oLocalFile.Close();
Ret = true;
}
catch (Exception) { throw; }
return Ret;
}
#endregion
#region Decrypt File Return String
public string DecryptFileReturnString(string Filename1,string EncryptionKey)
{
string Ret = "";
ASCIIEncoding encoding = new ASCIIEncoding();
try
{
if (File.Exists(Filename1) == false) { return Ret; }
FileStream fr = new FileStream(Filename1, FileMode.Open);
BinaryReader r = new BinaryReader(fr);
byte[] decryptedData = Common.Crypto.Decrypt(EncryptionKey,r.ReadBytes((int)fr.Length));
r.Close();
fr.Close();
Ret = encoding.GetString(decryptedData,0,decryptedData.Length);
}
catch (Exception) { throw; }
return Ret;
}
#endregion
#region Upload
public bool Upload(string FilePath,string FileName,string Url)
{
string BytesConfirmedReceived="";
int BytesSent=0;
bool Ret=false;
ASCIIEncoding encoding = new ASCIIEncoding();
try
{
if (File.Exists(FilePath + FileName) == false) { return true; }
FileInfo oInfo = new FileInfo(FilePath + FileName);
BytesSent = Convert.ToInt32(oInfo.Length.ToString());
Url += "?myfile=" + FileName.Trim();
FileStream fr = new FileStream(FilePath + FileName, FileMode.Open);
BinaryReader r = new BinaryReader(fr);
byte[] FileContents = r.ReadBytes((int)fr.Length);
r.Close();
fr.Close();
WebRequest oRequest = WebRequest.Create(Url);
oRequest.Method = "POST";
oRequest.Timeout=15000;
oRequest.ContentLength = FileContents.Length;
Stream oStream = oRequest.GetRequestStream();
BinaryWriter oWriter = new BinaryWriter(oStream);
oWriter.Write(FileContents);
oWriter.Close();
oStream.Close();
WebResponse oResponse = oRequest.GetResponse();
BytesConfirmedReceived = new StreamReader(oResponse.GetResponseStream(),
Encoding.Default).ReadToEnd();
oResponse.Close();
if (BytesSent.ToString() == BytesConfirmedReceived.Trim())
{
Ret = true;
}
}
catch (Exception)
{
throw;
}
return Ret;
}
#endregion
#region Remove File
public bool RemoveFile(string FileName)
{
bool Ret=false;
try
{
if (File.Exists(FileName) == false) { return true; }
File.Delete(FileName);
Ret=true;
}
catch (Exception) { throw; }
return Ret;
}
#endregion
#region Strip File Name From Folder
public string StripFileNameFromFolder(string FullFileName)
{
int nPos=0;
string sNewVal="";
try
{
FullFileName = FullFileName.Trim();
if (FullFileName.Length <1) { return FullFileName; }
nPos = FullFileName.LastIndexOf(@"\") + 1;
if (nPos<1) { return FullFileName; }
sNewVal = FullFileName.Substring(nPos,FullFileName.Length - nPos);
}
catch (Exception e) { sNewVal = e.Message; }
return sNewVal;
}
#endregion
#region Hourglass
public void Hourglass(bool Show)
{
if (Show == true)
{
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
}
else
{
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
}
return;
}
#endregion
}
}
|
/*
Encryption Class From Microsoft Signature Sample
--
Uses crypto API functions to encrypt and decrypt data. A passphrase
string is used to create a 128-bit hash that is used to create a
40-bit crypto key. The same key is required to encrypt and decrypt
the data.
*/
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
namespace Common
{
/// <summary>
/// Encrypts and decrypts data using the crypto APIs.
/// </summary>
public class Crypto
{
// API functions
private class WinApi
{
#region Crypto API imports
private const uint ALG_CLASS_HASH = (4 << 13);
private const uint ALG_TYPE_ANY = (0);
private const uint ALG_CLASS_DATA_ENCRYPT = (3 << 13);
private const uint ALG_TYPE_STREAM = (4 << 9);
private const uint ALG_TYPE_BLOCK = (3 << 9);
private const uint ALG_SID_DES = 1;
private const uint ALG_SID_RC4 = 1;
private const uint ALG_SID_RC2 = 2;
private const uint ALG_SID_MD5 = 3;
public const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
public const uint PROV_RSA_FULL = 1;
public const uint CRYPT_VERIFYCONTEXT = 0xf0000000;
public const uint CRYPT_EXPORTABLE = 0x00000001;
public static readonly uint CALG_MD5 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5);
public static readonly uint CALG_DES = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK
| ALG_SID_DES);
public static readonly uint CALG_RC2 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK
| ALG_SID_RC2);
public static readonly uint CALG_RC4 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM |
ALG_SID_RC4);
// Use these dlls for mobile devices only
const string CryptDll = "coredll.dll";
const string KernelDll = "coredll.dll";
// Use these dlls for all other pcs and servers
// const string CryptDll = "advapi32.dll";
// const string KernelDll = "kernel32.dll";
[DllImport(CryptDll)]
public static extern bool CryptAcquireContext(
ref IntPtr phProv, string pszContainer, string pszProvider,
uint dwProvType, uint dwFlags);
[DllImport(CryptDll)]
public static extern bool CryptReleaseContext(
IntPtr hProv, uint dwFlags);
[DllImport(CryptDll)]
public static extern bool CryptDeriveKey(
IntPtr hProv, uint Algid, IntPtr hBaseData,
uint dwFlags, ref IntPtr phKey);
[DllImport(CryptDll)]
public static extern bool CryptCreateHash(
IntPtr hProv, uint Algid, IntPtr hKey,
uint dwFlags, ref IntPtr phHash);
[DllImport(CryptDll)]
public static extern bool CryptHashData(
IntPtr hHash, byte[] pbData,
uint dwDataLen, uint dwFlags);
[DllImport(CryptDll)]
public static extern bool CryptEncrypt(
IntPtr hKey, IntPtr hHash, bool Final, uint dwFlags,
byte[] pbData, ref uint pdwDataLen, uint dwBufLen);
[DllImport(CryptDll)]
public static extern bool CryptDecrypt(
IntPtr hKey, IntPtr hHash, bool Final, uint dwFlags,
byte[] pbData, ref uint pdwDataLen);
[DllImport(CryptDll)]
public static extern bool CryptDestroyHash(IntPtr hHash);
[DllImport(CryptDll)]
public static extern bool CryptDestroyKey(IntPtr hKey);
#endregion
#region Error reporting imports
public const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
[DllImport(KernelDll)]
public static extern uint GetLastError();
[DllImport(KernelDll)]
public static extern uint FormatMessage(
uint dwFlags, string lpSource, uint dwMessageId,
uint dwLanguageId, StringBuilder lpBuffer, uint nSize,
string [] Arguments);
#endregion
}
// all static methods
private Crypto()
{
}
/// <summary>
/// Encrypt data. Use passphrase to generate the encryption key.
/// Returns a byte array that contains the encrypted data.
/// </summary>
static public byte[] Encrypt(string passphrase, byte[] data)
{
// holds encrypted data
byte[] buffer = null;
// crypto handles
IntPtr hProv = IntPtr.Zero;
IntPtr hKey = IntPtr.Zero;
try
{
// get crypto provider, specify the provider (3rd argument)
// instead of using default to ensure the same provider is
// used on client and server
if (!WinApi.CryptAcquireContext(ref hProv, null, WinApi.MS_DEF_PROV,
WinApi.PROV_RSA_FULL, WinApi.CRYPT_VERIFYCONTEXT))
Failed("CryptAcquireContext");
// generate encryption key from passphrase
hKey = GetCryptoKey(hProv, passphrase);
// determine how large of a buffer is required
// to hold the encrypted data
uint dataLength = (uint)data.Length;
uint bufLength = (uint)data.Length;
if (!WinApi.CryptEncrypt(hKey, IntPtr.Zero, true,
0, null, ref dataLength, bufLength))
Failed("CryptEncrypt");
// allocate and fill buffer with encrypted data
buffer = new byte[dataLength];
Buffer.BlockCopy(data, 0, buffer, 0, data.Length);
dataLength = (uint)data.Length;
bufLength = (uint)buffer.Length;
if (!WinApi.CryptEncrypt(hKey, IntPtr.Zero, true,
0, buffer, ref dataLength, bufLength))
Failed("CryptEncrypt");
}
finally
{
// release crypto handles
if (hKey != IntPtr.Zero)
WinApi.CryptDestroyKey(hKey);
if (hProv != IntPtr.Zero)
WinApi.CryptReleaseContext(hProv, 0);
}
return buffer;
}
/// <summary>
/// Decrypt data. Use passphrase to generate the encryption key.
/// Returns a byte array that contains the decrypted data.
/// </summary>
static public byte[] Decrypt(string passphrase, byte[] data)
{
// make a copy of the encrypted data
byte[] dataCopy = data.Clone() as byte[];
// holds the decrypted data
byte[] buffer = null;
// crypto handles
IntPtr hProv = IntPtr.Zero;
IntPtr hKey = IntPtr.Zero;
try
{
// get crypto provider, specify the provider (3rd argument)
// instead of using default to ensure the same provider is
// used on client and server
if (!WinApi.CryptAcquireContext(ref hProv, null, WinApi.MS_DEF_PROV,
WinApi.PROV_RSA_FULL, WinApi.CRYPT_VERIFYCONTEXT))
Failed("CryptAcquireContext");
// generate encryption key from the passphrase
hKey = GetCryptoKey(hProv, passphrase);
// decrypt the data
uint dataLength = (uint)dataCopy.Length;
if (!WinApi.CryptDecrypt(hKey, IntPtr.Zero, true,
0, dataCopy, ref dataLength))
Failed("CryptDecrypt");
// copy to a buffer that is returned to the caller
// the decrypted data size might be less then
// the encrypted size
buffer = new byte[dataLength];
Buffer.BlockCopy(dataCopy, 0, buffer, 0, (int)dataLength);
}
finally
{
// release crypto handles
if (hKey != IntPtr.Zero)
WinApi.CryptDestroyKey(hKey);
if (hProv != IntPtr.Zero)
WinApi.CryptReleaseContext(hProv, 0);
}
return buffer;
}
/// <summary>
/// Create a crypto key form a passphrase. This key is
/// used to encrypt and decrypt data.
/// </summary>
static private IntPtr GetCryptoKey(IntPtr hProv, string passphrase)
{
// crypto handles
IntPtr hHash = IntPtr.Zero;
IntPtr hKey = IntPtr.Zero;
try
{
// create 128 bit hash object
if (!WinApi.CryptCreateHash(hProv,
WinApi.CALG_MD5, IntPtr.Zero, 0, ref hHash))
Failed("CryptCreateHash");
// add passphrase to hash
byte[] keyData = ASCIIEncoding.ASCII.GetBytes(passphrase);
if (!WinApi.CryptHashData(hHash, keyData, (uint)keyData.Length, 0))
Failed("CryptHashData");
// create 40 bit crypto key from passphrase hash
if (!WinApi.CryptDeriveKey(hProv, WinApi.CALG_RC2,
hHash, WinApi.CRYPT_EXPORTABLE, ref hKey))
Failed("CryptDeriveKey");
}
finally
{
// release hash object
if (hHash != IntPtr.Zero)
WinApi.CryptDestroyHash(hHash);
}
return hKey;
}
/// <summary>
/// Throws SystemException with GetLastError information.
/// </summary>
static private void Failed(string command)
{
uint lastError = WinApi.GetLastError();
StringBuilder sb = new StringBuilder(500);
try
{
// get message for last error
WinApi.FormatMessage(WinApi.FORMAT_MESSAGE_FROM_SYSTEM,
null, lastError, 0, sb, 500, null);
}
catch
{
// error calling FormatMessage
sb.Append("N/A.");
}
throw new SystemException(
string.Format("{0} failed.\r\nLast error - 0x{1:x}.\r\nError message - {2}",
command, lastError, sb.ToString()));
}
}
}
|
<%@ WebHandler Language="C#" Class="CustomHandler.FileUpload" %>
using System;
using System.Xml;
using System.Data;
using System.Web;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
namespace CustomHandler
{
public class FileUpload : IHttpHandler
{
public void ProcessRequest(HttpContext oContext)
{
int BytesSent = 0;
int MaxBytesAccepted=10000;
string sXml="";
string LocalPath = @"C:\Inetpub\wwwroot\";
string MyFile="";
string Key="eggheadcafekey";
try
{
MyFile = LocalPath + oContext.Request["myfile"].ToString().Trim();
ASCIIEncoding encoding = new ASCIIEncoding();
BytesSent = oContext.Request.TotalBytes;
// Block out file uploads that are too big
if (BytesSent > MaxBytesAccepted) { oContext.Response.Write("0"); return; }
byte[] InComingBinaryArray = oContext.Request.BinaryRead(oContext.Request.TotalBytes);
byte[] decryptedData = Common.Crypto.Decrypt(Key,InComingBinaryArray);
// Validate the data inside. For instance, if you know the data is Xml, you
// attempt to load it. If you know some of its contents, you could check
// for that as well.
/*
sXml = encoding.GetString(decryptedData);
XmlDocument oXml = new XmlDocument();
oXml.LoadXml(sXml);
if (oXml.ChildNodes.Count == 0) { oContext.Response.Write("0"); return; }
*/
if (File.Exists(MyFile) == true)
{
File.Delete(MyFile);
}
FileStream fs = new FileStream(MyFile, FileMode.CreateNew);
BinaryWriter w = new BinaryWriter(fs);
w.Write(InComingBinaryArray);
w.Close();
fs.Close();
FileInfo oInfo = new FileInfo(MyFile);
oContext.Response.Write(oInfo.Length.ToString());
}
catch (Exception err) { oContext.Response.Write(err.Message); }
}
public bool IsReusable { get { return true; } }
}
}
/*
Signature Sample Cryptography class for Microsoft Sample
--
Uses crypto API functions to encrypt and decrypt data. A passphrase
string is used to create a 128-bit hash that is used to create a
40-bit crypto key. The same key is required to encrypt and decrypt
the data.
*/
namespace Common
{
/// <summary>
/// Encrypts and decrypts data using the crypto APIs.
/// </summary>
public class Crypto
{
// API functions
private class WinApi
{
#region Crypto API imports
private const uint ALG_CLASS_HASH = (4 << 13);
private const uint ALG_TYPE_ANY = (0);
private const uint ALG_CLASS_DATA_ENCRYPT = (3 << 13);
private const uint ALG_TYPE_STREAM = (4 << 9);
private const uint ALG_TYPE_BLOCK = (3 << 9);
private const uint ALG_SID_DES = 1;
private const uint ALG_SID_RC4 = 1;
private const uint ALG_SID_RC2 = 2;
private const uint ALG_SID_MD5 = 3;
public const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
public const uint PROV_RSA_FULL = 1;
public const uint CRYPT_VERIFYCONTEXT = 0xf0000000;
public const uint CRYPT_EXPORTABLE = 0x00000001;
public static readonly uint CALG_MD5 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5);
public static readonly uint CALG_DES = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_DES);
public static readonly uint CALG_RC2 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_RC2);
public static readonly uint CALG_RC4 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | ALG_SID_RC4);
const string CryptDll = "advapi32.dll";
const string KernelDll = "kernel32.dll";
[DllImport(CryptDll)]
public static extern bool CryptAcquireContext(
ref IntPtr phProv, string pszContainer, string pszProvider,
uint dwProvType, uint dwFlags);
[DllImport(CryptDll)]
public static extern bool CryptReleaseContext(
IntPtr hProv, uint dwFlags);
[DllImport(CryptDll)]
public static extern bool CryptDeriveKey(
IntPtr hProv, uint Algid, IntPtr hBaseData,
uint dwFlags, ref IntPtr phKey);
[DllImport(CryptDll)]
public static extern bool CryptCreateHash(
IntPtr hProv, uint Algid, IntPtr hKey,
uint dwFlags, ref IntPtr phHash);
[DllImport(CryptDll)]
public static extern bool CryptHashData(
IntPtr hHash, byte[] pbData,
uint dwDataLen, uint dwFlags);
[DllImport(CryptDll)]
public static extern bool CryptEncrypt(
IntPtr hKey, IntPtr hHash, bool Final, uint dwFlags,
byte[] pbData, ref uint pdwDataLen, uint dwBufLen);
[DllImport(CryptDll)]
public static extern bool CryptDecrypt(
IntPtr hKey, IntPtr hHash, bool Final, uint dwFlags,
byte[] pbData, ref uint pdwDataLen);
[DllImport(CryptDll)]
public static extern bool CryptDestroyHash(IntPtr hHash);
[DllImport(CryptDll)]
public static extern bool CryptDestroyKey(IntPtr hKey);
#endregion
#region Error reporting imports
public const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
[DllImport(KernelDll)]
public static extern uint GetLastError();
[DllImport(KernelDll)]
public static extern uint FormatMessage(
uint dwFlags, string lpSource, uint dwMessageId,
uint dwLanguageId, StringBuilder lpBuffer, uint nSize,
string [] Arguments);
#endregion
}
// all static methods
private Crypto()
{
}
/// <summary>
/// Encrypt data. Use passphrase to generate the encryption key.
/// Returns a byte array that contains the encrypted data.
/// </summary>
static public byte[] Encrypt(string passphrase, byte[] data)
{
// holds encrypted data
byte[] buffer = null;
// crypto handles
IntPtr hProv = IntPtr.Zero;
IntPtr hKey = IntPtr.Zero;
try
{
// get crypto provider, specify the provider (3rd argument)
// instead of using default to ensure the same provider is
// used on client and server
if (!WinApi.CryptAcquireContext(ref hProv, null, WinApi.MS_DEF_PROV,
WinApi.PROV_RSA_FULL, WinApi.CRYPT_VERIFYCONTEXT))
Failed("CryptAcquireContext");
// generate encryption key from passphrase
hKey = GetCryptoKey(hProv, passphrase);
// determine how large of a buffer is required
// to hold the encrypted data
uint dataLength = (uint)data.Length;
uint bufLength = (uint)data.Length;
if (!WinApi.CryptEncrypt(hKey, IntPtr.Zero, true,
0, null, ref dataLength, bufLength))
Failed("CryptEncrypt");
// allocate and fill buffer with encrypted data
buffer = new byte[dataLength];
Buffer.BlockCopy(data, 0, buffer, 0, data.Length);
dataLength = (uint)data.Length;
bufLength = (uint)buffer.Length;
if (!WinApi.CryptEncrypt(hKey, IntPtr.Zero, true,
0, buffer, ref dataLength, bufLength))
Failed("CryptEncrypt");
}
finally
{
// release crypto handles
if (hKey != IntPtr.Zero)
WinApi.CryptDestroyKey(hKey);
if (hProv != IntPtr.Zero)
WinApi.CryptReleaseContext(hProv, 0);
}
return buffer;
}
/// <summary>
/// Decrypt data. Use passphrase to generate the encryption key.
/// Returns a byte array that contains the decrypted data.
/// </summary>
static public byte[] Decrypt(string passphrase, byte[] data)
{
// make a copy of the encrypted data
byte[] dataCopy = data.Clone() as byte[];
// holds the decrypted data
byte[] buffer = null;
// crypto handles
IntPtr hProv = IntPtr.Zero;
IntPtr hKey = IntPtr.Zero;
try
{
// get crypto provider, specify the provider (3rd argument)
// instead of using default to ensure the same provider is
// used on client and server
if (!WinApi.CryptAcquireContext(ref hProv, null, WinApi.MS_DEF_PROV,
WinApi.PROV_RSA_FULL, WinApi.CRYPT_VERIFYCONTEXT))
Failed("CryptAcquireContext");
// generate encryption key from the passphrase
hKey = GetCryptoKey(hProv, passphrase);
// decrypt the data
uint dataLength = (uint)dataCopy.Length;
if (!WinApi.CryptDecrypt(hKey, IntPtr.Zero, true,
0, dataCopy, ref dataLength))
Failed("CryptDecrypt");
// copy to a buffer that is returned to the caller
// the decrypted data size might be less then
// the encrypted size
buffer = new byte[dataLength];
Buffer.BlockCopy(dataCopy, 0, buffer, 0, (int)dataLength);
}
finally
{
// release crypto handles
if (hKey != IntPtr.Zero)
WinApi.CryptDestroyKey(hKey);
if (hProv != IntPtr.Zero)
WinApi.CryptReleaseContext(hProv, 0);
}
return buffer;
}
/// <summary>
/// Create a crypto key form a passphrase. This key is
/// used to encrypt and decrypt data.
/// </summary>
static private IntPtr GetCryptoKey(IntPtr hProv, string passphrase)
{
// crypto handles
IntPtr hHash = IntPtr.Zero;
IntPtr hKey = IntPtr.Zero;
try
{
// create 128 bit hash object
if (!WinApi.CryptCreateHash(hProv,
WinApi.CALG_MD5, IntPtr.Zero, 0, ref hHash))
Failed("CryptCreateHash");
// add passphrase to hash
byte[] keyData = ASCIIEncoding.ASCII.GetBytes(passphrase);
if (!WinApi.CryptHashData(hHash, keyData, (uint)keyData.Length, 0))
Failed("CryptHashData");
// create 40 bit crypto key from passphrase hash
if (!WinApi.CryptDeriveKey(hProv, WinApi.CALG_RC2,
hHash, WinApi.CRYPT_EXPORTABLE, ref hKey))
Failed("CryptDeriveKey");
}
finally
{
// release hash object
if (hHash != IntPtr.Zero)
WinApi.CryptDestroyHash(hHash);
}
return hKey;
}
/// <summary>
/// Throws SystemException with GetLastError information.
/// </summary>
static private void Failed(string command)
{
uint lastError = WinApi.GetLastError();
StringBuilder sb = new StringBuilder(500);
try
{
// get message for last error
WinApi.FormatMessage(WinApi.FORMAT_MESSAGE_FROM_SYSTEM,
null, lastError, 0, sb, 500, null);
}
catch
{
// error calling FormatMessage
sb.Append("N/A.");
}
throw new SystemException(
string.Format("{0} failed.\r\nLast error - 0x{1:x}.\r\nError message - {2}",
command, lastError, sb.ToString()));
}
}
}
|