/// <summary> /// Calculates the authpath for tree in layer h which starts with seed[h] additionally computes the rootSignature of underlaying root /// </summary> /// /// <param name="LowerRoot">Stores the root of the lower tree</param> /// <param name="CurrentStack">Stack used for the treehash instance created by this method</param> /// <param name="Seed">Starting seeds</param> /// <param name="H">Actual layer</param> /// <returns>An initialized GMSSRootCalc</returns> private GMSSRootCalc GenerateCurrentAuthpathAndRoot(byte[] LowerRoot, List <byte[]> CurrentStack, byte[] Seed, int H) { byte[] help = new byte[_mdLength]; byte[] OTSseed = new byte[_mdLength]; OTSseed = _gmssRand.NextSeed(Seed); WinternitzOTSignature ots; // data structure that constructs the whole tree and stores the initial values for treehash, Auth and retain GMSSRootCalc treeToConstruct = new GMSSRootCalc(_heightOfTrees[H], m_K[H], GetDigest(_msgDigestType)); treeToConstruct.Initialize(CurrentStack); // generate the first leaf if (H == _numLayer - 1) { ots = new WinternitzOTSignature(OTSseed, GetDigest(_msgDigestType), _otsIndex[H]); help = ots.GetPublicKey(); } else { // for all layers except the lowest, generate the signature of the underlying root // and reuse this signature to compute the first leaf of acual layer more efficiently (by verifiing the signature) ots = new WinternitzOTSignature(OTSseed, GetDigest(_msgDigestType), _otsIndex[H]); _currentRootSigs[H] = ots.GetSignature(LowerRoot); WinternitzOTSVerify otsver = new WinternitzOTSVerify(GetDigest(_msgDigestType), _otsIndex[H]); help = otsver.Verify(LowerRoot, _currentRootSigs[H]); } // update the tree with the first leaf treeToConstruct.Update(help); int seedForTreehashIndex = 3; int count = 0; // update the tree 2^(H) - 1 times, from the second to the last leaf for (int i = 1; i < (1 << _heightOfTrees[H]); i++) { // initialize the seeds for the leaf generation with index 3 * 2^h if (i == seedForTreehashIndex && count < _heightOfTrees[H] - m_K[H]) { treeToConstruct.InitializeTreehashSeed(Seed, count); seedForTreehashIndex *= 2; count++; } OTSseed = _gmssRand.NextSeed(Seed); ots = new WinternitzOTSignature(OTSseed, GetDigest(_msgDigestType), _otsIndex[H]); treeToConstruct.Update(ots.GetPublicKey()); } if (treeToConstruct.IsFinished()) { return(treeToConstruct); } return(null); }
/// <summary> /// This function signs the message that has been updated, making use of the private key. /// <para>For computing the signature, L1 and L2 are needed, as well as LES should be solved /// for each layer in order to find the Oil-variables in the layer. /// The Vinegar-variables of the first layer are random generated.</para> /// </summary> /// /// <param name="Message">The message</param> /// /// <returns>The signature of the message</returns> private byte[] GenerateSignature(byte[] Message) { byte[] otsSig = new byte[_mdLength]; byte[] authPathBytes; byte[] indexBytes; otsSig = _Ots.GetSignature(Message); // get concatenated lowest layer tree authentication path authPathBytes = GMSSUtil.ConcatenateArray(_currentAuthPaths[_numLayer - 1]); // put lowest layer index into a byte array indexBytes = GMSSUtil.IntToBytesLittleEndian(_index[_numLayer - 1]); // create first part of GMSS signature byte[] gmssSigFirstPart = new byte[indexBytes.Length + otsSig.Length + authPathBytes.Length]; Array.Copy(indexBytes, 0, gmssSigFirstPart, 0, indexBytes.Length); Array.Copy(otsSig, 0, gmssSigFirstPart, indexBytes.Length, otsSig.Length); Array.Copy(authPathBytes, 0, gmssSigFirstPart, (indexBytes.Length + otsSig.Length), authPathBytes.Length); // create initial array with length 0 for iteration byte[] gmssSigNextPart = new byte[0]; for (int i = _numLayer - 1 - 1; i >= 0; i--) { // get concatenated next tree authentication path authPathBytes = GMSSUtil.ConcatenateArray(_currentAuthPaths[i]); // put next tree index into a byte array indexBytes = GMSSUtil.IntToBytesLittleEndian(_index[i]); // create help array and copy actual gmssSig into it byte[] helpGmssSig = new byte[gmssSigNextPart.Length]; Array.Copy(gmssSigNextPart, 0, helpGmssSig, 0, gmssSigNextPart.Length); // adjust length of gmssSigNextPart for adding next part gmssSigNextPart = new byte[helpGmssSig.Length + indexBytes.Length + _subtreeRootSig[i].Length + authPathBytes.Length]; // copy old data (help array) and new data in gmssSigNextPart Array.Copy(helpGmssSig, 0, gmssSigNextPart, 0, helpGmssSig.Length); Array.Copy(indexBytes, 0, gmssSigNextPart, helpGmssSig.Length, indexBytes.Length); Array.Copy(_subtreeRootSig[i], 0, gmssSigNextPart, (helpGmssSig.Length + indexBytes.Length), _subtreeRootSig[i].Length); Array.Copy(authPathBytes, 0, gmssSigNextPart, (helpGmssSig.Length + indexBytes.Length + _subtreeRootSig[i].Length), authPathBytes.Length); } // concatenate the two parts of the GMSS signature byte[] gmssSig = new byte[gmssSigFirstPart.Length + gmssSigNextPart.Length]; Array.Copy(gmssSigFirstPart, 0, gmssSig, 0, gmssSigFirstPart.Length); Array.Copy(gmssSigNextPart, 0, gmssSig, gmssSigFirstPart.Length, gmssSigNextPart.Length); // return the GMSS signature return(gmssSig); }