예제 #1
0
        /// <summary>
        /// Create KSI signature instance from given signature by adding a new aggregation hash chain as the lowest level chain.
        /// </summary>
        /// <param name="signature">Base KSI signature</param>
        /// <param name="inputHash">Input hash of the aggregation chain to be added.</param>
        /// <param name="aggregationAlgorithm">Aggregation algorithm of the aggregation chain to be added.</param>
        /// <param name="chainLinks">Hash chain links of the aggregation chain to be added.</param>
        /// <returns></returns>
        public IKsiSignature CreateSignatureWithAggregationChain(IKsiSignature signature, DataHash inputHash, HashAlgorithm aggregationAlgorithm,
                                                                 AggregationHashChain.Link[] chainLinks)
        {
            AggregationHashChain lowestChain = signature.GetAggregationHashChains()[0];

            // create chain index
            ulong[] firstLevelChainIndex = lowestChain.GetChainIndex();
            ulong[] chainIndex           = new ulong[firstLevelChainIndex.Length + 1];
            Array.Copy(firstLevelChainIndex, 0, chainIndex, 0, firstLevelChainIndex.Length);
            chainIndex[chainIndex.Length - 1] = AggregationHashChain.CalcLocationPointer(chainLinks);

            // Create new lowest chain
            AggregationHashChain newAggregationHashChain = new AggregationHashChain(lowestChain.AggregationTime, chainIndex, inputHash, aggregationAlgorithm.Id, chainLinks);

            // check level correction
            AggregationHashChainResult chainResult = newAggregationHashChain.GetOutputHash(new AggregationHashChainResult(0, inputHash));
            ulong levelCorrection = lowestChain.GetChainLinks()[0].LevelCorrection;

            if (chainResult.Level > levelCorrection)
            {
                throw new KsiException(string.Format(
                                           "The aggregation hash chain cannot be added as lowest level chain. It's output level ({0}) is bigger than level correction of the first link of the first aggregation hash chain of the base signature ({1}).",
                                           chainResult.Level, levelCorrection));
            }

            if (chainResult.Hash != lowestChain.InputHash)
            {
                throw new KsiException("The aggregation hash chain cannot be added as lowest level chain. It's output hash does not match base signature input hash.");
            }

            // Create list on new signature child tags.
            // Add new aggregation hash chain as the first element.
            // Add the chain that was initally the lowest (with corrected level correction) as second element
            List <ITlvTag> childTags = new List <ITlvTag>
            {
                newAggregationHashChain,
                CreateAggregationHashChainWithLevelCorrection(lowestChain, levelCorrection - chainResult.Level)
            };

            foreach (ITlvTag tag in signature)
            {
                // Add all the signature components except the chain that was initially the lowest.
                if (!ReferenceEquals(tag, lowestChain))
                {
                    childTags.Add(tag);
                }
            }

            KsiSignature resultSignature = new KsiSignature(false, false, childTags.ToArray());

            Verify(resultSignature, inputHash);
            return(resultSignature);
        }
예제 #2
0
        /// <summary>
        ///     Get last aggregation hash chain output hash that is calculated from all aggregation hash chains
        /// </summary>
        /// <returns>output hash</returns>
        public DataHash GetLastAggregationHashChainRootHash()
        {
            if (_aggregationHashChainRootHash != null)
            {
                return(_aggregationHashChainRootHash);
            }

            AggregationHashChainResult lastResult = new AggregationHashChainResult(0, _aggregationHashChains[0].InputHash);

            foreach (AggregationHashChain chain in _aggregationHashChains)
            {
                lastResult = chain.GetOutputHash(lastResult);
            }

            return(_aggregationHashChainRootHash = lastResult.Hash);
        }
        /// <summary>
        ///     Get output hash.
        /// </summary>
        /// <param name="result">last hashing result</param>
        /// <returns>output hash chain result</returns>
        public AggregationHashChainResult GetOutputHash(AggregationHashChainResult result)
        {
            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            lock (_cacheLock)
            {
                if (_aggregationHashChainResultCache == null)
                {
                    _aggregationHashChainResultCache = new Dictionary <AggregationHashChainResult, AggregationHashChainResult>();
                }
                else if (_aggregationHashChainResultCache.ContainsKey(result))
                {
                    return(_aggregationHashChainResultCache[result]);
                }
            }

            DataHash lastHash = result.Hash;
            ulong    level    = result.Level;

            foreach (Link link in _links)
            {
                level += link.LevelCorrection + 1;

                if (link.Direction == LinkDirection.Left)
                {
                    lastHash = GetStepHash(lastHash.Imprint, link.GetSiblingData(), level);
                }
                if (link.Direction == LinkDirection.Right)
                {
                    lastHash = GetStepHash(link.GetSiblingData(), lastHash.Imprint, level);
                }
            }

            AggregationHashChainResult returnValue = new AggregationHashChainResult(level, lastHash);

            lock (_cacheLock)
            {
                _aggregationHashChainResultCache[result] = returnValue;
            }

            return(returnValue);
        }
예제 #4
0
        /// <summary>
        ///     Compare current object against another object.
        /// </summary>
        /// <param name="obj">object to compare with</param>
        /// <returns>true if objects are equal</returns>
        public override bool Equals(object obj)
        {
            AggregationHashChainResult a = obj as AggregationHashChainResult;

            // If parameter is null, return false.
            if (ReferenceEquals(a, null))
            {
                return(false);
            }

            if (ReferenceEquals(this, a))
            {
                return(true);
            }

            // If run-time types are not exactly the same, return false.
            if (GetType() != a.GetType())
            {
                return(false);
            }

            return(Hash == a.Hash && Level == a.Level);
        }