Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Implement the MD5CryptoServiceProvider like in the full framework

0.00/5 (No votes)
11 Mar 2005 1  
MD5CryptoServiceProvider for .NET CF.

Sample Image - MD5CryptoServiceProvider.jpg

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();
     //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 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;
  }
 }

References

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here