Ejemplo n.º 1
0
 /// <summary>
 /// Initialize the distributed leaf calculation reset i,j and compute OTSseed with seed0
 /// </summary>
 ///
 /// <param name="Seed">The starting seed</param>
 public void InitLeafCalc(byte[] Seed)
 {
     _ctr1 = 0;
     _ctr2 = 0;
     byte[] dummy = new byte[_mdsize];
     Array.Copy(Seed, 0, dummy, 0, _seed.Length);
     _seed = _gmssRandom.NextSeed(dummy);
 }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
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)m_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;
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Updates the nextSeed of this treehash instance one step needed for the schedulng of the seeds
 /// </summary>
 ///
 /// <param name="GmssRand">The prng used for the seeds</param>
 public void UpdateNextSeed(GMSSRandom GmssRand)
 {
     GmssRand.NextSeed(_seedNext);
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Calculates one update of the treehash instance, i.e. creates a new leaf and hashes if possible
        /// </summary>
        ///
        /// <param name="GmssRand">An instance of the PRNG</param>
        /// <param name="Leaf">The byte value of the leaf needed for the update</param>
        public void Update(GMSSRandom GmssRand, byte[] Leaf)
        {
            if (_isFinished)
            {
                return;
            }
            if (!m_isInitialized)
            {
                return;
            }

            byte[] help       = new byte[_msgDigestTree.DigestSize];
            int    helpHeight = -1;

            GmssRand.NextSeed(_seedActive);

            // if treehash gets first update
            if (_firstNode == null)
            {
                _firstNode       = Leaf;
                _firstNodeHeight = 0;
            }
            else
            {
                // store the new node in help array, do not push it on the stack
                help       = Leaf;
                helpHeight = 0;

                // hash the nodes on the stack if possible
                while (_tailLength > 0 && helpHeight == ((int)_heightOfNodes[_heightOfNodes.Count - 1]))
                {
                    // put top element of the stack and help node in array 'tobehashed'
                    // and hash them together, put result again in help array
                    byte[] toBeHashed = new byte[_msgDigestTree.DigestSize << 1];

                    // pop element from stack
                    Array.Copy(_tailStack[_tailStack.Count - 1], 0, toBeHashed, 0, _msgDigestTree.DigestSize);
                    _tailStack.RemoveAt(_tailStack.Count - 1);
                    _heightOfNodes.RemoveAt(_heightOfNodes.Count - 1);

                    Array.Copy(help, 0, toBeHashed, _msgDigestTree.DigestSize, _msgDigestTree.DigestSize);
                    _msgDigestTree.BlockUpdate(toBeHashed, 0, toBeHashed.Length);
                    help = new byte[_msgDigestTree.DigestSize];
                    _msgDigestTree.DoFinal(help, 0);

                    // increase help height, stack was reduced by one element
                    helpHeight++;
                    _tailLength--;
                }

                // push the new node on the stack
                _tailStack.Add(help);
                _heightOfNodes.Add(helpHeight);
                _tailLength++;

                // finally check whether the top node on stack and the first node in treehash have same height.
                // If so hash them together and store them in treehash
                if (((int)_heightOfNodes[_heightOfNodes.Count - 1] == _firstNodeHeight))
                {
                    byte[] toBeHashed = new byte[_msgDigestTree.DigestSize << 1];
                    Array.Copy(_firstNode, 0, toBeHashed, 0, _msgDigestTree.DigestSize);
                    // pop element from tailStack and copy it into help2 array
                    Array.Copy(_tailStack[_tailStack.Count - 1], 0, toBeHashed, _msgDigestTree.DigestSize, _msgDigestTree.DigestSize);
                    _tailStack.RemoveAt(_tailStack.Count - 1);
                    _heightOfNodes.RemoveAt(_heightOfNodes.Count - 1);
                    // store new element in firstNode, stack is then empty
                    _msgDigestTree.BlockUpdate(toBeHashed, 0, toBeHashed.Length);
                    _firstNode = new byte[_msgDigestTree.DigestSize];
                    _msgDigestTree.DoFinal(_firstNode, 0);
                    _firstNodeHeight++;
                    // empty the stack
                    _tailLength = 0;
                }
            }

            // check if treehash instance is completed
            if (_firstNodeHeight == _maxHeight)
            {
                _isFinished = true;
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Return The one-time signature of the message, generated step by step
        /// </summary>
        private void OneStep()
        {
            if (8 % _W == 0)
            {
                if (_testCtr == 0)
                {
                    // get current OTSprivateKey
                    _privateKeyOTS = _gmssRand.NextSeed(_otsSeed);

                    if (_iI < _mdSize)
                    {
                        // for main message part
                        _testCtr      = _msgHash[_iI] & m_K;
                        _msgHash[_iI] = (byte)(IntUtils.URShift(_msgHash[_iI], _W));
                    }
                    else
                    {
                        // for checksum part
                        _testCtr = _chkSum & m_K;
                        _chkSum  = IntUtils.URShift(_chkSum, _W);
                    }
                }
                else if (_testCtr > 0)
                {
                    // hash the private Key 'test' times (on time each step)
                    _msgDigestOTS.BlockUpdate(_privateKeyOTS, 0, _privateKeyOTS.Length);
                    _privateKeyOTS = new byte[_msgDigestOTS.DigestSize];
                    _msgDigestOTS.DoFinal(_privateKeyOTS, 0);
                    _testCtr--;
                }

                if (_testCtr == 0)
                {
                    // if all hashes done copy result to siganture array
                    Array.Copy(_privateKeyOTS, 0, _sgnCode, _Counter * _mdSize, _mdSize);
                    _Counter++;

                    // raise array index for main massage part
                    if (_Counter % (8 / _W) == 0)
                    {
                        _iI++;
                    }
                }
            }
            else if (_W < 8)
            {
                if (_testCtr == 0)
                {
                    if (_Counter % 8 == 0 && _iI < _mdSize)
                    {
                        // after every 8th "add to signature"-step
                        _big8 = 0;
                        if (_Counter < ((_mdSize / _W) << 3))
                        {
                            // main massage (generate w*8 Bits every time) part
                            for (int j = 0; j < _W; j++)
                            {
                                _big8 ^= (_msgHash[_iI] & 0xff) << (j << 3);
                                _iI++;
                            }
                        }
                        else
                        {
                            // rest of massage part (once)
                            for (int j = 0; j < _mdSize % _W; j++)
                            {
                                _big8 ^= (_msgHash[_iI] & 0xff) << (j << 3);
                                _iI++;
                            }
                        }
                    }

                    // checksum part (once)
                    if (_Counter == _msgSize)
                    {
                        _big8 = _chkSum;
                    }

                    _testCtr = (int)(_big8 & m_K);
                    // generate current OTSprivateKey
                    _privateKeyOTS = _gmssRand.NextSeed(_otsSeed);
                }
                else if (_testCtr > 0)
                {
                    // hash the private Key 'test' times (on time each step)
                    _msgDigestOTS.BlockUpdate(_privateKeyOTS, 0, _privateKeyOTS.Length);
                    _privateKeyOTS = new byte[_msgDigestOTS.DigestSize];
                    _msgDigestOTS.DoFinal(_privateKeyOTS, 0);
                    _testCtr--;
                }
                if (_testCtr == 0)
                {
                    // if all hashes done copy result to siganture array
                    Array.Copy(_privateKeyOTS, 0, _sgnCode, _Counter * _mdSize, _mdSize);
                    _big8 = IntUtils.URShift(_big8, _W);
                    _Counter++;
                }
            }
            else if (_W < 57)
            {
                if (_test8 == 0)
                {
                    int s, f, rest;
                    _big8 = 0;
                    _iI   = 0;
                    rest  = _R % 8;
                    s     = IntUtils.URShift(_R, 3);
                    // message part
                    if (s < _mdSize)
                    {
                        if (_R <= ((_mdSize << 3) - _W))
                        {
                            // first message part
                            _R += _W;
                            f   = IntUtils.URShift((_R + 7), 3);
                        }
                        else
                        {
                            // rest of message part (once)
                            f   = _mdSize;
                            _R += _W;
                        }
                        // generate long 'big8' with minimum w next bits of the message array
                        for (int i = s; i < f; i++)
                        {
                            _big8 ^= (_msgHash[i] & 0xff) << (_iI << 3);
                            _iI++;
                        }
                        // delete bits on the right side, which were used already by the last loop
                        _big8  = IntUtils.URShift(_big8, rest);
                        _test8 = (_big8 & m_K);
                    }
                    // checksum part
                    else
                    {
                        _test8  = (_chkSum & m_K);
                        _chkSum = IntUtils.URShift(_chkSum, _W);
                    }
                    // generate current OTSprivateKey
                    _privateKeyOTS = _gmssRand.NextSeed(_otsSeed);
                }
                else if (_test8 > 0)
                {
                    // hash the private Key 'test' times (on time each step)
                    _msgDigestOTS.BlockUpdate(_privateKeyOTS, 0, _privateKeyOTS.Length);
                    _privateKeyOTS = new byte[_msgDigestOTS.DigestSize];
                    _msgDigestOTS.DoFinal(_privateKeyOTS, 0);
                    _test8--;
                }
                if (_test8 == 0)
                {
                    // if all hashes done copy result to siganture array
                    Array.Copy(_privateKeyOTS, 0, _sgnCode, _Counter * _mdSize, _mdSize);
                    _Counter++;
                }
            }
        }