/// <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], _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] - _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;
        }
Exemple #2
0
        /// <summary>
        /// This function verifies the signature of the message that has been updated, with the aid of the public key
        /// </summary>
        /// 
        /// <param name="Message">The message</param>
        /// <param name="Signature">The signature of the message</param>
        /// 
        /// <returns>Returns true if the signature has been verified, false otherwise</returns>
        private bool VerifySignature(byte[] Message, byte[] Signature)
        {
            bool success = false;
            // int halfSigLength = signature.length >>> 1;
            _msgDigestOTS.Reset();
            WinternitzOTSVerify otsVerify;
            int otsSigLength;
            byte[] help = Message;
            byte[] otsSig;
            byte[] otsPublicKey;
            byte[][] authPath;
            byte[] dest;
            int nextEntry = 0;
            int index;

            // begin with message = 'message that was signed' and then in each step message = subtree root
            for (int j = _numLayer - 1; j >= 0; j--)
            {
                otsVerify = new WinternitzOTSVerify(GetDigest(_gmssPS.DigestEngine), _gmssPS.WinternitzParameter[j]);
                otsSigLength = otsVerify.GetSignatureLength();
                Message = help;
                // get the subtree index
                index = GMSSUtil.BytesToIntLittleEndian(Signature, nextEntry);
                // 4 is the number of bytes in integer
                nextEntry += 4;
                // get one-time signature
                otsSig = new byte[otsSigLength];
                Array.Copy(Signature, nextEntry, otsSig, 0, otsSigLength);
                nextEntry += otsSigLength;
                // compute public OTS key from the one-time signature
                otsPublicKey = otsVerify.Verify(Message, otsSig);

                // test if OTSsignature is correct
                if (otsPublicKey == null)
                    return false;

                // get authentication path from the signature
                authPath = ArrayUtils.CreateJagged<byte[][]>(_gmssPS.HeightOfTrees[j], _mdLength);//new byte[gmssPS.GetHeightOfTrees()[j]][mdLength];
                for (int i = 0; i < authPath.Length; i++)
                {
                    Array.Copy(Signature, nextEntry, authPath[i], 0, _mdLength);
                    nextEntry = nextEntry + _mdLength;
                }

                // compute the root of the subtree from the authentication path
                help = new byte[_mdLength];
                help = otsPublicKey;
                int count = 1 << authPath.Length;
                count = count + index;

                for (int i = 0; i < authPath.Length; i++)
                {
                    dest = new byte[_mdLength << 1];

                    if ((count % 2) == 0)
                    {
                        Array.Copy(help, 0, dest, 0, _mdLength);
                        Array.Copy(authPath[i], 0, dest, _mdLength, _mdLength);
                        count = count / 2;
                    }
                    else
                    {
                        Array.Copy(authPath[i], 0, dest, 0, _mdLength);
                        Array.Copy(help, 0, dest, _mdLength, help.Length);
                        count = (count - 1) / 2;
                    }

                    _msgDigestTrees.BlockUpdate(dest, 0, dest.Length);
                    help = new byte[_msgDigestTrees.DigestSize];
                    _msgDigestTrees.DoFinal(help, 0);
                }
            }

            // now help contains the root of the maintree
            // test if help is equal to the GMSS public key
            if (Compare.IsEqual(_pubKeyBytes, help))
                success = true;

            return success;
        }