SecureString到Byte [] C#

ini*_*are 8 c# encryption wpf securestring

我怎样才能获得byte[]相当于a SecureString(我从中得到的PasswordBox)?

我的目标是使用a将这些字节写入CryptoStream文件,并且Write该类的方法接受byte[]输入,因此我想将其转换SecureStringbyte[]所以我可以使用a CryptoStream.

编辑:我不想使用,string因为它打败了一个点SecureString

Eri*_*oyd 10

假设你想要使用字节数组并在完成后立即删除它,你应该封装整个操作,以便它自己清理:

public static T Process<T>(this SecureString src, Func<byte[], T> func)
{
    IntPtr bstr = IntPtr.Zero;
    byte[] workArray = null;
    GCHandle handle = GCHandle.Alloc(workArray, GCHandleType.Pinned);
    try
    {
        /*** PLAINTEXT EXPOSURE BEGINS HERE ***/
        bstr = Marshal.SecureStringToBSTR(src);
        unsafe
        {
            byte* bstrBytes = (byte*)bstr;
            workArray = new byte[src.Length * 2];

            for (int i = 0; i < workArray.Length; i++)
                workArray[i] = *bstrBytes++;
        }

        return func(workArray);
    }
    finally
    {
        if (workArray != null)
            for (int i = 0; i < workArray.Length; i++)
                workArray[i] = 0;
        handle.Free();
        if (bstr != IntPtr.Zero)
            Marshal.ZeroFreeBSTR(bstr);
        /*** PLAINTEXT EXPOSURE ENDS HERE ***/
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是用例的外观:

private byte[] GetHash(SecureString password)
{
    using (var h = new SHA256Cng()) // or your hash of choice
    {
        return password.Process(h.ComputeHash);
    }
}
Run Code Online (Sandbox Code Playgroud)

没有麻烦,没有大惊小怪,没有明文留在内存中.

请记住,传递给的字节数组func()包含明文的原始Unicode呈现,这对于大多数加密应用程序来说应该不是问题.

  • Eric - 我认为你的workArray有点问题.你把它归零很好,但是如果垃圾收集器会决定移动它呢?然后你将暴露的数据作为内存中的"垃圾".在将敏感数据放入内部之前,您需要将字节数组固定到内存中 (2认同)

Jef*_*ang 3

我修改了原来的答案来处理unicode

IntPtr unmanagedBytes = Marshal.SecureStringToGlobalAllocUnicode(password);
byte[] bValue = null;
try
{
    byte* byteArray = (byte*)unmanagedBytes.GetPointer();

    // Find the end of the string
    byte* pEnd = byteArray;
    char c='\0';
    do
    {
        byte b1=*pEnd++;
        byte b2=*pEnd++;
        c = '\0';
        c= (char)(b1 << 8);                 
        c += (char)b2;
    }while (c != '\0');

    // Length is effectively the difference here (note we're 2 past end) 
    int length = (int)((pEnd - byteArray) - 2);
    bValue = new byte[length];
    for (int i=0;i<length;++i)
    {
        // Work with data in byte array as necessary, via pointers, here
        bValue[i] = *(byteArray + i);
    }
}
finally
{
    // This will completely remove the data from memory
    Marshal.ZeroFreeGlobalAllocUnicode(unmanagedBytes);
}
Run Code Online (Sandbox Code Playgroud)

  • 与 ANSI C 字符串不同,BSTR 可以包含空字符,因此对空值的扫描无效。只需使用源 SecureString 的 Length 成员(乘以 2 即可获得字节数)。 (2认同)