Reading single chars from a .NET SecureString in C#?

本小妞迷上赌 提交于 2020-01-02 11:26:40

问题


WPF's PasswordBox returns a SecureString, which hides the password from snoopers.

The problem is that you eventually have to get the value of the password, and the suggestions I've found on the net all involve copying the value into a string, which gets you back to the problem of snoopers.

IntPtr bstr = Marshal.SecureStringToBSTR(secureString);
string password = Marshal.PtrToStringBSTR(bstr);
Marshal.FreeBSTR(bstr);

But if you really think about it, you don't really need the value, as a string. I mean, what do you do with a password? You hash it and then compare the result to a saved hash, and see if they are the same.

In other words, you don't need to convert the SecureString into a string, you just need to be able to iterate over the individual characters in the string.

But how?

How do I loop over the individual characters in a BSTR, in C#, without converting it to a managed string?

EDITING: the solution, in case the link disappears:

The Marshall class provides methods that can extract individual bytes or ints from an IntPtr, at given offsets. A BSTR object contains an array of 16-bit characters, terminated by two null bytes. So you can access them by looping:

byte b = 1;
int i = 0;
while ((char)b != '\0')
{
    b = Marshal.ReadByte(bstr, i);
    // ...
    i += 2;
}

(I don't care for that flow control. I'd have used a do...while, rather than prepopulate b with a dummy value, or I'd have used a for(;;) loop, with internal breaks, or I'd have looped on the length, which I explain how to get, below.)

Also, I'd probably use:

short b = Marshal.ReadInt16(bstr, i);

Reading the entire unicode chars, instead of just the low bytes of each.

You can get the length of the BSTR with:

int len = Marshal.ReadInt32(bstr, -4);

This is the number of bytes, not including the nulls, not the number of chars.

Also - use:

Marshal.ZeroFreeBSTR(bstr);

回答1:


http://weblogs.asp.net/pglavich/archive/2005/08/15/422525.aspx

This link shows how to use Marshal.SecureStringToBSTR(secretString) and assign it to a pointer and update the pointer to loop over the characters.




回答2:


This worked for me:

    static char GetChar(SecureString value, int idx)
    {
        IntPtr bstr = Marshal.SecureStringToBSTR(value);
        try
        {
            // Index in 2-byte (char) chunks
            //TODO: Some range validation might be good.
            return (char)Marshal.ReadByte(bstr, idx * 2);
        }
        finally
        {
            Marshal.FreeBSTR(bstr);
        }
    }



回答3:


Try something like this I converted the VB code sample that lc had in the link to C# for you hope this helps to get you started

Char[] input = "Super Secret String".ToCharArray();
SecureString secret = new SecureString();

for (int idx = 0; idx <= input.Length - 1; idx++) {
    secret.AppendChar(FileSystem.input(idx));
}
SecurePassword.MakeReadOnly();

IntPtr pBStr = Marshal.SecureStringToBSTR(secret);

string output = Marshal.PtrToStringBSTR(pBStr);
Marshal.FreeBSTR(pBStr);

SHA512 sha = new SHA512Managed();
byte[] result = sha.ComputeHash(Encoding.UTF8.GetBytes(output));


来源:https://stackoverflow.com/questions/11458894/reading-single-chars-from-a-net-securestring-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!