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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|