namespace com.hitrust.Security.Cryptography { using com.hitrust.Security; using System; using System.Runtime.InteropServices; using System.Security.Cryptography; public sealed class RC4CryptoServiceProvider : RC4 { private bool m_Disposed; private ARCFourManaged m_Managed; private int m_MaxLen; private int m_MinLen; private int m_Provider = 0; public RC4CryptoServiceProvider() { if ((SspiProvider.CryptAcquireContext(ref this.m_Provider, IntPtr.Zero, null, 1, 0) == 0) && (Marshal.GetLastWin32Error() == -2146893802)) { SspiProvider.CryptAcquireContext(ref this.m_Provider, IntPtr.Zero, null, 1, 8); } if (this.m_Provider != 0) { int dwFlags = 1; bool found = false; IntPtr provEnum = Marshal.AllocHGlobal(100); do { int dwSize = 100; if (SspiProvider.CryptGetProvParam(this.m_Provider, 0x16, provEnum, ref dwSize, dwFlags) == 0) { break; } dwFlags = 0; com.hitrust.Security.PROV_ENUMALGS_EX eax = (com.hitrust.Security.PROV_ENUMALGS_EX) Marshal.PtrToStructure(provEnum, typeof(com.hitrust.Security.PROV_ENUMALGS_EX)); if (eax.aiAlgid == 0x6801) { found = true; this.m_MinLen = eax.dwMinLen; this.m_MaxLen = eax.dwMaxLen; } } while (!found); Marshal.FreeHGlobal(provEnum); if (!found) { SspiProvider.CryptReleaseContext(this.m_Provider, 0); this.m_Provider = 0; } } this.m_Managed = new ARCFourManaged(); } private bool CanUseUnmanaged(int keySize) { return (((this.m_Provider != 0) && (keySize >= this.m_MinLen)) && (keySize <= this.m_MaxLen)); } public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV) { if (this.m_Disposed) { throw new ObjectDisposedException(base.GetType().FullName); } if (rgbKey == null) { throw new ArgumentNullException("Key is a null reference."); } if ((rgbKey.Length == 0) || (rgbKey.Length > 0x100)) { throw new CryptographicException("Invalid Key."); } if ((rgbIV != null) && (rgbIV.Length > 1)) { throw new CryptographicException("Invalid Initialization Vector."); } try { if (this.CanUseUnmanaged(rgbKey.Length * 8)) { return new RC4UnmanagedTransform(rgbKey); } } catch { } return this.m_Managed.CreateDecryptor(rgbKey, rgbIV); } public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV) { return this.CreateDecryptor(rgbKey, rgbIV); } private void CurrentDispose() { if (!this.m_Disposed) { this.m_Disposed = true; if (this.m_Managed != null) { this.m_Managed.Clear(); this.m_Managed = null; } if (this.m_Provider != 0) { SspiProvider.CryptReleaseContext(this.m_Provider, 0); this.m_Provider = 0; } try { GC.SuppressFinalize(this); } catch { } } } ~RC4CryptoServiceProvider() { this.CurrentDispose(); } public override void GenerateIV() { this.m_Managed.GenerateIV(); } public override void GenerateKey() { this.m_Managed.GenerateKey(); } public override int BlockSize { get { return this.m_Managed.BlockSize; } set { this.m_Managed.BlockSize = value; } } public override int FeedbackSize { get { return this.m_Managed.FeedbackSize; } set { this.m_Managed.FeedbackSize = value; } } public override byte[] IV { get { return this.m_Managed.IV; } set { this.m_Managed.IV = value; } } public override byte[] Key { get { return this.m_Managed.Key; } set { this.m_Managed.Key = value; } } public override int KeySize { get { return this.m_Managed.KeySize; } set { this.m_Managed.KeySize = value; } } public override KeySizes[] LegalBlockSizes { get { return this.m_Managed.LegalBlockSizes; } } public override KeySizes[] LegalKeySizes { get { return this.m_Managed.LegalKeySizes; } } public override CipherMode Mode { get { return this.m_Managed.Mode; } set { this.m_Managed.Mode = value; } } public override PaddingMode Padding { get { return this.m_Managed.Padding; } set { this.m_Managed.Padding = value; } } } }