在有人提出&#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