Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- var secureString = new SecureString();
- secureString.AppendChar('a');
- secureString.AppendChar('q');
- secureString.AppendChar('1');
- using (var command = new SqlCommand("select case when @secureParam = 'aq1' then 'yes' else 'no' end", connection))
- {
- object returnValue;
- using (command.Parameters.AddSecure("secureParam", secureString))
- {
- // At this point no copies exist in the clear
- returnValue = (string)command.ExecuteScalar();
- // Now one pinned String object exists in the clear (referenced at the internal property command.Parameters[0].CoercedValue)
- }
- // At this point no copies exist in the clear
- }
- public static class SecureSqlParameterExtensions
- {
- [DllImport("kernel32.dll", EntryPoint = "CopyMemory")]
- private static extern void CopyMemory(IntPtr dest, IntPtr src, IntPtr count);
- [DllImport("kernel32.dll", EntryPoint = "RtlZeroMemory")]
- private static extern void ZeroMemory(IntPtr ptr, IntPtr count);
- /// <summary>
- /// You must dispose the return value as soon as SqlCommand.Execute* is called.
- /// </summary>
- public static IDisposable AddSecure(this SqlParameterCollection collection, string name, SecureString secureString)
- {
- var value = new SecureStringParameterValue(secureString);
- collection.Add(name, SqlDbType.NVarChar).Value = value;
- return value;
- }
- private sealed class SecureStringParameterValue : IConvertible, IDisposable
- {
- private readonly SecureString secureString;
- private int length;
- private string insecureManagedCopy;
- private GCHandle insecureManagedCopyGcHandle;
- public SecureStringParameterValue(SecureString secureString)
- {
- this.secureString = secureString;
- }
- #region IConvertible
- public TypeCode GetTypeCode()
- {
- return TypeCode.String;
- }
- public string ToString(IFormatProvider provider)
- {
- if (insecureManagedCopy != null) return insecureManagedCopy;
- if (secureString == null || secureString.Length == 0) return string.Empty;
- // We waited till the last possible minute.
- // Here's the plan:
- // 1. Create a new managed string initialized to zero
- // 2. Pin the managed string so the GC leaves it alone
- // 3. Copy the contents of the SecureString into the managed string
- // 4. Use the string as a SqlParameter
- // 5. Zero the managed string after Execute* is called and free the GC handle
- length = secureString.Length;
- insecureManagedCopy = new string('