/// <summary>
        /// Calculates the authpath and root for tree in layer h which starts with seed[h]
        /// </summary>
        /// 
        /// <param name="NextStack">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 GenerateNextAuthpathAndRoot(List<byte[]> NextStack, byte[] Seed, int H)
        {
            byte[] OTSseed = new byte[_numLayer];
            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(NextStack);
            int seedForTreehashIndex = 3;
            int count = 0;

            // update the tree 2^(H) times, from the first to the last leaf
            for (int i = 0; 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;
        }
        /// <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;
        }
Esempio n. 3
0
        /// <summary>
        /// Updates the authentication path and root calculation for the tree after next (AUTH++, ROOT++) in layer <c>layer</c>
        /// </summary>
        /// 
        /// <param name="Layer">The layer</param>
        private void UpdateNextNextAuthRoot(int Layer)
        {
            byte[] OTSseed = new byte[_mdLength];
            OTSseed = _gmssRandom.NextSeed(_nextNextSeeds[Layer - 1]);

            // get the necessary leaf
            if (Layer == _numLayer - 1)
            {
                // lowest layer computes the necessary leaf completely at this time
                WinternitzOTSignature ots = new WinternitzOTSignature(OTSseed, GetDigest(_msgDigestType), _otsIndex[Layer]);
                _nextNextRoot[Layer - 1].Update(_nextNextSeeds[Layer - 1], ots.GetPublicKey());
            }
            else
            {
                // other layers use the precomputed leafs in nextNextLeaf
                _nextNextRoot[Layer - 1].Update(_nextNextSeeds[Layer - 1], _nextNextLeaf[Layer - 1].GetLeaf());
                _nextNextLeaf[Layer - 1].InitLeafCalc(_nextNextSeeds[Layer - 1]);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Initializes the signature algorithm for signing a message
        /// </summary>
        private void InitSign()
        {
            _msgDigestTrees.Reset();
            // set private key and take from it ots key, auth, tree and key counter, rootSign
            GMSSPrivateKey gmssPrivateKey = (GMSSPrivateKey)_asmKey;

            if (gmssPrivateKey.IsUsed)
                throw new Exception("Private key already used");

            // check if last signature has been generated
            if (gmssPrivateKey.GetCurrentIndex(0) >= gmssPrivateKey.GetNumLeafs(0))
                throw new Exception("No more signatures can be generated");

            // get numLayer
            _numLayer = _gmssPS.NumLayers;

            // get OTS Instance of lowest layer
            byte[] seed = gmssPrivateKey.CurrentSeeds[_numLayer - 1];
            byte[] OTSSeed = new byte[_mdLength];
            byte[] dummy = new byte[_mdLength];
            Array.Copy(seed, 0, dummy, 0, _mdLength);
            OTSSeed = _gmssRandom.NextSeed(dummy);
            _Ots = new WinternitzOTSignature(OTSSeed, GetDigest(_gmssPS.DigestEngine), _gmssPS.WinternitzParameter[_numLayer - 1]);

            byte[][][] helpCurrentAuthPaths = gmssPrivateKey.CurrentAuthPaths;
            _currentAuthPaths = new byte[_numLayer][][];

            // copy the main tree authentication path
            for (int j = 0; j < _numLayer; j++)
            {
                _currentAuthPaths[j] = ArrayUtils.CreateJagged<byte[][]>(helpCurrentAuthPaths[j].Length, _mdLength);
                for (int i = 0; i < helpCurrentAuthPaths[j].Length; i++)
                    Array.Copy(helpCurrentAuthPaths[j][i], 0, _currentAuthPaths[j][i], 0, _mdLength);
            }

            // copy index
            _index = new int[_numLayer];
            Array.Copy(gmssPrivateKey.Index, 0, _index, 0, _numLayer);

            // copy subtreeRootSig
            byte[] helpSubtreeRootSig;
            _subtreeRootSig = new byte[_numLayer - 1][];
            for (int i = 0; i < _numLayer - 1; i++)
            {
                helpSubtreeRootSig = gmssPrivateKey.SubtreeRootSig(i);
                _subtreeRootSig[i] = new byte[helpSubtreeRootSig.Length];
                Array.Copy(helpSubtreeRootSig, 0, _subtreeRootSig[i], 0, helpSubtreeRootSig.Length);
            }

            if (gmssPrivateKey.GetCurrentIndex(0) >= gmssPrivateKey.GetNumLeafs(0))
                gmssPrivateKey.IsUsed = true;
        }
Esempio n. 5
0
        /// <summary>
        /// Computes the upcoming currentAuthpath of <c>layer</c> using the revisited authentication path computation of Dahmen/Schneider 2008
        /// </summary>
        /// 
        /// <param name="Layer">The actual layer</param>
        private void ComputeAuthPaths(int Layer)
        {
            int Phi = _index[Layer];
            int H = _heightOfTrees[Layer];
            int K = _K[Layer];

            // update all nextSeeds for seed scheduling
            for (int i = 0; i < H - K; i++)
                _currentTreehash[Layer][i].UpdateNextSeed(_gmssRandom);

            // STEP 1 of Algorithm
            int Tau = HeightOfPhi(Phi);
            byte[] OTSseed = new byte[_mdLength];
            OTSseed = _gmssRandom.NextSeed(_currentSeeds[Layer]);

            // STEP 2 of Algorithm
            // if phi's parent on height tau + 1 if left node, store auth_tau in keep_tau
            int L = (IntUtils.URShift(Phi, (Tau + 1))) & 1;
            byte[] tempKeep = new byte[_mdLength];
            // store the keep node not in keep[layer][tau/2] because it might be in use
            // wait until the space is freed in step 4a
            if (Tau < H - 1 && L == 0)
                Array.Copy(_currentAuthPaths[Layer][Tau], 0, tempKeep, 0, _mdLength);

            byte[] help = new byte[_mdLength];
            // STEP 3 of Algorithm
            // if phi is left child, compute and store leaf for next currentAuthPath path,
            // (obtained by veriying current signature)
            if (Tau == 0)
            {
                // leaf calc
                if (Layer == _numLayer - 1)
                {
                    // lowest layer computes the necessary leaf completely at this time
                    WinternitzOTSignature ots = new WinternitzOTSignature(OTSseed, GetDigest(_msgDigestType), _otsIndex[Layer]);
                    help = ots.GetPublicKey();
                }
                else
                {
                    // other layers use the precomputed leafs in nextNextLeaf
                    byte[] dummy = new byte[_mdLength];
                    Array.Copy(_currentSeeds[Layer], 0, dummy, 0, _mdLength);
                    _gmssRandom.NextSeed(dummy);
                    help = _upperLeaf[Layer].GetLeaf();
                    _upperLeaf[Layer].InitLeafCalc(dummy);
                }
                Array.Copy(help, 0, _currentAuthPaths[Layer][0], 0, _mdLength);
            }
            else
            {
                // STEP 4a of Algorithm
                // get new left currentAuthPath node on height tau
                byte[] toBeHashed = new byte[_mdLength << 1];
                Array.Copy(_currentAuthPaths[Layer][Tau - 1], 0, toBeHashed, 0, _mdLength);
                // free the shared keep[layer][tau/2]
                Array.Copy(_keep[Layer][(int)Math.Floor((decimal)(Tau - 1) / 2)], 0, toBeHashed, _mdLength, _mdLength);
                _msgDigestTrees.BlockUpdate(toBeHashed, 0, toBeHashed.Length);
                _currentAuthPaths[Layer][Tau] = new byte[_msgDigestTrees.DigestSize];
                _msgDigestTrees.DoFinal(_currentAuthPaths[Layer][Tau], 0);

                // STEP 4b and 4c of Algorithm
                // copy right nodes to currentAuthPath on height 0..Tau-1
                for (int i = 0; i < Tau; i++)
                {
                    // STEP 4b of Algorithm
                    // 1st: copy from treehashs
                    if (i < H - K)
                    {
                        if (_currentTreehash[Layer][i].IsFinished())
                        {
                            Array.Copy(_currentTreehash[Layer][i].GetFirstNode(), 0, _currentAuthPaths[Layer][i], 0, _mdLength);
                            _currentTreehash[Layer][i].Destroy();
                        }
                    }

                    // 2nd: copy precomputed values from Retain
                    if (i < H - 1 && i >= H - K)
                    {
                        if (_currentRetain[Layer][i - (H - K)].Count > 0)
                        {
                            // pop element from retain
                            Array.Copy(_currentRetain[Layer][i - (H - K)][_currentRetain[Layer][i - (H - K)].Count - 1], 0, _currentAuthPaths[Layer][i], 0, _mdLength);
                            _currentRetain[Layer][i - (H - K)].RemoveAt(_currentRetain[Layer][i - (H - K)].Count - 1);
                        }
                    }

                    // STEP 4c of Algorithm initialize new stack at heights 0..Tau-1
                    if (i < H - K)
                    {
                        // create stacks anew
                        int startPoint = Phi + 3 * (1 << i);
                        if (startPoint < _numLeafs[Layer])
                            _currentTreehash[Layer][i].Initialize();
                    }
                }
            }

            // now keep space is free to use
            if (Tau < H - 1 && L == 0)
            {
                Array.Copy(tempKeep, 0, _keep[Layer][(int)Math.Floor((decimal)Tau / 2)], 0, _mdLength);
            }

            // only update empty stack at height h if all other stacks have
            // tailnodes with height >h
            // finds active stack with lowest node height, choses lower index in
            // case of tie on the lowest layer leafs must be computed at once, no precomputation
            // is possible. So all treehash updates are done at once here
            if (Layer == _numLayer - 1)
            {
                for (int tmp = 1; tmp <= (H - K) / 2; tmp++)
                {
                    // index of the treehash instance that receives the next update
                    int minTreehash = GetMinTreehashIndex(Layer);

                    // if active treehash is found update with a leaf
                    if (minTreehash >= 0)
                    {
                        try
                        {
                            byte[] seed = new byte[_mdLength];
                            Array.Copy(_currentTreehash[Layer][minTreehash].GetSeedActive(), 0, seed, 0, _mdLength);
                            byte[] seed2 = _gmssRandom.NextSeed(seed);
                            WinternitzOTSignature ots = new WinternitzOTSignature(seed2, GetDigest(_msgDigestType), _otsIndex[Layer]);
                            byte[] leaf = ots.GetPublicKey();
                            _currentTreehash[Layer][minTreehash].Update(_gmssRandom, leaf);
                        }
                        catch
                        {
                        }
                    }
                }
            }
            else
            {
                // on higher layers the updates are done later
                _minTreehash[Layer] = GetMinTreehashIndex(Layer);
            }
        }