Introduction
The full .NET Framework includes rich support for cryptographic functions, such as computing hashes and encrypting data using a variety of algorithms.
Most Windows CE devices and all Pocket PC devices include an implementation of the CryptoAPI, which is a native code library that performs a wide variety of cryptographic functions. Its architecture allows developers to add new algorithm packages, thus extending the cryptography capabilities while retaining a familiar API for accessing new algorithms.
The OpenNetCF provides a very huge and integrated library which contains the “OpenNETCF.Security.Cryptography
” namespace for displacing the “System.Security.Cryptography
” namespace in the full .NET Framework. But it does not have the same interface with the full .NET Framework, it makes the user confuse. This subject provides an example to implement the MD5 as the hash cryptography functions. This example implements it by P/Invoke the CryptoAPI.
Imlementation
Demo code list
private void Form1_Load(object sender, System.EventArgs e)
{
HashAlgorithm x_hash_alg = HashAlgorithm.Create("MD5");
foreach(ListViewItem lvi in this.listView1.Items)
{
byte[] x_buf=System.Text.Encoding.ASCII.GetBytes(lvi.Text);
byte[] x_hash_code = x_hash_alg.ComputeHash(x_buf);
string s=ArrayToString(x_hash_code);
lvi.SubItems.Add(s);
}
this.listView1.Refresh();
}
private string ArrayToString(byte[] buf)
{
string str="";
for(int i=0;i<buf.Length;i++)
{
string tmp=buf[i].ToString("x");
if(tmp.Length>1)
{
str+=tmp;
}
else
{
str+="0"+tmp;
}
}
return str;
}
Implementation of the "System.Security.Cryptography.MD5CryptoServiceProvider" class
public sealed class MD5CryptoServiceProvider : MD5
{
public MD5CryptoServiceProvider()
{
Initialize();
m_Disposed = false;
}
public override void Initialize()
{
if (m_Disposed)
throw new ObjectDisposedException(this.GetType().FullName);
if (m_Hash != IntPtr.Zero)
{
Crypto.CryptDestroyHash(m_Hash);
}
m_Prov = Crypto.AcquireContext(ProvType.RSA_FULL);
bool retVal=Crypto.CryptCreateHash(m_Prov, (uint)CalgHash.MD5,
IntPtr.Zero, 0, out m_Hash);
}
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
if (m_Disposed)
throw new ObjectDisposedException(this.GetType().FullName);
byte[] copy = (byte[]) array.Clone();
bool retVal=false;
retVal=Crypto.CryptHashData(m_Hash, copy, copy.Length, 0);
}
protected override byte[] HashFinal()
{
if (m_Disposed)
throw new ObjectDisposedException(this.GetType().FullName);
byte [] data = new byte[0];
uint dataLen = 0;
uint flags = 0;
bool retVal = Crypto.CryptGetHashParam(m_Hash, (uint) HashParam.HASHVAL,
data, ref dataLen, flags);
if(234 == Marshal.GetLastWin32Error()) {
data = new byte[dataLen];
retVal = Crypto.CryptGetHashParam(m_Hash, (uint) HashParam.HASHVAL,
data, ref dataLen, flags);
}
return data;
}
protected override void Dispose(bool disposing)
{
if (!m_Disposed)
{
if (m_Hash != IntPtr.Zero)
{
bool retVal=Crypto.CryptDestroyHash(m_Hash);
m_Hash = IntPtr.Zero;
}
if(m_Prov!=IntPtr.Zero)
{
Crypto.CryptReleaseContext(m_Prov, 0);
m_Prov=IntPtr.Zero;
}
try
{
GC.SuppressFinalize(this);
}
catch {}
m_Disposed = true;
}
}
~MD5CryptoServiceProvider()
{
Clear();
}
private IntPtr m_Hash=IntPtr.Zero;
private bool m_Disposed;
private IntPtr m_Prov=IntPtr.Zero;
}
public abstract class MD5 : HashAlgorithm
{
protected MD5()
{
HashSizeValue = 128;
}
public new static MD5 Create()
{
return (MD5)(CryptoConfig.CreateFromName
(CryptoConfig.MD5Default, null));
}
public new static MD5 Create(String algName)
{
return (MD5)(CryptoConfig.CreateFromName(algName, null));
}
}
P/Invoke the cryotoAPI
public class Crypto
{
[DllImport("coredll.dll", EntryPoint="CryptAcquireContext")]
public static extern bool CryptAcquireContext(out IntPtr hProv,
string pszContainer, string pszProvider,
uint dwProvType, uint dwFlags);
[DllImport("coredll.dll", EntryPoint="CryptCreateHash")]
public static extern bool CryptCreateHash(IntPtr hProv,
uint Algid, IntPtr hKey, uint dwFlags, out IntPtr phHash);
[DllImport("coredll.dll", EntryPoint="CryptDestroyHash")]
public static extern bool CryptDestroyHash(IntPtr hHash);
[DllImport("coredll.dll", EntryPoint="CryptHashData")]
public static extern bool CryptHashData(IntPtr hHash,
byte[] pbData, int dwDataLen, uint dwFlags);
[DllImport("coredll.dll", EntryPoint="CryptGetHashParam", SetLastError=true)]
public static extern bool CryptGetHashParam(IntPtr hHash,
uint dwParam, byte[] pbData, ref uint pdwDataLen, uint dwFlags);
[DllImport("coredll.dll", EntryPoint="CryptReleaseContext")]
public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
public static IntPtr AcquireContext()
{
return AcquireContext("MD5Container", ProvName.MS_ENHANCED_PROV,
ProvType.RSA_FULL, ContextFlag.NONE);
}
public static IntPtr AcquireContext(string container)
{
return AcquireContext(container, ProvName.MS_ENHANCED_PROV,
ProvType.RSA_FULL, ContextFlag.NONE);
}
public static IntPtr AcquireContext(ProvType provType)
{
return AcquireContext(null, null, provType, ContextFlag.NONE);
}
public static IntPtr AcquireContext(string provName, ProvType provType)
{
return AcquireContext(null, provName, provType, ContextFlag.NONE);
}
public static IntPtr AcquireContext(string provName,
ProvType provType, ContextFlag conFlag)
{
return AcquireContext(null, provName, provType, conFlag);
}
public static IntPtr AcquireContext(string conName,
string provName, ProvType provType)
{
return AcquireContext(conName, provName, provType, ContextFlag.NONE);
}
public static IntPtr AcquireContext(string conName,
string provName, ProvType provType, ContextFlag conFlag)
{
IntPtr hProv;
bool retVal = Crypto.CryptAcquireContext(out hProv, conName,
provName, (uint) provType, (uint) conFlag);
if(!retVal) {
retVal = Crypto.CryptAcquireContext(out hProv, conName, provName,
(uint) provType, (uint) ContextFlag.NEWKEYSET);
}
if(hProv == IntPtr.Zero)
throw new Exception("System.Security.Cryptography");
return hProv;
}
}
References