首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SecureString to Byte[] C#

SecureString to Byte[] C#
EN

Stack Overflow用户
提问于 2013-08-22 23:49:09
回答 5查看 9.5K关注 0票数 11

我如何获得与byte[]等价的SecureString (从PasswordBox获得)?

我的目标是使用CryptoStream将这些字节写入文件,该类的Write方法接受byte[]输入,因此我希望将SecureString转换为byte[],以便与CryptoStream一起使用。

编辑:--我不想使用string,因为它违背了拥有SecureString的意义

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-01-07 05:24:53

我从原始答案修改来处理unicode

代码语言:javascript
复制
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);
}
票数 3
EN

Stack Overflow用户

发布于 2014-08-07 19:27:56

假设您想要使用字节数组并在完成后立即将其清除,那么您应该封装整个操作,以便它在其自身之后清理:

代码语言:javascript
复制
public static T Process<T>(this SecureString src, Func<byte[], T> func)
{
    IntPtr bstr = IntPtr.Zero;
    byte[] workArray = null;
    GCHandle? handle = null; // Hats off to Tobias Bauer
    try
    {
        /*** PLAINTEXT EXPOSURE BEGINS HERE ***/
        bstr = Marshal.SecureStringToBSTR(src);
        unsafe
        {
            byte* bstrBytes = (byte*)bstr;
            workArray = new byte[src.Length * 2];
            handle = GCHandle.Alloc(workArray, GCHandleType.Pinned); // Hats off to Tobias Bauer
            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 ***/
    }
}

下面是用例的外观:

代码语言:javascript
复制
private byte[] GetHash(SecureString password)
{
    using (var h = new SHA256Cng()) // or your hash of choice
    {
        return password.Process(h.ComputeHash);
    }
}

没有音乐,没有大惊小怪,没有明文漂浮在记忆中。

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

票数 13
EN

Stack Overflow用户

发布于 2020-09-28 14:40:49

由于我没有足够的声誉点来评论埃里克的回答,所以我必须发表这篇文章。

在我看来,埃里克的代码有问题,因为GCHandle.Alloc(workArray, ...)做得不对。它不应该插入null值的workArray,而应该是实际的数组,它将在更低的位置创建几行。

此外,handle.Free()可以抛出一个InvalidOperationException,因此我建议将它放在Marshal.ZeroFreeBSTR(...)之后,至少使二进制字符串bstr指向零。

经修订的守则如下:

代码语言:javascript
复制
public static T Process<T>(this SecureString src, Func<byte[], T> func)
{
    IntPtr bstr = IntPtr.Zero;
    byte[] workArray = null;
    GCHandle? handle = null; // Change no. 1
    try
    {
        /*** PLAINTEXT EXPOSURE BEGINS HERE ***/
        bstr = Marshal.SecureStringToBSTR(src);
        unsafe
        {
            byte* bstrBytes = (byte*)bstr;
            workArray = new byte[src.Length * 2];
            handle = GCHandle.Alloc(workArray, GCHandleType.Pinned); // Change no. 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;
        
        if (bstr != IntPtr.Zero)
            Marshal.ZeroFreeBSTR(bstr);

        handle?.Free(); // Change no. 3 (Edit: no try-catch but after Marshal.ZeroFreeBSTR)

        /*** PLAINTEXT EXPOSURE ENDS HERE ***/
    }
}

这些修改确保将正确的byte数组固定在内存中(更改号1和2)。此外,它们避免将未加密的二进制字符串仍然加载在内存中,以防handle?.Free()抛出异常(更改第3号)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18392538

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档