Welcome to mirror list, hosted at ThFree Co, Russian Federation.

SecureStringHasher.cs « Core « Xml « System « System.Xml « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 95684b22d5b24b0c3eeef264a2ecdb6a3ed9fd9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//------------------------------------------------------------------------------
// <copyright file="SecureStringHasher.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Security;
#if !SILVERLIGHT
using System.Security.Permissions;
#endif

namespace System.Xml {

    // SecureStringHasher is a hash code provider for strings. The hash codes calculation starts with a seed (hasCodeRandomizer) which is usually
    // different for each instance of SecureStringHasher. Since the hash code depend on the seed, the chance of hashtable DoS attack in case when 
    // someone passes in lots of strings that hash to the same hash code is greatly reduced.
    // The SecureStringHasher implements IEqualityComparer for strings and therefore can be used in generic IDictionary.
    internal class SecureStringHasher : IEqualityComparer<String> {
        [SecurityCritical]
        delegate int HashCodeOfStringDelegate(string s, int sLen, long additionalEntropy);
        
        // Value is guaranteed to be null by the spec.
        // No explicit assignment because it will require adding SecurityCritical on .cctor
        // which could hurt the performance
        [SecurityCritical]
        static HashCodeOfStringDelegate hashCodeDelegate;

        int hashCodeRandomizer;

        public SecureStringHasher() {
            this.hashCodeRandomizer = Environment.TickCount;
        }

#if false // This is here only for debugging of hashing issues
        public SecureStringHasher( int hashCodeRandomizer ) {
            this.hashCodeRandomizer = hashCodeRandomizer;
        }
#endif

        public bool Equals( String x, String y ) {
            return String.Equals( x, y, StringComparison.Ordinal );
        }

        [SecuritySafeCritical]
        public int GetHashCode( String key ) {
            if (hashCodeDelegate == null) {
                hashCodeDelegate = GetHashCodeDelegate();
            }
            return hashCodeDelegate(key, key.Length, hashCodeRandomizer);
        }
        
        [SecurityCritical]
        private static int GetHashCodeOfString( string key, int sLen, long additionalEntropy ) {
            int hashCode = unchecked((int)additionalEntropy);
            // use key.Length to eliminate the rangecheck
            for ( int i = 0; i < key.Length; i++ ) {
                hashCode += ( hashCode << 7 ) ^ key[i];
            }
            // mix it a bit more
            hashCode -= hashCode >> 17; 
            hashCode -= hashCode >> 11; 
            hashCode -= hashCode >> 5;
            return hashCode;
        }
        
        [SecuritySafeCritical]
#if !SILVERLIGHT
        [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)]
#endif
        private static HashCodeOfStringDelegate GetHashCodeDelegate() {
            // If we find the Marvin hash method, we use that
            // Otherwise, we use the old string hashing function.
 
            MethodInfo getHashCodeMethodInfo = typeof(String).GetMethod("InternalMarvin32HashString", BindingFlags.NonPublic | BindingFlags.Static);
            if (getHashCodeMethodInfo != null) {
                return (HashCodeOfStringDelegate)Delegate.CreateDelegate(typeof(HashCodeOfStringDelegate), getHashCodeMethodInfo);
            }
     
            // This will fall through and return a delegate to the old hash function
            Debug.Assert(false, "Randomized hashing is not supported.");

            return new HashCodeOfStringDelegate(GetHashCodeOfString);
        }
    }
}