2003-02-05 Sebastien Pouliot <spouliot@videotron.ca>
authorSebastien Pouliot <sebastien@ximian.com>
Thu, 6 Feb 2003 03:27:34 +0000 (03:27 -0000)
committerSebastien Pouliot <sebastien@ximian.com>
Thu, 6 Feb 2003 03:27:34 +0000 (03:27 -0000)
* CapiContext.cs: New. Class to acquire and release an
  unmanaged context with CryptoAPI.
* CapiHash.cs: New. Base class to handle hash algorithms.
* CapiRandomNumberGenerator.cs: New. Base class to handle
  random number generation.
* CryptoAPI.cs: Wrapper class around CryptoAPI.
* MD2.cs: Abstract class for Message Digest 2 (RFC1319).
* MD2CryptoServiceProvider.cs: Unmanaged MD2 implementation.
* MD4.cs: Abstract class for Message Digest 4 (RFC1320).
* MD4CryptoServiceProvider.cs: Unmanaged MD4 implementation.
* MD5CryptoServiceProvider.cs: Unmanaged MD5 implementation.
* RNGCryptoServiceProvider.cs: Unmanaged RNG implementation.
* MD2CryptoServiceProvider.cs: Unmanaged SHA1 implementation.

svn path=/trunk/mcs/; revision=11259

12 files changed:
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CapiContext.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CapiHash.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CapiRandomNumberGenerator.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/ChangeLog [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CryptoAPI.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD2.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD2CryptoServiceProvider.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD4.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD4CryptoServiceProvider.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD5CryptoServiceProvider.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/RNGCryptoServiceProvider.cs [new file with mode: 0644]
mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/SHA1CryptoServiceProvider.cs [new file with mode: 0644]

diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CapiContext.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CapiContext.cs
new file mode 100644 (file)
index 0000000..e33ffb6
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Mono.Security.Cryptography.CapiContext
+//
+// Authors:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+// we deal with unmanaged resources - they MUST be released after use!
+public class CapiContext : IDisposable {
+
+       // handles to CryptoAPI - they are 
+       protected IntPtr providerHandle;
+        
+       protected CspParameters cspParams;
+
+       // has the last call succeded ?
+       protected bool lastResult;
+
+       // Create an instance using the default CSP
+       public CapiContext ()
+       {
+               Acquire (null);
+       }
+
+       // Create an instance using the specified CSP
+       public CapiContext (CspParameters csp) 
+       {
+               Acquire (csp);
+               // do not show user interface (CRYPT_SILENT) - if UI is required then the function fails.
+               lastResult = CryptoAPI.CryptAcquireContextA (ref providerHandle, cspParams.KeyContainerName, cspParams.ProviderName, cspParams.ProviderType, CryptoAPI.CRYPT_SILENT);
+       }
+
+       ~CapiContext () 
+       {
+               Dispose ();
+       }
+
+       public int Error {
+               get { return CryptoAPI.GetLastError(); }
+       }
+
+       public IntPtr Handle {
+               get { return providerHandle; }
+       }
+
+       public bool Result {
+               get { return lastResult; }
+       }
+
+       internal bool InternalResult {
+               set { lastResult = value; }
+       }
+
+       private void Acquire (CspParameters csp) 
+       {
+               providerHandle = IntPtr.Zero;
+               if (csp == null) {
+                       // default parameters
+                       cspParams = new CspParameters ();
+               }
+               else {
+                       // keep of copy of the parameters
+                       cspParams = new CspParameters (csp.ProviderType, csp.ProviderName, csp.KeyContainerName);
+                       cspParams.KeyNumber = csp.KeyNumber;
+                       cspParams.Flags = csp.Flags;
+               }
+               // do not show user interface (CRYPT_SILENT) -  if UI is required then the function fails.
+               lastResult = CryptoAPI.CryptAcquireContextA (ref providerHandle, cspParams.KeyContainerName, cspParams.ProviderName, cspParams.ProviderType, 0);
+       }
+
+       // release unmanaged resources
+       public void Dispose () 
+       {
+               if (providerHandle != IntPtr.Zero) {
+                       lastResult = CryptoAPI.CryptReleaseContext (providerHandle, 0);
+                       providerHandle = IntPtr.Zero;
+               }
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CapiHash.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CapiHash.cs
new file mode 100644 (file)
index 0000000..e2cabb1
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Mono.Security.Cryptography.CapiHash
+//
+// Authors:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+public class CapiHash {
+
+       private CapiContext context;
+       private IntPtr handle;
+       private uint hashSize;
+
+       public CapiHash (uint hashAlgorithm) 
+       {
+               context = new CapiContext ();
+               Initialize (hashAlgorithm);
+       }
+
+       public CapiHash (CapiContext ctx, uint hashAlgorithm) 
+       {
+               context = ctx;
+               Initialize (hashAlgorithm);
+       }
+
+       public CapiHash (CspParameters cspParams, uint hashAlgorithm) 
+       {
+               context = new CapiContext (cspParams);
+               Initialize (hashAlgorithm);
+       }
+
+       public IntPtr Handle {
+               get { return handle; }
+       }
+
+       public int HashSize {
+               get { return (int) hashSize; }
+       }
+
+       public void Initialize (uint algo) 
+       {
+               if (context != null) {
+                       context.InternalResult = CryptoAPI.CryptCreateHash (context.Handle, algo, IntPtr.Zero, 0, ref handle);
+                       hashSize = 0;
+                       if (context.Result)
+                               context.InternalResult = CryptoAPI.CryptGetHashParam (handle, CryptoAPI.HP_HASHVAL, null, ref hashSize, 0);
+               }
+       }
+
+       public void Dispose () 
+       {
+               if (handle != IntPtr.Zero) {
+                       CryptoAPI.CryptDestroyHash (handle);
+                       handle = IntPtr.Zero;
+               }
+       }
+
+       // FIXME: calling this function 1,000,000 times (with a single character)
+       // is a good way to lose time (and hung NUnit)
+       // TODO: find the bug that hang NUnit
+       // TODO: optimize the function to call CryptHashData less often (bufferize)
+       public void HashCore (byte[] data, int start, int length) 
+       {
+               byte[] toBeHashed = data;
+               if (start != 0) {
+                       toBeHashed = new byte [length];
+                       Array.Copy (data, start, toBeHashed, 0, length);
+               }
+               context.InternalResult = CryptoAPI.CryptHashData (handle, toBeHashed, (uint)length, 0);
+       }
+
+       public byte[] HashFinal () 
+       {
+               byte[] hash = new byte [hashSize];
+               context.InternalResult = CryptoAPI.CryptGetHashParam (handle, CryptoAPI.HP_HASHVAL, hash, ref hashSize, 0);
+               return hash;
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CapiRandomNumberGenerator.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CapiRandomNumberGenerator.cs
new file mode 100644 (file)
index 0000000..514efef
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// Mono.Security.Cryptography.CapiRandomNumberGenerator
+//
+// Authors:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+class CapiRandomNumberGenerator : CapiContext {
+
+       public CapiRandomNumberGenerator () : base () {}
+
+       public CapiRandomNumberGenerator (CspParameters cspParams) : base (cspParams) {}
+
+       public void GenRandom (byte[] data) 
+       {
+               uint l = (uint) data.Length;
+               lastResult = CryptoAPI.CryptGenRandom (providerHandle, l, data);
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/ChangeLog b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/ChangeLog
new file mode 100644 (file)
index 0000000..aa9b77c
--- /dev/null
@@ -0,0 +1,16 @@
+2003-02-05  Sebastien Pouliot  <spouliot@videotron.ca>
+
+       * CapiContext.cs: New. Class to acquire and release an
+         unmanaged context with CryptoAPI.
+       * CapiHash.cs: New. Base class to handle hash algorithms.
+       * CapiRandomNumberGenerator.cs: New. Base class to handle
+         random number generation.
+       * CryptoAPI.cs: Wrapper class around CryptoAPI.
+       * MD2.cs: Abstract class for Message Digest 2 (RFC1319).
+       * MD2CryptoServiceProvider.cs: Unmanaged MD2 implementation.
+       * MD4.cs: Abstract class for Message Digest 4 (RFC1320).
+       * MD4CryptoServiceProvider.cs: Unmanaged MD4 implementation.
+       * MD5CryptoServiceProvider.cs: Unmanaged MD5 implementation.
+       * RNGCryptoServiceProvider.cs: Unmanaged RNG implementation.
+       * MD2CryptoServiceProvider.cs: Unmanaged SHA1 implementation.
+
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CryptoAPI.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/CryptoAPI.cs
new file mode 100644 (file)
index 0000000..79fe8ac
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// Mono.Security.Cryptography.CryptoAPI
+//
+// Authors:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Mono.Security.Cryptography {
+
+internal class CryptoAPI {
+
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptAcquireContextA (ref IntPtr phProv, string pszContainer, string pszProvider, int dwProvType, uint dwFlags);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptCreateHash (IntPtr hProv, uint Algid, IntPtr hKey, uint dwFlags, ref IntPtr phHash);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptDecrypt (IntPtr hKey, IntPtr hHash, bool Final, uint dwFlags, byte[] pbData, ref uint pdwDataLen);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptDestroyHash (IntPtr hHash);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptDestroyKey (IntPtr hKey);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptEncrypt (IntPtr hKey, IntPtr hHash, bool Final, uint dwFlags, byte[] pbData, ref uint pdwDataLen, uint dwBufLen);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptGenKey (IntPtr hProv, uint Algid, uint dwFlags, ref IntPtr phKey);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptGenRandom (IntPtr hProv, uint dwLen, byte[] pbBuffer);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptGetHashParam (IntPtr hHash, uint dwParam, byte[] pbData, ref uint pdwDataLen, uint dwFlags);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptHashData (IntPtr hHash, byte[] pbData, uint dwDataLen, uint dwFlags);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptImportKey (IntPtr hProv, byte[] pbData, uint dwDataLen, IntPtr hPubKey, uint dwFlags, ref IntPtr phKey);
+       [DllImport ("advapi32.dll", SetLastError=true)]
+       public static extern bool CryptReleaseContext (IntPtr hProv, uint dwFlags);
+
+       public static readonly uint CRYPT_VERIFYCONTEXT  = 0xF0000000;
+       public static readonly uint CRYPT_NEWKEYSET      = 0x00000008;
+       public static readonly uint CRYPT_DELETEKEYSET   = 0x00000010;
+       public static readonly uint CRYPT_MACHINE_KEYSET = 0x00000020;
+       public static readonly uint CRYPT_SILENT         = 0x00000040;
+
+       public static readonly int PROV_RSA_FULL         = 1;
+
+       public static readonly uint HP_HASHVAL           = 0x0002;
+
+       public static readonly uint CALG_MD2  = 0x8001;
+       public static readonly uint CALG_MD4  = 0x8002;
+       public static readonly uint CALG_MD5  = 0x8003;
+       public static readonly uint CALG_SHA1 = 0x8004;
+
+       // just so we don't have to add System.Runtime.InteropServices
+       // in every file
+       static public int GetLastError () 
+       {
+               return Marshal.GetLastWin32Error ();
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD2.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD2.cs
new file mode 100644 (file)
index 0000000..60e13c2
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// MD2.cs - Message Digest 2 Abstract class
+//
+// Author:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// (C) 2001-2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+public abstract class MD2 : HashAlgorithm {
+
+       protected MD2 () 
+       {
+               // MD2 hash length are 128 bits long
+               HashSizeValue = 128; 
+       }
+
+       public static new MD2 Create ()
+       {
+               // for this to work we must register ourself with CryptoConfig
+               return Create ("MD2");
+       }
+
+       public static new MD2 Create (string hashName)
+       {
+               object o = CryptoConfig.CreateFromName (hashName);
+               // in case machine.config isn't configured to use any MD2 implementation
+               if (o == null) {
+                       o = new MD2CryptoServiceProvider ();
+               }
+               return (MD2) o;
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD2CryptoServiceProvider.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD2CryptoServiceProvider.cs
new file mode 100644 (file)
index 0000000..e21fdbb
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Mono.Security.Cryptography.MD2CryptoServiceProvider
+//
+// Authors:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+public class MD2CryptoServiceProvider : MD2 {
+
+       private CapiHash hash;
+
+       public MD2CryptoServiceProvider () 
+       {
+               hash = null;
+       }
+
+       ~MD2CryptoServiceProvider () 
+       {
+               Dispose (true);
+       }
+
+       // 2 cases:
+       // a. we were calculing a hash and want to abort
+       // b. we haven't started yet
+       public override void Initialize () 
+       {
+               State = 0;
+               if (hash == null) {
+                       hash = new CapiHash (CryptoAPI.CALG_MD2);
+               }
+       }
+
+       protected override void Dispose (bool disposing) 
+       {
+               if (hash != null) {
+                       hash.Dispose ();
+                       hash = null;
+                       // there's no unmanaged resources (so disposing isn't used)
+               }
+       }
+
+       protected override void HashCore (byte[] rgb, int ibStart, int cbSize) 
+       {
+               if (State == 0)
+                       Initialize ();
+               if (hash == null)
+                       throw new ObjectDisposedException ("MD2CryptoServiceProvider");
+               State = 1;
+               hash.HashCore (rgb, ibStart, cbSize);
+       }
+
+       protected override byte[] HashFinal () 
+       {
+               if (hash == null)
+                       throw new ObjectDisposedException ("MD2CryptoServiceProvider");
+               State = 0;
+               byte[] result = hash.HashFinal ();
+               Dispose (false);
+               return result;
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD4.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD4.cs
new file mode 100644 (file)
index 0000000..06cb43a
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// MD4.cs - Message Digest 4 Abstract class
+//
+// Author:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+public abstract class MD4 : HashAlgorithm {
+
+       protected MD4 () 
+       {
+               // MD4 hash length are 128 bits long
+               HashSizeValue = 128; 
+       }
+
+       public static new MD4 Create () 
+       {
+               // for this to work we must register ourself with CryptoConfig
+               return Create ("MD4");
+       }
+
+       public static new MD4 Create (string hashName) 
+       {
+               object o = CryptoConfig.CreateFromName (hashName);
+               // in case machine.config isn't configured to use any MD4 implementation
+               if (o == null) {
+                       o = new MD4CryptoServiceProvider ();
+               }
+               return (MD4) o;
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD4CryptoServiceProvider.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD4CryptoServiceProvider.cs
new file mode 100644 (file)
index 0000000..4794e14
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Mono.Security.Cryptography.MD4CryptoServiceProvider
+//
+// Authors:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+public class MD4CryptoServiceProvider : MD4 {
+
+       private CapiHash hash;
+
+       public MD4CryptoServiceProvider () 
+       {
+               hash = null;
+       }
+
+       ~MD4CryptoServiceProvider () 
+       {
+               Dispose (true);
+       }
+
+       // 2 cases:
+       // a. we were calculing a hash and want to abort
+       // b. we haven't started yet
+       public override void Initialize () 
+       {
+               State = 0;
+               if (hash == null) {
+                       hash = new CapiHash (CryptoAPI.CALG_MD4);
+               }
+       }
+
+       protected override void Dispose (bool disposing) 
+       {
+               if (hash != null) {
+                       hash.Dispose ();
+                       hash = null;
+                       // there's no unmanaged resources (so disposing isn't used)
+               }
+       }
+
+       protected override void HashCore (byte[] rgb, int ibStart, int cbSize) 
+       {
+               if (State == 0)
+                       Initialize ();
+               if (hash == null)
+                       throw new ObjectDisposedException ("MD4CryptoServiceProvider");
+               State = 1;
+               hash.HashCore (rgb, ibStart, cbSize);
+       }
+
+       protected override byte[] HashFinal () 
+       {
+               if (hash == null)
+                       throw new ObjectDisposedException ("MD4CryptoServiceProvider");
+               State = 0;
+               byte[] result = hash.HashFinal ();
+               Dispose (false);
+               return result;
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD5CryptoServiceProvider.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/MD5CryptoServiceProvider.cs
new file mode 100644 (file)
index 0000000..66b7dce
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Mono.Security.Cryptography.MD5CryptoServiceProvider
+//
+// Authors:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+public class MD5CryptoServiceProvider : MD5 {
+
+       private CapiHash hash;
+
+       public MD5CryptoServiceProvider () 
+       {
+               hash = null;
+       }
+
+       ~MD5CryptoServiceProvider () 
+       {
+               Dispose (true);
+       }
+
+       // 2 cases:
+       // a. we were calculing a hash and want to abort
+       // b. we haven't started yet
+       public override void Initialize () 
+       {
+               State = 0;
+               if (hash == null) {
+                       hash = new CapiHash (CryptoAPI.CALG_MD5);
+               }
+       }
+
+       protected override void Dispose (bool disposing) 
+       {
+               if (hash != null) {
+                       hash.Dispose ();
+                       hash = null;
+                       // there's no unmanaged resources (so disposing isn't used)
+               }
+       }
+
+       protected override void HashCore (byte[] rgb, int ibStart, int cbSize) 
+       {
+               if (State == 0)
+                       Initialize ();
+               if (hash == null)
+                       throw new ObjectDisposedException ("MD5CryptoServiceProvider");
+               State = 1;
+               hash.HashCore (rgb, ibStart, cbSize);
+       }
+
+       protected override byte[] HashFinal () 
+       {
+               if (hash == null)
+                       throw new ObjectDisposedException ("MD5CryptoServiceProvider");
+               State = 0;
+               byte[] result = hash.HashFinal ();
+               Dispose (false);
+               return result;
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/RNGCryptoServiceProvider.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/RNGCryptoServiceProvider.cs
new file mode 100644 (file)
index 0000000..32bcc78
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Mono.Security.Cryptography.RNGCryptoServiceProvider
+//
+// Authors:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Mono.Security.Cryptography {
+       
+public class RNGCryptoServiceProvider : RandomNumberGenerator {
+
+       private CapiRandomNumberGenerator rng;
+       private byte[] seed;
+
+       public RNGCryptoServiceProvider () 
+       {
+               rng = new CapiRandomNumberGenerator ();
+               seed = null;
+       }
+
+       public RNGCryptoServiceProvider (byte[] rgb) 
+       {
+               rng = new CapiRandomNumberGenerator ();
+               seed = rgb;
+       }
+
+       public RNGCryptoServiceProvider (CspParameters cspParams) 
+       {
+               rng = new CapiRandomNumberGenerator (cspParams);
+               seed = null;
+       }
+
+       public RNGCryptoServiceProvider (string str) 
+       {
+               rng = new CapiRandomNumberGenerator ();
+               seed = Encoding.Default.GetBytes (str);
+       }
+
+       ~RNGCryptoServiceProvider () 
+       {
+               // zeroize seed
+               if (seed != null)
+                       Array.Clear (seed, 0, seed.Length);
+               // release unmanaged resources
+               rng.Dispose ();
+       }
+
+       public override void GetBytes (byte[] data) 
+       {
+               if (data == null)
+                       throw new ArgumentNullException ("data");
+
+               // send the seed
+               if (seed != null)
+                       rng.GenRandom (seed);   
+               // note: by doing this seed is modified each time
+
+               rng.GenRandom (data);
+
+               // generate random
+               if (!rng.Result)
+                       throw new CryptographicException (rng.Error);
+       }
+
+       public override void GetNonZeroBytes (byte[] data) 
+       {
+               byte[] random = new byte [data.Length * 2];
+               int i = 0;
+               // one pass should be enough but hey this is random ;-)
+               while (i < data.Length) {
+                       GetBytes (random);
+                       for (int j=0; j < random.Length; j++) {
+                               if (i == data.Length)
+                                       break;
+                               if (random [j] != 0)
+                                       data [i++] = random [j];
+                       }
+               }
+       }
+}
+
+}
diff --git a/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/SHA1CryptoServiceProvider.cs b/mcs/class/Mono.Security.Win32/Mono.Security.Cryptography/SHA1CryptoServiceProvider.cs
new file mode 100644 (file)
index 0000000..e483ccf
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Mono.Security.Cryptography.SHA1CryptoServiceProvider
+//
+// Authors:
+//     Sebastien Pouliot (spouliot@motus.com)
+//
+// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+//
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+public class SHA1CryptoServiceProvider : SHA1 {
+
+       private CapiHash hash;
+
+       public SHA1CryptoServiceProvider ()
+       {
+               hash = null;
+       }
+
+       ~SHA1CryptoServiceProvider () 
+       {
+               Dispose (true);
+       }
+
+       // 2 cases:
+       // a. we were calculing a hash and want to abort
+       // b. we haven't started yet
+       public override void Initialize () 
+       {
+               State = 0;
+               if (hash == null) {
+                       hash = new CapiHash (CryptoAPI.CALG_SHA1);
+               }
+       }
+
+       protected override void Dispose (bool disposing) 
+       {
+               if (hash != null) {
+                       hash.Dispose ();
+                       hash = null;
+                       // there's no unmanaged resources (so disposing isn't used)
+               }
+       }
+
+       protected override void HashCore (byte[] rgb, int ibStart, int cbSize) 
+       {
+               if (State == 0)
+                       Initialize ();
+               if (hash == null)
+                       throw new ObjectDisposedException ("SHA1CryptoServiceProvider");
+               State = 1;
+               hash.HashCore (rgb, ibStart, cbSize);
+       }
+
+       protected override byte[] HashFinal () 
+       {
+               if (hash == null)
+                       throw new ObjectDisposedException ("SHA1CryptoServiceProvider");
+               State = 0;
+               byte[] result = hash.HashFinal ();
+               Dispose (false);
+               return result;
+       }
+}
+
+}