在.net Flamework完全版中对System.Security.Cryptography名字空间下的加密类支持得很好。但在精简版中却没有提供这个名字空间中的相应的类。在用.net写Pocket PC程序的时候用的加密算法的时候确实比较麻烦。一般有两种方法来解决这个问题。OpenNetCF( www.openetcf.org )提供了System.Security.Cryptography名字空间下的各个类的模拟,但它的提供缺乏灵活性:比如在对称加密的时候,用户无法设置Padding, CipherMode等属性。而且它的提供方式和完全版的.net下的类的接口不一致,这样给用户造成困惑。另一种方法就是自己动手对cryptoAPI进行自己封装。
最近出于工作需要对MD5CryptoServiceProvider进行了实现,这个类的接口和完整版下面的接口完全一致。
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();
//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 ));
}
}; // class MD5
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;
&nb