Click here to Skip to main content
15,881,715 members
Articles / Programming Languages / eVC

Implement the MD5CryptoServiceProvider like in the full framework

Rate me:
Please Sign up or sign in to vote.
2.23/5 (4 votes)
11 Mar 2005CPOL 46.4K   380   14   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

C#
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

C#
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

C#
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
China China
My home page: http://www.xtrafinal.com

Comments and Discussions

 
Question33 char Md5 ??? Pin
nmrdk14-Nov-05 6:49
nmrdk14-Nov-05 6:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.