哈希在.NET中的SecureString的 [英] Hashing a SecureString in .NET

查看:210
本文介绍了哈希在.NET中的SecureString的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在.NET中,我们有SecureString类,这固然很好,直到你来试试,并用它,以(例如)哈希字符串,你需要的明文。我了个去,在这里写这将散列SecureString的一个函数,给定一个哈希函数,它接受一个字节数组并输出一个字节数组。

 私有静态的byte [] HashSecureString(SecureString的SS,Func键<字节[],byte []的>哈希)
{
    //将SecureString的转换为BSTR
    IntPtr的BSTR = Marshal.SecureStringToBSTR(SS);

    // BSTR包含字符串的在一个字节长度
    //的Int32之前BSTR指针存储在4个字节
    INT长度= Marshal.ReadInt32(BSTR,-4);

    //分配一个字节数组的字符串复制到
    字节[]字节=新字节[长度];

    //复制BSTR的字节数组
    Marshal.Copy(BSTR,字节,0,长度);

    //立即销毁BSTR,因为我们不需要它了
    Marshal.ZeroFreeBSTR(BSTR);

    //散列字节数组
    byte []的散列=散列(字节);

    //摧毁字节数组中的明文副本
    对(INT I = 0; I&其中;长度;我++){字节[I] = 0; }

    //返回哈希
    返回哈希;
}
 

相信这将正确散列字符串,并且将正确擦洗明文的任何副本从存储器由时间函数返回时,假定所提供的散列函数性能良好,并且不会使所述输入,它的任何副本不擦洗自己。有我在这里错过了什么?

解决方案
  

有我在这里错过了什么?

是的,你有一个相当基本的一个。你不能擦洗阵时留下的垃圾收集器压缩堆后面的副本。 Marshal.SecureStringToBSTR(SS)是可以的,因为一个BSTR被分配在非托管内存中,因此将有一个可靠的指针不会改变。换言之,没有任何问题擦洗,一个。

字节[]字节但是数组包含字符串的副本,而的分配在GC堆上。你让这可能导致垃圾收集与哈希[]数组。很容易避免的。当然,你无法控制你的过程中其他线程分配内存和诱导的集合。或者在这方面背景GC前已经在进行中,当你的$ C $下开始运行。

SecureString的的一点是要的永远的都字符串的垃圾明文副本收集的内存。它复制到一个管理的阵列违反了保证。如果你想使这个code安全,那么你将不得不写一个散列()方法,它的IntPtr的只有读通过该指针。

要注意的是,如果你的散列需要匹配计算在另一台机器哈希那么你就不能忽略的机器将使用转串入字节编码。

In .NET, we have the SecureString class, which is all very well until you come to try and use it, as to (for example) hash the string, you need the plaintext. I've had a go here at writing a function that will hash a SecureString, given a hash function that takes a byte array and outputs a byte array.

private static byte[] HashSecureString(SecureString ss, Func<byte[], byte[]> hash)
{
    // Convert the SecureString to a BSTR
    IntPtr bstr = Marshal.SecureStringToBSTR(ss);

    // BSTR contains the length of the string in bytes in an
    // Int32 stored in the 4 bytes prior to the BSTR pointer
    int length = Marshal.ReadInt32(bstr, -4);

    // Allocate a byte array to copy the string into
    byte[] bytes = new byte[length];

    // Copy the BSTR to the byte array
    Marshal.Copy(bstr, bytes, 0, length);

    // Immediately destroy the BSTR as we don't need it any more
    Marshal.ZeroFreeBSTR(bstr);

    // Hash the byte array
    byte[] hashed = hash(bytes);

    // Destroy the plaintext copy in the byte array
    for (int i = 0; i < length; i++) { bytes[i] = 0; }

    // Return the hash
    return hashed;
}

I believe this will correctly hash the string, and will correctly scrub any copies of the plaintext from memory by the time the function returns, assuming the provided hash function is well behaved and doesn't make any copies of the input that it doesn't scrub itself. Have I missed anything here?

解决方案

Have I missed anything here?

Yes, you have, a rather fundamental one at that. You cannot scrub the copy of the array left behind when the garbage collector compacts the heap. Marshal.SecureStringToBSTR(ss) is okay because a BSTR is allocated in unmanaged memory so will have a reliable pointer that won't change. In other words, no problem scrubbing that one.

Your byte[] bytes array however contains the copy of the string and is allocated on the GC heap. You make it likely to induce a garbage collection with the hashed[] array. Easily avoided but of course you have little control over other threads in your process allocating memory and inducing a collection. Or for that matter a background GC that was already in progress when your code started running.

The point of SecureString is to never have a cleartext copy of the string in garbage collected memory. Copying it into a managed array violated that guarantee. If you want to make this code secure then you are going to have to write a hash() method that takes the IntPtr and only reads through that pointer.

Beware that if your hash needs to match a hash computed on another machine then you cannot ignore the Encoding that machine would use to turn the string into bytes.

这篇关于哈希在.NET中的SecureString的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆