在.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;
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;
}
}
代码下载在codeproject上有:http://www.codeproject.com/useritems/md5cryptoserviceprovider.asp
reference:
dot net compact framework kick start 2003
www.opennetcf.org
http://www.koders.com/csharp/fidc21861b5f1b717ec1fdec006dbd0b8226b92d878.aspx