Hashing a SecureString in .NET

前端 未结 4 1042
一个人的身影
一个人的身影 2020-12-01 05:27

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

4条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-01 06:05

    As a complement to Hans’ answer here’s a suggestion how to implement the hasher. Hans suggests passing the pointer to the unmanaged string to the hash function but that means that client code (= the hash function) needs to deal with unmanaged memory. That’s not ideal.

    On the other hand, you can replace the callback by an instance of the following interface:

    interface Hasher {
        void Reinitialize();
        void AddByte(byte b);
        byte[] Result { get; }
    }
    

    That way the hasher (although it becomes slightly more complex) can be implemented wholly in managed land without leaking secure information. Your HashSecureString would then look as follows:

    private static byte[] HashSecureString(SecureString ss, Hasher hasher) {
        IntPtr bstr = Marshal.SecureStringToBSTR(ss);
        try {
            int length = Marshal.ReadInt32(bstr, -4);
    
            hasher.Reinitialize();
    
            for (int i = 0; i < length; i++)
                hasher.AddByte(Marshal.ReadByte(bstr, i));
    
            return hasher.Result;
        }
        finally {
            Marshal.ZeroFreeBSTR(bstr);
        }
    }
    

    Note the finally block to make sure that the unmanaged memory is zeroed, no matter what shenanigans the hasher instance does.

    Here’s a simple (and not very useful) Hasher implementation to illustrate the interface:

    sealed class SingleByteXor : Hasher {
        private readonly byte[] data = new byte[1];
    
        public void Reinitialize() {
            data[0] = 0;
        }
    
        public void AddByte(byte b) {
            data[0] ^= b;
        }
    
        public byte[] Result {
            get { return data; }
        }
    }
    

提交回复
热议问题