Giả sử bạn muốn sử dụng các mảng byte và được thoát khỏi nó càng sớm càng bạn đã hoàn tất, bạn nên đóng gói toàn bộ hoạt động để nó làm sạch lên sau khi chính nó:
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 ***/
}
}
Và dưới đây là cách một trường hợp sử dụng trông:
private byte[] GetHash(SecureString password)
{
using (var h = new SHA256Cng()) // or your hash of choice
{
return password.Process(h.ComputeHash);
}
}
Không ồn ào, không ồn ào, không có chữ thô nào nổi trong bộ nhớ.
Hãy nhớ rằng mảng byte được chuyển đến func()
chứa hiển thị Unicode thô của bản rõ, không phải là vấn đề đối với hầu hết các ứng dụng mã hóa.
Nguồn
2014-08-07 19:27:56
Không giống như các chuỗi ANSI C, BSTR có thể chứa các ký tự null, do đó việc quét tìm các giá trị rỗng của bạn không hợp lệ. Chỉ cần sử dụng thành viên Length của SecureString nguồn (nhân với 2 để có được số byte). –