wpf SecureString 到 Byte[] C#

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18392538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:28:50  来源:igfitidea点击:

SecureString to Byte[] C#

c#wpfencryptionsecurestring

提问by inixsoftware

How would I get a byte[]equivalent of a SecureString(which I get from a PasswordBox)?

我将如何获得byte[]相当于 a SecureString(我从 a 获得的PasswordBox)?

My objective is to write these bytes using a CryptoStreamto a file, and the Writemethod of that class takes a byte[]input, so I want to convert the SecureStringto the byte[]so I can use in with a CryptoStream.

我的目标是使用 a 将这些字节写入CryptoStream文件,并且Write该类的方法接受一个byte[]输入,所以我想将 the 转换SecureString为 thebyte[]以便我可以在CryptoStream.

EDIT:I don't want to use stringas it defeats the point of having a SecureString

编辑:我不想使用,string因为它破坏了拥有一个SecureString

采纳答案by Jeff Pang

I modified from the original answerto handle unicode

我修改了原始答案以处理 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='
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 ***/
    }
}
'; do { byte b1=*pEnd++; byte b2=*pEnd++; c = '
private byte[] GetHash(SecureString password)
{
    using (var h = new SHA256Cng()) // or your hash of choice
    {
        return password.Process(h.ComputeHash);
    }
}
'; c= (char)(b1 << 8); c += (char)b2; }while (c != '
static string SecureStringToString( SecureString value )
{
  string s ;
  IntPtr p = Marshal.SecureStringToBSTR( value );
  try
  {
    s = Marshal.PtrToStringBSTR( p ) ;
  }
  finally
  {
    Marshal.FreeBSTR( p ) ;
  }
  return s ;
}
'); // 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); }

回答by Eric Lloyd

Assuming you want to use the byte array and get rid of it as soon as you're done, you should encapsulate the entire operation so that it cleans up after itself:

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

##代码##

And here's how a use case looks:

这是用例的外观:

##代码##

No muss, no fuss, no plaintext left floating in memory.

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

Keep in mind that the byte array passed to func()contains the raw Unicode rendering of the plaintext, which shouldn't be an issue for most cryptographic applications.

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

回答by Nicholas Carey

Per this, http://www.microsoft.com/indonesia/msdn/credmgmt.aspx, you can marshal it into a stock C# string and then convert that into an array of bytes:

根据这一点,http://www.microsoft.com/indonesia/msdn/credmgmt.aspx,您可以将其编组为股票 C# 字符串,然后将其转换为字节数组:

##代码##

or per this answer, How to convert SecureString to System.String?, you can use Marshal.ReadByteand Marshal.ReadInt16on the IntPtrto get what you need.

或根据此答案,如何将 SecureString 转换为 System.String?,您可以使用Marshal.ReadByte,并Marshal.ReadInt16IntPtr得到你所需要的。