示例#1
0
        /// <summary>
        /// Computes the fuzzy hash of the first len bytes of the buffer.
        /// </summary>
        public static string HashBuffer(byte[] buf, int len, FuzzyHashMode flags = FuzzyHashMode.None)
        {
            var ctx = new Hasher();

            ctx.Update(buf, len);
            return(ctx.Digest(flags));
        }
示例#2
0
        /// <summary>
        /// Obtain the fuzzy hash from the state.
        /// This operation does not change the state at all. It reports the hash for the
        /// concatenation of the data previously fed using fuzzy_update.
        /// </summary>
        private string Digest(FuzzyHashMode flags)
        {
            var result = new byte[FuzzyConstants.MaxResultLength];
            var pos    = 0;

            uint bi = _bhstart;
            uint h  = _roll.Sum();
            int  i; // Exclude terminating '\0'.

            /* Initial blocksize guess. */
            while ((uint)(((uint)FuzzyConstants.MinBlocksize) << (int)(bi)) * FuzzyConstants.SpamSumLength < _totalSize)
            {
                ++bi;
                if (bi >= FuzzyConstants.NumBlockhashes)
                {
                    throw new OverflowException("EOVERFLOW");
                }
            }
            /* Adapt blocksize guess to actual digest length. */
            while (bi >= _bhend)
            {
                --bi;
            }
            while (bi > _bhstart && _bh[bi].DLen < FuzzyConstants.SpamSumLength / 2)
            {
                --bi;
            }

            var actualBlockSize = (((uint)FuzzyConstants.MinBlocksize) << (int)(bi));
            var blockSizeChars  = actualBlockSize.ToString().ToCharArray();

            i = blockSizeChars.Length;
            for (int j = 0; j < i; j++)
            {
                result[j + pos] = (byte)blockSizeChars[j];
            }
            result[i++] = (byte)':';

            pos += i;
            i    = (int)_bh[bi].DLen;

            if (flags.HasFlag(FuzzyHashMode.EliminateSequences))
            {
                i = MemcpyEliminateSequences(result, pos, _bh[bi].Digest, i);
            }
            else
            {
                Array.Copy(_bh[bi].Digest, 0, result, pos, i);
            }

            pos += i;
            if (h != 0)
            {
                var base64Val = FuzzyConstants.Base64[_bh[bi].H % 64];
                result[pos] = base64Val;
                if (!flags.HasFlag(FuzzyHashMode.EliminateSequences) || i < 3 || base64Val != result[pos - 1] || base64Val != result[pos - 2] || base64Val != result[pos - 3])
                {
                    ++pos;
                }
            }
            else if (_bh[bi].Digest[i] != '\0')
            {
                var digestVal = _bh[bi].Digest[i];
                result[pos] = digestVal;
                if (!flags.HasFlag(FuzzyHashMode.EliminateSequences) || i < 3 || digestVal != result[pos - 1] || digestVal != result[pos - 2] || digestVal != result[pos - 3])
                {
                    ++pos;
                }
            }
            result[pos++] = (byte)':';

            if (bi < _bhend - 1)
            {
                ++bi;
                i = (int)_bh[bi].DLen;
                if (!flags.HasFlag(FuzzyHashMode.DoNotTruncate) && i > FuzzyConstants.SpamSumLength / 2 - 1)
                {
                    i = FuzzyConstants.SpamSumLength / 2 - 1;
                }

                if (flags.HasFlag(FuzzyHashMode.EliminateSequences))
                {
                    i = MemcpyEliminateSequences(result, pos, _bh[bi].Digest, i);
                }
                else
                {
                    Array.Copy(_bh[bi].Digest, 0, result, pos, i);
                }

                pos += i;
                if (h != 0)
                {
                    h = flags.HasFlag(FuzzyHashMode.DoNotTruncate) ? _bh[bi].H : _bh[bi].HalfH;
                    var base64Val = FuzzyConstants.Base64[h % 64];
                    result[pos] = base64Val;
                    if (!flags.HasFlag(FuzzyHashMode.EliminateSequences) || i < 3 || base64Val != result[pos - 1] || base64Val != result[pos - 2] || base64Val != result[pos - 3])
                    {
                        ++pos;
                    }
                }
                else
                {
                    i = flags.HasFlag(FuzzyHashMode.DoNotTruncate) ? _bh[bi].Digest[_bh[bi].DLen] : _bh[bi].HalfDigest;
                    if (i != '\0')
                    {
                        result[pos] = (byte)i;
                        if (!flags.HasFlag(FuzzyHashMode.EliminateSequences) || i < 3 || i != result[pos - 1] || i != result[pos - 2] || i != result[pos - 3])
                        {
                            ++pos;
                        }
                    }
                }
            }
            else if (h != 0)
            {
                result[pos++] = FuzzyConstants.Base64[_bh[bi].H % 64];

                /* No need to bother with FuzzyHashMode.EliminateSequences, because this
                 * digest has length 1. */
            }

            return(Encoding.ASCII.GetString(result, 0, pos));
        }