private static AggregationHashChain CreateAggregationHashChainWithLevelCorrection(AggregationHashChain aggregationHashChain, ulong levelCorrection) { ReadOnlyCollection <AggregationHashChain.Link> chainLinks = aggregationHashChain.GetChainLinks(); TlvTagBuilder builder = new TlvTagBuilder(aggregationHashChain); AggregationHashChain.Link firstLink = chainLinks[0]; builder.ReplaceChildTag(firstLink, CreateLinkWithLevelCorrection(firstLink, levelCorrection)); return(new AggregationHashChain(builder.BuildTag())); }
private static KsiSignature CreateSignatureWithLevelCorrection(KsiSignature signature, uint addToFirstLinkLinkLevelCorrection) { ReadOnlyCollection <AggregationHashChain> aggregationHashChains = signature.GetAggregationHashChains(); TlvTagBuilder builder = new TlvTagBuilder(signature); AggregationHashChain firstAggregationHashChain = aggregationHashChains[0]; ulong levelCorrection = firstAggregationHashChain.GetChainLinks()[0].LevelCorrection + addToFirstLinkLinkLevelCorrection; builder.ReplaceChildTag(firstAggregationHashChain, CreateAggregationHashChainWithLevelCorrection(firstAggregationHashChain, levelCorrection)); return(new KsiSignature(false, false, builder.GetChildTags())); }
/// <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); }