在SecureString中存储字节数组偶尔会失败

时间:2016-04-01 16:42:36

标签: c# .net security extension-methods securestring

在有人提出&#34之前,为什么要这样做"蔑视我需要的事实。如果没有,那么我只想要一个安全的字节数组,将其视为二进制密码。现在开始吧!

我有以下扩展方法从字节数组中的数据中获取SecureString实例:

public static SecureString FromByteArray(this SecureString secure, byte[] data)
{
    secure.Clear(); // throw exception if IsReadOnly
    char[] chars = new char[data.Length];

    chars = data.Select(c => (char)c).ToArray();
    foreach (char c in chars)
    {
        secure.AppendChar(c);
    }
    return secure;
}

然后在StackOverflow中的某处我发现以下内容将SecureString转储到byte []:

public static byte[] ToInsecureBytes(this SecureString securePassword)
    {
        byte[] bytes = null;

        if (null != securePassword)
        {
            GCHandle? gc = null;
            var handle = IntPtr.Zero;
            var length = securePassword.Length;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                handle = Marshal.SecureStringToGlobalAllocAnsi(securePassword);
                bytes = new byte[length];
                gc = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                for (var i = 0; i < length; i++)
                {
                    bytes[i] = Marshal.ReadByte(handle, i);
                }
            }
            finally
            {
                if (handle != IntPtr.Zero)
                {
                    Marshal.ZeroFreeGlobalAllocAnsi(handle);
                }

                if (null != gc &&
                    gc.HasValue)
                {
                    gc.Value.Free();
                }
            }
        }

        return bytes;
    }

请注意,代码与字符串编码无关,因为我们将数据视为仅仅是二进制文件,但使用的是SecureString功能。

然后我在LinqPad中有这个测试代码来证明这个概念:

byte[] byteData = Generate256BitsOfRandomEntropy();  // byte[32]
BitConverter.ToString(byteData).Dump();

SecureString pwd4 = pass.FromByteArray(byteData);
byte[] byteOut = pwd4.ToInsecureBytes();
BitConverter.ToString(byteOut).Dump();
Console.WriteLine("Conversion successful: {0}", byteData.SequenceEqual(byteOut));

但是当作为往返转换运行时,我注意到它们不一样,序列中始终存在不匹配,并且它始终是十六进制代码0x3F的字符,它在byteOut数组的随机位置显得神秘。

07-F7-90-67-A7-46-1E-F9-CE-44-91-46-44-9D-B9-81-75-7B-27-43-34-C3-F9-38-AC-E7-F9-E6-F1-7F-29-84
07-F7-90-67-A7-46-1E-F9-CE-44-3F-46-44-9D-B9-81-75-7B-27-43-34-C3-F9-38-AC-E7-F9-E6-F1-7F-29-3F
Conversion successful: False

0 个答案:

没有答案