コード例 #1
0
        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());
                }
            }
        }
コード例 #2
0
        internal static Int32 ToDigestBitLength(this HashingAlgorithmSpecification target)
        {
            switch (target)
            {
            case HashingAlgorithmSpecification.Unspecified:

                return(default(Int32));

            case HashingAlgorithmSpecification.Md5:

                return(128);

            case HashingAlgorithmSpecification.ShaTwo256:

                return(256);

            case HashingAlgorithmSpecification.ShaTwo384:

                return(384);

            case HashingAlgorithmSpecification.ShaTwo512:

                return(512);

            default:

                throw new ArgumentException($"{target} is not a supported {nameof(HashingAlgorithmSpecification)}.", nameof(target));
            }
        }
コード例 #3
0
        internal static HashAlgorithm ToHashAlgorithm(this HashingAlgorithmSpecification target)
        {
            switch (target)
            {
            case HashingAlgorithmSpecification.Unspecified:

                return(null);

            case HashingAlgorithmSpecification.Md5:

                return(MD5.Create());

            case HashingAlgorithmSpecification.ShaTwo256:

                return(SHA256.Create());

            case HashingAlgorithmSpecification.ShaTwo384:

                return(SHA384.Create());

            case HashingAlgorithmSpecification.ShaTwo512:

                return(SHA512.Create());

            default:

                throw new ArgumentException($"{target} is not a supported {nameof(HashingAlgorithmSpecification)}.", nameof(target));
            }
        }
コード例 #4
0
        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;
            }
        }
コード例 #5
0
ファイル: HashTree.cs プロジェクト: lulzzz/solid-instruments
 /// <summary>
 /// Initializes a new instance of the <see cref="HashTree{T}" /> class.
 /// </summary>
 /// <param name="hashingProcessor">
 /// A processor that produces hash values.
 /// </param>
 /// <param name="algorithm">
 /// The algorithm used to produce hash values. The default value is <see cref="HashingAlgorithmSpecification.ShaTwo256" />.
 /// </param>
 /// <param name="blocks">
 /// An ordered collection of data block objects underlying the tree.
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// <paramref name="hashingProcessor" /> is <see langword="null" /> -or- <paramref name="blocks" /> is
 /// <see langword="null" />.
 /// </exception>
 /// <exception cref="ArgumentOutOfRangeException">
 /// <paramref name="algorithm" /> is equal to <see cref="HashingAlgorithmSpecification.Unspecified" />.
 /// </exception>
 /// <exception cref="SecurityException">
 /// An exception was raised during hashing or serialization.
 /// </exception>
 public HashTree(IHashingProcessor <TBlock> hashingProcessor, HashingAlgorithmSpecification algorithm, IEnumerable <TBlock> blocks)
     : base()
 {
     Algorithm        = algorithm.RejectIf().IsEqualToValue(HashingAlgorithmSpecification.Unspecified, nameof(algorithm));
     HashingProcessor = hashingProcessor.RejectIf().IsNull(nameof(hashingProcessor)).TargetArgument;
     LeafNodes        = new List <HashTreeNode>();
     RootNode         = new HashTreeNode();
     AddBlockRange(blocks);
 }
コード例 #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 binary array.
        /// </summary>
        /// <param name="plaintextBinaryArray">
        /// The plaintext binary array to hash.
        /// </param>
        /// <param name="algorithm">
        /// The algorithm specification used to transform the plaintext.
        /// </param>
        /// <param name="salt">
        /// The salt to apply to the plaintext, or <see langword="null" /> if the plaintext is unsalted. The default value is
        /// <see langword="null" />.
        /// </param>
        /// <returns>
        /// The resulting hash value.
        /// </returns>
        /// <exception cref="SecurityException">
        /// An exception was raised during hashing or serialization.
        /// </exception>
        public Byte[] CalculateHash(Byte[] plaintextBinaryArray, HashingAlgorithmSpecification algorithm, Byte[] salt)
        {
            try
            {
                var    applySalt                    = (salt is null == false);
                var    saltLengthInBytes            = (applySalt ? salt.Length : 0);
                var    plaintextLengthInBytes       = plaintextBinaryArray.Length;
                var    plaintextBufferLengthInBytes = (plaintextLengthInBytes + saltLengthInBytes);
                var    digestLengthInBytes          = (algorithm.ToDigestBitLength() / 8);
                var    hashLengthInBytes            = (digestLengthInBytes + saltLengthInBytes);
                var    hashValue                    = new Byte[hashLengthInBytes];
                Byte[] plaintextBuffer;

                if (applySalt)
                {
                    plaintextBuffer = new Byte[plaintextBufferLengthInBytes];
                    Array.Copy(plaintextBinaryArray, plaintextBuffer, plaintextLengthInBytes);
                    Array.Copy(salt, 0, plaintextBuffer, plaintextLengthInBytes, saltLengthInBytes);
                }
                else
                {
                    plaintextBuffer = plaintextBinaryArray;
                }

                using (var hashAlgorithm = algorithm.ToHashAlgorithm())
                {
                    Array.Copy(hashAlgorithm.ComputeHash(plaintextBinaryArray), hashValue, digestLengthInBytes);
                }

                if (applySalt)
                {
                    Array.Copy(salt, 0, hashValue, digestLengthInBytes, saltLengthInBytes);
                }

                return(hashValue);
            }
            catch
            {
                throw new SecurityException("The hashing operation failed.");
            }
        }
コード例 #8
0
        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);
            }
        }
コード例 #9
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.");
            }
        }
コード例 #10
0
        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());
                }
            }
        }
コード例 #11
0
        private static void Constructor_ShouldProduceDesiredResults(Int32 blockCount, HashingAlgorithmSpecification algorithm)
        {
            using (var randomnessProvider = RandomNumberGenerator.Create())
            {
                // Arrange.
                var hashingProcessor = new HashingStringProcessor(randomnessProvider);
                var blocks           = new String[blockCount];
                randomnessProvider.FillStringArray(blocks, 1, 8, false, true, true, true, false, false, false);

                // Act.
                var target    = new HashTree <String>(hashingProcessor, algorithm, blocks);
                var duplicate = new HashTree <String>(hashingProcessor, algorithm, blocks);

                // Assert.
                target.LeafCount.Should().Be(blockCount);
                target.RootNode.Should().NotBeNull();
                target.RootNode.Value.Should().NotBeNull();
                target.RootNode.Value.ComputeThirtyTwoBitHash().Should().Be(duplicate.RootNode.Value.ComputeThirtyTwoBitHash());
                target.RootNode.ToString().Should().Be(Convert.ToBase64String(target.RootNode.Value));
                ValidateDigestLength(blockCount, target.RootNode.Value, algorithm);
                ValidateTreeHeight(blockCount, target.RootNode.Height);
            }
        }
コード例 #12
0
ファイル: HashTree.cs プロジェクト: lulzzz/solid-instruments
 /// <summary>
 /// Initializes a new instance of the <see cref="HashTree{T}" /> class.
 /// </summary>
 /// <param name="hashingProcessor">
 /// A processor that produces hash values.
 /// </param>
 /// <param name="algorithm">
 /// The algorithm used to produce hash values. The default value is <see cref="HashingAlgorithmSpecification.ShaTwo256" />.
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// <paramref name="hashingProcessor" /> is <see langword="null" />.
 /// </exception>
 /// <exception cref="ArgumentOutOfRangeException">
 /// <paramref name="algorithm" /> is equal to <see cref="HashingAlgorithmSpecification.Unspecified" />.
 /// </exception>
 public HashTree(IHashingProcessor <TBlock> hashingProcessor, HashingAlgorithmSpecification algorithm)
     : this(hashingProcessor, algorithm, Array.Empty <TBlock>())
 {
     return;
 }
コード例 #13
0
 private Byte[] CalculateHash(T plaintextObject, HashingAlgorithmSpecification algorithm, Byte[] salt) => CalculateHash(BinarySerializer.Serialize(plaintextObject), algorithm, salt);
コード例 #14
0
 /// <summary>
 /// Calculates a hash value for the specified plaintext binary array.
 /// </summary>
 /// <param name="plaintextBinaryArray">
 /// The plaintext binary array to hash.
 /// </param>
 /// <param name="algorithm">
 /// The algorithm specification used to transform the plaintext.
 /// </param>
 /// <returns>
 /// The resulting hash value.
 /// </returns>
 /// <exception cref="SecurityException">
 /// An exception was raised during hashing or serialization.
 /// </exception>
 public Byte[] CalculateHash(Byte[] plaintextBinaryArray, HashingAlgorithmSpecification algorithm) => CalculateHash(plaintextBinaryArray, algorithm, null);
コード例 #15
0
 private static void CalculateHash_ShouldNotBeDeterministic_ForSaltedHashing(HashingAlgorithmSpecification algorithm) => CalculateHash_ShouldNotBeDeterministic(algorithm, SaltingMode.Salted);
コード例 #16
0
 private static void CalculateHash_ShouldNotBeDeterministic(HashingAlgorithmSpecification algorithm, SaltingMode saltingMode) => CalculateHash_ValidateDeterminism(algorithm, saltingMode, false);
コード例 #17
0
        private static void ValidateDigestLength(Int32 blockCount, Byte[] rootHashValue, HashingAlgorithmSpecification algorithm)
        {
            if (blockCount == 0)
            {
                rootHashValue.Length.Should().Be(0);
                return;
            }

            switch (algorithm)
            {
            case HashingAlgorithmSpecification.Md5:

                rootHashValue.Length.Should().Be(16);
                break;

            case HashingAlgorithmSpecification.ShaTwo256:

                rootHashValue.Length.Should().Be(32);
                break;

            case HashingAlgorithmSpecification.ShaTwo384:

                rootHashValue.Length.Should().Be(48);
                break;

            case HashingAlgorithmSpecification.ShaTwo512:

                rootHashValue.Length.Should().Be(64);
                break;

            default:

                Assert.Fail();
                return;
            }
        }
コード例 #18
0
 private static void EvaluateHash_ShouldProduceDesiredResults_ForUnsaltedHashing(HashingAlgorithmSpecification algorithm) => EvaluateHash_ShouldProduceDesiredResults(algorithm, SaltingMode.Unsalted);