namespace com.hitrust.Security.Cryptography { using com.hitrust.Security; using System; using System.Runtime.InteropServices; using System.Security.Cryptography; public sealed class DataProtectionCryptoServiceProvider : IDisposable { private bool m_Disposed; private byte[] m_OptionalEntropy; public DataProtectionCryptoServiceProvider() : this(null) { } public DataProtectionCryptoServiceProvider(byte[] optionalEntropy) { if (optionalEntropy != null) { this.m_OptionalEntropy = (byte[]) optionalEntropy.Clone(); } this.m_Disposed = false; } public void Dispose() { if (this.m_OptionalEntropy != null) { Array.Clear(this.m_OptionalEntropy, 0, this.m_OptionalEntropy.Length); } this.m_Disposed = true; } ~DataProtectionCryptoServiceProvider() { this.Dispose(); } public byte[] ProtectData(ProtectionType type, byte[] data) { return this.ProtectData(type, data, this.Entropy); } public byte[] ProtectData(ProtectionType type, byte[] data, byte[] entropy) { if (data == null) { throw new ArgumentNullException(); } return this.ProtectData(type, data, 0, data.Length, entropy); } public byte[] ProtectData(ProtectionType type, byte[] data, int offset, int size, byte[] entropy) { byte[] bytes; if (this.m_Disposed) { throw new ObjectDisposedException(base.GetType().FullName); } if (data == null) { throw new ArgumentNullException(); } if (!(((offset >= 0) && ((offset + size) <= data.Length)) && Enum.IsDefined(typeof(ProtectionType), type))) { throw new ArgumentException(); } DataBlob input = new DataBlob(); DataBlob entr = new DataBlob(); DataBlob output = new DataBlob(); try { input.cbData = size; input.pbData = Marshal.AllocHGlobal(size); Marshal.Copy(data, offset, input.pbData, size); if (entropy == null) { entr.cbData = 0; entr.pbData = IntPtr.Zero; } else { entr.cbData = entropy.Length; entr.pbData = Marshal.AllocHGlobal(entr.cbData); Marshal.Copy(entropy, 0, entr.pbData, entr.cbData); } output.cbData = 0; output.pbData = IntPtr.Zero; int flags = 0; if (type == ProtectionType.LocalMachine) { flags |= 4; } if (!Environment.UserInteractive) { flags |= 1; } if ((SspiProvider.CryptProtectData(ref input, "", ref entr, IntPtr.Zero, IntPtr.Zero, flags, ref output) == 0) || (output.pbData == IntPtr.Zero)) { throw new CryptographicException("The data could not be protected."); } byte[] ret = new byte[output.cbData]; Marshal.Copy(output.pbData, ret, 0, output.cbData); bytes = ret; } finally { if (input.pbData != IntPtr.Zero) { Marshal.FreeHGlobal(input.pbData); } if (entr.pbData != IntPtr.Zero) { Marshal.FreeHGlobal(entr.pbData); } if (output.pbData != IntPtr.Zero) { Marshal.FreeHGlobal(output.pbData); } } return bytes; } public byte[] UnprotectData(byte[] data) { return this.UnprotectData(data, this.Entropy); } public byte[] UnprotectData(byte[] data, byte[] entropy) { if (data == null) { throw new ArgumentNullException(); } return this.UnprotectData(data, 0, data.Length, entropy); } public byte[] UnprotectData(byte[] data, int offset, int size, byte[] entropy) { byte[] a; if (this.m_Disposed) { throw new ObjectDisposedException(base.GetType().FullName); } if (data == null) { throw new ArgumentNullException(); } if ((offset < 0) || ((offset + size) > data.Length)) { throw new ArgumentException(); } DataBlob input = new DataBlob(); DataBlob entr = new DataBlob(); DataBlob output = new DataBlob(); try { input.cbData = size; input.pbData = Marshal.AllocHGlobal(size); Marshal.Copy(data, offset, input.pbData, size); if (entropy == null) { entr.cbData = 0; entr.pbData = IntPtr.Zero; } else { entr.cbData = entropy.Length; entr.pbData = Marshal.AllocHGlobal(entr.cbData); Marshal.Copy(entropy, 0, entr.pbData, entr.cbData); } output.cbData = 0; output.pbData = IntPtr.Zero; int flags = 0; if (!Environment.UserInteractive) { flags |= 1; } if ((SspiProvider.CryptUnprotectData(ref input, IntPtr.Zero, ref entr, IntPtr.Zero, IntPtr.Zero, flags, ref output) == 0) || (output.pbData == IntPtr.Zero)) { throw new CryptographicException("The data could not be unprotected."); } byte[] ret = new byte[output.cbData]; Marshal.Copy(output.pbData, ret, 0, output.cbData); a = ret; } finally { if (input.pbData != IntPtr.Zero) { Marshal.FreeHGlobal(input.pbData); } if (entr.pbData != IntPtr.Zero) { Marshal.FreeHGlobal(entr.pbData); } if (output.pbData != IntPtr.Zero) { Marshal.FreeHGlobal(output.pbData); } } return a; } public byte[] Entropy { get { return this.m_OptionalEntropy; } set { this.m_OptionalEntropy = value; } } } }