2
\$\begingroup\$

In .NET, the SecureString type exists to prevent leaking secrets in memory. I want to create a hash from the contents of a SecureString, without putting the contents in memory in a place where I can't delete them. I have come up with the following solution, where I pinvoke the winapi crypto functions to calculate a hash over a BSTR. Does this approach make any sense? Doesn't this put the secret somewhere in memory where I can't delete it?

[DllImport("advapi32.dll", SetLastError = true)]
static extern bool Crypt...(...);

static byte[] CreateHashForSecureString(SecureString ss)
{
    IntPtr hProv = IntPtr.Zero;
    CryptAcquireContext(ref hProv, null, null, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);

    IntPtr hHash = IntPtr.Zero;
    CryptCreateHash(hProv, CALG_SHA1, IntPtr.Zero, 0, ref hHash);

    var bstr = Marshal.SecureStringToBSTR(ss);
    var len = (uint)Marshal.ReadInt32(bstr, -4);
    CryptHashData(hHash, bstr, len, 0);
    Marshal.ZeroFreeBSTR(bstr);

    byte[] pbData = new byte[20];
    uint length = (uint)pbData.Length;
    CryptGetHashParam(hHash, HP_HASHVAL, pbData, ref length, 0);

    CryptDestroyHash(hHash);
    CryptReleaseContext(hProv, 0);

    return pbData;
}

I am aware that error handling is missing. I am also aware that using SecureString is often more hasle than it's worth. I am particularly looking for whether this is the right approach to this problem.

\$\endgroup\$
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.