Esempio n. 1
0
        public TlshHash GetHash(bool force)
        {
            if (!IsValid(force))
            {
                throw new InvalidOperationException("TLSH not valid. Either not enough data or data has too little variance");
            }

            uint q1, q2, q3;

            uint[] quartiles = FindQuartiles();
            q1 = quartiles[0];
            q2 = quartiles[1];
            q3 = quartiles[2];

            var tmp_code = new int[codeSize];

            for (int i = 0; i < codeSize; i++)
            {
                int h = 0;
                for (int j = 0; j < 4; j++)
                {
                    var k = accumulatorBuckets[4 * i + j];
                    if (q3 < k)
                    {
                        h += 3 << (j * 2);
                    }
                    else if (q2 < k)
                    {
                        h += 2 << (j * 2);
                    }
                    else if (q1 < k)
                    {
                        h += 1 << (j * 2);
                    }
                }
                tmp_code[i] = h;
            }

            int lvalue  = TlshUtilities.LengthCapture(dataLength);
            int q1ratio = (int)((q1 * 100.0f) / q3) & 0xF;
            int q2ratio = (int)((q2 * 100.0f) / q3) & 0xF;

            if (checksumLength == 1)
            {
                return(new TlshHash(new int[] { checksum }, lvalue, q1ratio, q2ratio, tmp_code));
            }
            else
            {
                var checksumArrayCopy = new int[checksumArray.Length];
                Array.Copy(checksumArray, checksumArrayCopy, checksumArray.Length);
                return(new TlshHash(checksumArrayCopy, lvalue, q1ratio, q2ratio, tmp_code));
            }
        }
Esempio n. 2
0
        public void LoadFromString(string input)
        {
            var buffer = new byte[1024];

            using (var s = TlshUtilities.GenerateStreamFromString(input))
            {
                var bytesRead = s.Read(buffer, 0, buffer.Length);
                while (bytesRead > 0)
                {
                    Update(buffer, 0, bytesRead);
                    bytesRead = s.Read(buffer, 0, buffer.Length);
                }
            }
        }
Esempio n. 3
0
        public async Task LoadFromStringAsync(string input)
        {
            var buffer = new byte[1024];

            using (var s = TlshUtilities.GenerateStreamFromString(input))
            {
                var bytesRead = await s.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);

                while (bytesRead > 0)
                {
                    Update(buffer, 0, bytesRead);
                    bytesRead = await s.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
                }
            }
        }
Esempio n. 4
0
        private readonly int[] codes;    // 32/64 bytes

        public static TlshHash FromTlshStr(string tlshStr)
        {
            int[] checksum = null;
            int[] tmp_code = null;
            foreach (BucketSize bucketSize in Enum.GetValues(typeof(BucketSize)))
            {
                foreach (ChecksumSize checksumOption in Enum.GetValues(typeof(ChecksumSize)))
                {
                    if (tlshStr.Length == HashStringLength(bucketSize, checksumOption))
                    {
                        checksum = new int[(int)checksumOption];
                        tmp_code = new int[(int)bucketSize / 4];
                    }
                }
            }
            if (checksum == null)
            {
                throw new ArgumentException("Invalid hash string, length does not match any known encoding");
            }

            var offset = 0;

            for (int k = 0; k < checksum.Length; k++)
            {
                checksum[k] = TlshUtilities.FromHexSwapped(tlshStr, offset);
                offset     += 2;
            }

            var Lvalue = TlshUtilities.FromHexSwapped(tlshStr, offset);

            offset += 2;

            var qRatios = TlshUtilities.FromHex(tlshStr, offset);

            offset += 2;

            for (int i = 0; i < tmp_code.Length; i++)
            {
                // un-reverse the code during encoding
                tmp_code[tmp_code.Length - i - 1] = TlshUtilities.FromHex(tlshStr, offset);
                offset += 2;
            }

            return(new TlshHash(checksum, Lvalue, qRatios >> 4, qRatios & 0xF, tmp_code));
        }
Esempio n. 5
0
        public string GetEncoded()
        {
            // The C++ code reverses the order of some of the fields before
            // converting to hex, so copy that behaviour.
            var sb = new StringBuilder(HashStringLength());

            for (int k = 0; k < checksum.Length; k++)
            {
                TlshUtilities.ToHexSwapped(checksum[k], sb);
            }
            TlshUtilities.ToHexSwapped(Lvalue, sb);
            TlshUtilities.ToHex(Q1ratio << 4 | Q2ratio, sb);
            for (int i = 0; i < codes.Length; i++)
            {
                // reverse the code during encoding
                TlshUtilities.ToHex(codes[codes.Length - 1 - i], sb);
            }

            return(sb.ToString());
        }
Esempio n. 6
0
        public void Update(byte[] data, int offset, int byteArrDataLength)
        {
            const int RNG_SIZE = CSlidingWindowSize;

            // Indexes into the sliding window. They cycle like
            // 0 4 3 2 1
            // 1 0 4 3 2
            // 2 1 0 4 3
            // 3 2 1 0 4
            // 4 3 2 1 0
            // 0 4 3 2 1
            // and so on
            int j   = dataLength % RNG_SIZE;
            int j_1 = (j - 1 + RNG_SIZE) % RNG_SIZE;
            int j_2 = (j - 2 + RNG_SIZE) % RNG_SIZE;
            int j_3 = (j - 3 + RNG_SIZE) % RNG_SIZE;
            int j_4 = (j - 4 + RNG_SIZE) % RNG_SIZE;

            int fedLength = dataLength;

            for (int i = offset; i < offset + byteArrDataLength; i++, fedLength++)
            {
                slideWindow[j] = data[i] & 0xFF;

                if (fedLength >= 4)
                {
                    // only calculate when input >= 5 bytes

                    checksum = TlshUtilities.PearsonHash(0, slideWindow[j], slideWindow[j_1], checksum);
                    if (checksumLength > 1)
                    {
                        checksumArray[0] = checksum;
                        for (int k = 1; k < checksumLength; k++)
                        {
                            // use calculated 1 byte checksums to expand the total checksum to 3 bytes
                            checksumArray[k] = TlshUtilities.PearsonHash(checksumArray[k - 1], slideWindow[j],
                                                                         slideWindow[j_1], checksumArray[k]);
                        }
                    }

                    int r;
                    r = TlshUtilities.PearsonHash(2, slideWindow[j], slideWindow[j_1], slideWindow[j_2]);
                    accumulatorBuckets[r]++;
                    r = TlshUtilities.PearsonHash(3, slideWindow[j], slideWindow[j_1], slideWindow[j_3]);
                    accumulatorBuckets[r]++;
                    r = TlshUtilities.PearsonHash(5, slideWindow[j], slideWindow[j_2], slideWindow[j_3]);
                    accumulatorBuckets[r]++;
                    r = TlshUtilities.PearsonHash(7, slideWindow[j], slideWindow[j_2], slideWindow[j_4]);
                    accumulatorBuckets[r]++;
                    r = TlshUtilities.PearsonHash(11, slideWindow[j], slideWindow[j_1], slideWindow[j_4]);
                    accumulatorBuckets[r]++;
                    r = TlshUtilities.PearsonHash(13, slideWindow[j], slideWindow[j_3], slideWindow[j_4]);
                    accumulatorBuckets[r]++;
                }
                // rotate the sliding window indexes
                int j_tmp = j_4;
                j_4 = j_3;
                j_3 = j_2;
                j_2 = j_1;
                j_1 = j;
                j   = j_tmp;
            }
            dataLength += byteArrDataLength;
        }
Esempio n. 7
0
        public int TotalDiff(TlshHash otherHash, bool lengthDiff)
        {
            if (checksum.Length != otherHash.checksum.Length || codes.Length != otherHash.codes.Length)
            {
                throw new ArgumentException("Given TLSH structure was created with different options from this hash and cannot be compared");
            }

            var diff = 0;

            if (lengthDiff)
            {
                var ldiff = TlshUtilities.ModDiff(Lvalue, otherHash.Lvalue, CRangeLValue);
                if (ldiff == 0)
                {
                    diff = 0;
                }
                else if (ldiff == 1)
                {
                    diff = 1;
                }
                else
                {
                    diff += ldiff * 12;
                }
            }

            var q1diff = TlshUtilities.ModDiff(Q1ratio, otherHash.Q1ratio, CRangeQRatio);

            if (q1diff <= 1)
            {
                diff += q1diff;
            }
            else
            {
                diff += (q1diff - 1) * 12;
            }

            var q2diff = TlshUtilities.ModDiff(Q2ratio, otherHash.Q2ratio, CRangeQRatio);

            if (q2diff <= 1)
            {
                diff += q2diff;
            }
            else
            {
                diff += (q2diff - 1) * 12;
            }

            for (int k = 0; k < checksum.Length; k++)
            {
                if (checksum[k] != otherHash.checksum[k])
                {
                    diff++;
                    break;
                }
            }

            diff += TlshUtilities.HashDistance(codes, otherHash.codes);

            return(diff);
        }