private static void CalculateHash_ShouldNotBeDeterministic(HashingAlgorithmSpecification algorithm, SaltingMode saltingMode) => CalculateHash_ValidateDeterminism(algorithm, saltingMode, false);
        private static void CalculateHash_ValidateDeterminism(HashingAlgorithmSpecification algorithm, SaltingMode saltingMode, Boolean shouldBeDeterministic)
        {
            using (var randomnessProvider = RandomNumberGenerator.Create())
            {
                // Arrange.
                var target          = new HashingStringProcessor(randomnessProvider);
                var plaintextObject = "䆟`ಮ䷆ʘ‣⦸⏹ⰄͶa✰ṁ亡Zᨖ0༂⽔9㗰";

                // Act.
                var firstHashValue = target.CalculateHash(plaintextObject, algorithm, saltingMode);

                // Assert.
                firstHashValue.Should().NotBeNullOrEmpty();
                firstHashValue.Count(value => value == 0x00).Should().NotBe(firstHashValue.Length);

                // Act.
                var secondHashValue = target.CalculateHash(plaintextObject, algorithm, saltingMode);

                // Assert.
                secondHashValue.Should().NotBeNullOrEmpty();
                secondHashValue.Length.Should().Be(firstHashValue.Length);
                secondHashValue.Count(value => value == 0x00).Should().NotBe(secondHashValue.Length);

                if (shouldBeDeterministic)
                {
                    // Assert.
                    firstHashValue.ComputeThirtyTwoBitHash().Should().Be(secondHashValue.ComputeThirtyTwoBitHash());
                }
                else
                {
                    // Assert.
                    firstHashValue.ComputeThirtyTwoBitHash().Should().NotBe(secondHashValue.ComputeThirtyTwoBitHash());
                }
            }
        }
        private static void CalculateHash_ValidateDeterminism(HashingAlgorithmSpecification algorithm, SaltingMode saltingMode, Boolean shouldBeDeterministic)
        {
            using (var randomnessProvider = RandomNumberGenerator.Create())
            {
                // Arrange.
                var binarySerializer = new BinaryPassThroughSerializer();
                var target           = new HashingProcessor <Byte[]>(randomnessProvider, binarySerializer);
                var plaintextObject  = new Byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };

                // Act.
                var firstHashValue = target.CalculateHash(plaintextObject, algorithm, saltingMode);

                // Assert.
                firstHashValue.Should().NotBeNullOrEmpty();
                firstHashValue.Count(value => value == 0x00).Should().NotBe(firstHashValue.Length);
                ValidateDigestLength(firstHashValue, algorithm, saltingMode, target.SaltLengthInBytes);

                // Act.
                var secondHashValue = target.CalculateHash(plaintextObject, algorithm, saltingMode);

                // Assert.
                secondHashValue.Should().NotBeNullOrEmpty();
                secondHashValue.Length.Should().Be(firstHashValue.Length);
                secondHashValue.Count(value => value == 0x00).Should().NotBe(secondHashValue.Length);

                if (shouldBeDeterministic)
                {
                    // Assert.
                    firstHashValue.ComputeThirtyTwoBitHash().Should().Be(secondHashValue.ComputeThirtyTwoBitHash());
                }
                else
                {
                    // Assert.
                    firstHashValue.ComputeThirtyTwoBitHash().Should().NotBe(secondHashValue.ComputeThirtyTwoBitHash());
                }
            }
        }
        private static void ValidateDigestLength(Byte[] hashValue, HashingAlgorithmSpecification algorithm, SaltingMode saltingMode, Int32 saltLengthInBytes)
        {
            switch (algorithm)
            {
            case HashingAlgorithmSpecification.Md5:

                hashValue.Length.Should().Be(16 + (saltingMode == SaltingMode.Salted ? saltLengthInBytes : 0));
                break;

            case HashingAlgorithmSpecification.ShaTwo256:

                hashValue.Length.Should().Be(32 + (saltingMode == SaltingMode.Salted ? saltLengthInBytes : 0));
                break;

            case HashingAlgorithmSpecification.ShaTwo384:

                hashValue.Length.Should().Be(48 + (saltingMode == SaltingMode.Salted ? saltLengthInBytes : 0));
                break;

            case HashingAlgorithmSpecification.ShaTwo512:

                hashValue.Length.Should().Be(64 + (saltingMode == SaltingMode.Salted ? saltLengthInBytes : 0));
                break;

            default:

                Assert.Fail();
                return;
            }
        }
        private static void EvaluateHash_ShouldProduceDesiredResults(HashingAlgorithmSpecification algorithm, SaltingMode saltingMode)
        {
            using (var randomnessProvider = RandomNumberGenerator.Create())
            {
                // Arrange.
                var binarySerializer     = new BinaryPassThroughSerializer();
                var target               = new HashingProcessor <Byte[]>(randomnessProvider, binarySerializer);
                var plaintextObject      = new Byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };
                var matchingHashValue    = target.CalculateHash(plaintextObject, algorithm, saltingMode);
                var nonMatchingHashValue = matchingHashValue.PerformCircularBitShift(Core.BitShiftDirection.Left, 16);

                // Act.
                var resultOne = target.EvaluateHash(matchingHashValue, plaintextObject, algorithm, saltingMode);
                var resultTwo = target.EvaluateHash(nonMatchingHashValue, plaintextObject, algorithm, saltingMode);

                // Assert.
                resultOne.Should().BeTrue();
                resultTwo.Should().BeFalse();
                ValidateDigestLength(matchingHashValue, algorithm, saltingMode, target.SaltLengthInBytes);
            }
        }
示例#6
0
        /// <summary>
        /// Calculates a hash value for the specified plaintext object and compares the result with the specified hash value.
        /// </summary>
        /// <param name="hash">
        /// The hash value to evaluate.
        /// </param>
        /// <param name="plaintextObject">
        /// The plaintext object to evaluate.
        /// </param>
        /// <param name="algorithm">
        /// The algorithm specification used to transform the plaintext.
        /// </param>
        /// <param name="saltingMode">
        /// A value specifying whether or not salt is applied to the plaintext.
        /// </param>
        /// <returns>
        /// <see langword="true" /> if the resulting hash value matches <paramref name="hash" />, otherwise <see langword="false" />.
        /// </returns>
        /// <exception cref="SecurityException">
        /// An exception was raised during hashing or serialization.
        /// </exception>
        public Boolean EvaluateHash(Byte[] hash, T plaintextObject, HashingAlgorithmSpecification algorithm, SaltingMode saltingMode)
        {
            try
            {
                var    digestLength = (algorithm.ToDigestBitLength() / 8);
                Byte[] processedHash;
                Byte[] calculatedHash;

                switch (saltingMode)
                {
                case SaltingMode.Salted:

                    var salt = new Byte[SaltLengthInBytes];
                    processedHash  = hash.Take(digestLength).ToArray();
                    salt           = hash.Skip(digestLength).Take(SaltLengthInBytes).ToArray();
                    calculatedHash = CalculateHash(plaintextObject, algorithm, salt).Take(digestLength).ToArray();
                    break;

                default:

                    processedHash  = hash;
                    calculatedHash = CalculateHash(plaintextObject, algorithm, null);
                    break;
                }

                if (processedHash.Length != digestLength)
                {
                    return(false);
                }
                else if (calculatedHash.Length != digestLength)
                {
                    return(false);
                }

                for (var i = 0; i < digestLength; i++)
                {
                    if (processedHash[i] == calculatedHash[i])
                    {
                        continue;
                    }

                    return(false);
                }

                return(true);
            }
            catch
            {
                throw new SecurityException("The hashing operation failed.");
            }
        }
示例#7
0
        /// <summary>
        /// Calculates a hash value for the specified plaintext object.
        /// </summary>
        /// <param name="plaintextObject">
        /// The plaintext object to hash.
        /// </param>
        /// <param name="algorithm">
        /// The algorithm specification used to transform the plaintext.
        /// </param>
        /// <param name="saltingMode">
        /// A value specifying whether or not salt is applied to the plaintext.
        /// </param>
        /// <returns>
        /// The resulting hash value.
        /// </returns>
        /// <exception cref="SecurityException">
        /// An exception was raised during hashing or serialization.
        /// </exception>
        public Byte[] CalculateHash(T plaintextObject, HashingAlgorithmSpecification algorithm, SaltingMode saltingMode)
        {
            try
            {
                switch (saltingMode)
                {
                case SaltingMode.Salted:

                    var salt = new Byte[SaltLengthInBytes];
                    RandomnessProvider.GetBytes(salt);
                    return(CalculateHash(plaintextObject, algorithm, salt));

                default:

                    return(CalculateHash(plaintextObject, algorithm, null));
                }
            }
            catch
            {
                throw new SecurityException("The hashing operation failed.");
            }
        }