eMbedded Visual C++ 4.0eMbedded Visual C++ 3.0eVC.NET CFVisual C++ 7.1Visual C++ 8.0.NET 1.0Visual Studio .NET 2003.NET 1.1中级开发Visual StudioWindowsC++.NETC#
实现 MD5CryptoServiceProvider,就像在完整框架中一样
.NET CF 的 MD5CryptoServiceProvider。
引言
完整的 .NET Framework 包含对加密功能的丰富支持,例如使用各种算法计算哈希和加密数据。
大多数 Windows CE 设备和所有 Pocket PC 设备都包含 CryptoAPI 的实现,这是一个本机代码库,执行各种加密功能。 其架构允许开发人员添加新的算法包,从而扩展加密功能,同时保留用于访问新算法的熟悉 API。
OpenNetCF 提供了一个非常庞大且集成的库,其中包含“OpenNETCF.Security.Cryptography
”命名空间,用于替换完整的 .NET Framework 中的“System.Security.Cryptography
”命名空间。 但它与完整的 .NET Framework 接口不相同,这会让用户感到困惑。 本主题提供了一个示例,以实现 MD5 作为哈希加密功能。 此示例通过 P/Invoke CryptoAPI 实现它。
实现
演示代码列表
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;
}
实现“System.Security.Cryptography.MD5CryptoServiceProvider”类
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();
//Array.Copy(array, ibStart, copy, 0, cbSize);
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;
//size
bool retVal = Crypto.CryptGetHashParam(m_Hash, (uint) HashParam.HASHVAL,
data, ref dataLen, flags);
if(234 == Marshal.GetLastWin32Error())//MORE_DATA = 234,
{
//data
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
{
// Constructor.
protected MD5()
{
HashSizeValue = 128;
}
// Create a new instance of the "MD5" class.
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 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) //try creating a new key container
{
retVal = Crypto.CryptAcquireContext(out hProv, conName, provName,
(uint) provType, (uint) ContextFlag.NEWKEYSET);
}
if(hProv == IntPtr.Zero)
throw new Exception("System.Security.Cryptography");
return hProv;
}
}
参考文献
- Dot NET Compact Framework Kick Start 2003。
- opennetcf.org.
- koders.com.