Ejemplo n.º 1
0
    private bool AddKeyValue(byte[] key, TValue value)
    {     // lock(cs) required.
        var table = this.hashTable;
        var hash  = unchecked ((int)FarmHash.Hash64(key));
        var h     = hash & (table.Length - 1);

        if (table[h] == null)
        {
            var item = new Item(key, value, hash);
            System.Threading.Volatile.Write(ref table[h], item);
        }
        else
        {
            var i = table[h] !;
            while (true)
            {
                if (key.SequenceEqual(i.Key) == true)
                {    // Identical
                    return(false);
                }

                if (i.Next == null)
                {     // Last item.
                    break;
                }

                i = i.Next;
            }

            var item = new Item(key, value, hash);
            System.Threading.Volatile.Write(ref i.Next, item);
        }

        return(true);
    }
Ejemplo n.º 2
0
 public static int GetHashCode(byte[] bytes, int offset, int count)
 {
     if (Is32Bit)
     {
         return(unchecked ((int)FarmHash.Hash32(bytes, offset, count)));
     }
     else
     {
         return(unchecked ((int)FarmHash.Hash64(bytes, offset, count)));
     }
 }
Ejemplo n.º 3
0
    /// <summary>
    /// Decrypts data using the specified password.
    /// </summary>
    /// <param name="encrypted">The encrypted data.</param>
    /// <param name="password">The password.</param>
    /// <param name="data">The decrypted data.</param>
    /// <returns><see langword="true"/> if the decryption was successful; otherwise, <see langword="false"/>.</returns>
    public static bool TryDecrypt(ReadOnlySpan <byte> encrypted, ReadOnlySpan <byte> password, out Memory <byte> data)
    {
        data = default;
        if (encrypted.Length < SaltLength)
        {
            return(false);
        }

        // Hash: Sha3_384 => Key(32) + IV(16)
        var keyIV = GetKeyIV(encrypted.Slice(0, SaltLength), password);

        // AES
        byte[] decrypted;
        using (var aes = Aes.Create())
        {
            aes.Key = keyIV.Slice(0, aes.KeySize / 8).ToArray();
            if (keyIV.Length != ((aes.KeySize / 8) + (aes.BlockSize / 8)))
            {
                throw new InvalidOperationException();
            }

            // Salt[8], Encrypted[8 + 8 + DataLength] (Random[8], Checksum[8 = FarmHash64], Data[DataLength])
            try
            {
                decrypted = aes.DecryptCbc(encrypted.Slice(SaltLength), keyIV.Slice(aes.KeySize / 8), DefaultPaddingMode);
            }
            catch
            {
                return(false);
            }
        }

        var dataPosition = RandomLength + ChecksumLength;

        if (decrypted.Length < dataPosition)
        {
            return(false);
        }

        // Checksum: FarmHash64
        var checksum = FarmHash.Hash64(decrypted.AsSpan(dataPosition));

        if (BitConverter.ToUInt64(decrypted.AsSpan(RandomLength)) != checksum)
        {
            return(false);
        }

        data = decrypted.AsMemory(dataPosition);
        return(true);
    }
Ejemplo n.º 4
0
    /// <summary>
    /// Encrypts data using the specified password.
    /// </summary>
    /// <param name="data">The data to encrypt.</param>
    /// <param name="password">The password.</param>
    /// <returns>The encrypted data.</returns>
    public static byte[] Encrypt(ReadOnlySpan <byte> data, ReadOnlySpan <byte> password)
    {
        // Salt: Random[SaltLength], Random: Random[RandomLength]
        var randomBuffer = RandomNumberGenerator.GetBytes(SaltLength + RandomLength);
        var salt         = randomBuffer.AsSpan(0, SaltLength);
        var random       = randomBuffer.AsSpan(SaltLength, RandomLength);

        // Hash: Sha3_384 => Key(32) + IV(16)
        var keyIV = GetKeyIV(salt, password);

        // Checksum: FarmHash64
        var checksum = FarmHash.Hash64(data);

        // AES
        byte[] buffer;
        using (var aes = Aes.Create())
        {
            aes.Key = keyIV.Slice(0, aes.KeySize / 8).ToArray();
            var plainLength  = RandomLength + ChecksumLength + data.Length;
            var cipherLength = aes.GetCiphertextLengthCbc(plainLength, DefaultPaddingMode);
            if (keyIV.Length != ((aes.KeySize / 8) + (aes.BlockSize / 8)))
            {
                throw new InvalidOperationException();
            }

            // Salt[8], Encrypted[8 + 8 + DataLength] (Random[8], Checksum[8 = FarmHash64], Data[DataLength])
            var bufferLength = SaltLength + cipherLength;
            buffer = new byte[bufferLength];
            var bufferSpan = buffer.AsSpan();
            salt.CopyTo(bufferSpan);
            bufferSpan = bufferSpan.Slice(SaltLength);
            random.CopyTo(bufferSpan);
            bufferSpan = bufferSpan.Slice(RandomLength);
            BitConverter.TryWriteBytes(bufferSpan, checksum);
            bufferSpan = bufferSpan.Slice(ChecksumLength);
            data.CopyTo(bufferSpan);

            // Encrypt
            var written = aes.EncryptCbc(buffer.AsSpan(SaltLength, plainLength), keyIV.Slice(aes.KeySize / 8), buffer.AsSpan(SaltLength), DefaultPaddingMode);
            Debug.Assert(written == cipherLength, "Encrypted length mismatch.");
        }

        return(buffer);
    }
Ejemplo n.º 5
0
    public bool TryGetValue(ReadOnlySpan <byte> key, [MaybeNullWhen(false)] out TValue value)
    {
        var table = this.hashTable;
        var hash  = unchecked ((int)FarmHash.Hash64(key));
        var item  = table[hash & (table.Length - 1)];

        while (item != null)
        {
            if (key.SequenceEqual(item.Key) == true)
            {     // Identical. alternative: (key == item.Key).
                value = item.Value;
                return(true);
            }

            item = item.Next;
        }

        value = default;
        return(false);
    }
Ejemplo n.º 6
0
    public void TestHashUpdate()
    {
        const int N      = 1_000_000;
        var       random = new Random(42);
        var       data   = new byte[N];

        random.NextBytes(data);

        // CRC-32
        var crc32 = new Crc32();

        for (var n = 0; n < 1000; n++)
        {
            var span = data.AsSpan(0, n);
            var h    = BitConverter.ToUInt32(crc32.GetHash(span));
            var h2   = Crc32.Hash32(span);
            Assert.Equal(h, h2);
        }

        this.TestHashUpdate_do(crc32, data, random);

        // Adler-32
        var adler32 = new Adler32();

        for (var n = 0; n < 1000; n++)
        {
            var span = data.AsSpan(0, n);
            var h    = BitConverter.ToUInt32(adler32.GetHash(span));
            var h2   = Adler32.Hash32(span);
            Assert.Equal(h, h2);
        }

        this.TestHashUpdate_do(adler32, data, random);

        // FarmHash
        var farm = new FarmHash();

        for (var n = 0; n < 1000; n++)
        {
            var span = data.AsSpan(0, n);
            var h    = BitConverter.ToUInt64(farm.GetHash(span));
            var h2   = FarmHash.Hash64(span);
            Assert.Equal(h, h2);
        }

        this.TestHashUpdate_do(farm, data, random);

        // xxHash32
        var xxh32 = new XXHash32();

        for (var n = 0; n < 1000; n++)
        {
            var span = data.AsSpan(0, n);
            var h    = BitConverter.ToUInt32(xxh32.GetHash(span));
            var h2   = XXHash32.Hash32(span);
            Assert.Equal(h, h2);
        }

        this.TestHashUpdate_do(xxh32, data, random);

        // xxHash64
        var xxh64 = new XxHash64();

        for (var n = 0; n < 1000; n++)
        {
            var span = data.AsSpan(0, n);
            var h    = BitConverter.ToUInt64(xxh64.GetHash(span));
            var h2   = XxHash64.Hash64(span);
            Assert.Equal(h, h2);
        }

        this.TestHashUpdate_do(xxh64, data, random);

        // Sha1
        using var sha1 = new Arc.Crypto.Sha1();
        this.TestHashUpdate_do(sha1, data, random);

        // Sha2_256
        using var sha2_256 = new Arc.Crypto.Sha2_256();
        this.TestHashUpdate_do(sha2_256, data, random);

        // Sha2_384
        using var sha2_384 = new Arc.Crypto.Sha2_384();
        this.TestHashUpdate_do(sha2_384, data, random);

        // Sha2_512
        using var sha2_512 = new Arc.Crypto.Sha2_512();
        this.TestHashUpdate_do(sha2_512, data, random);

        // Sha3_256
        var sha3_256 = new Arc.Crypto.Sha3_256();

        this.TestHashUpdate_do(sha3_256, data, random);

        // Sha3_384
        var sha3_384 = new Arc.Crypto.Sha3_384();

        this.TestHashUpdate_do(sha3_384, data, random);

        // Sha3_512
        var sha3_512 = new Arc.Crypto.Sha3_512();

        this.TestHashUpdate_do(sha3_512, data, random);
    }