--- /dev/null
+//
+// 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;
+ }
+ }
+}
+
+}
--- /dev/null
+//
+// 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;
+ }
+}
+
+}
--- /dev/null
+//
+// 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);
+ }
+}
+
+}
--- /dev/null
+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.
+
--- /dev/null
+//
+// 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 ();
+ }
+}
+
+}
--- /dev/null
+//
+// 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;
+ }
+}
+
+}
--- /dev/null
+//
+// 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;
+ }
+}
+
+}
--- /dev/null
+//
+// 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;
+ }
+}
+
+}
--- /dev/null
+//
+// 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;
+ }
+}
+
+}
--- /dev/null
+//
+// 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;
+ }
+}
+
+}
--- /dev/null
+//
+// 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];
+ }
+ }
+ }
+}
+
+}
--- /dev/null
+//
+// 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;
+ }
+}
+
+}