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 { EggHeadCafe.DataTransfer oTransfer = new EggHeadCafe.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 { EggHeadCafe.DataTransfer oTransfer = new EggHeadCafe.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(); EggHeadCafe.DataTransfer oTransfer = new EggHeadCafe.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 { EggHeadCafe.DataTransfer oTransfer = new EggHeadCafe.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) { EggHeadCafe.DataTransfer oTransfer = new EggHeadCafe.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 EggHeadCafe { 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())); } } }
Articles
Submit Article
Message Board
Software Downloads
Videos
Rant & Rave
About Us