예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <summary>
        /// This constructor regenerates a prior treehash object
        /// </summary>
        ///
        /// <param name="Digest">The hash function</param>
        /// <param name="StatByte">The status bytes</param>
        /// <param name="StatInt">The  status ints</param>
        /// <param name="TreeH">The tree hash</param>
        /// <param name="NodeRet">The retained nodes</param>
        public GMSSRootCalc(IDigest Digest, byte[][] StatByte, int[] StatInt, Treehash[] TreeH, List <byte[]>[] NodeRet)
        {
            _msgDigestTree = Digest;
            // decode statInt
            _heightOfTree     = StatInt[0];
            _mdLength         = StatInt[1];
            m_K               = StatInt[2];
            _indexForNextSeed = StatInt[3];
            _heightOfNextSeed = StatInt[4];

            if (StatInt[5] == 1)
            {
                _isFinished = true;
            }
            else
            {
                _isFinished = false;
            }

            if (StatInt[6] == 1)
            {
                m_isInitialized = true;
            }
            else
            {
                m_isInitialized = false;
            }

            int tailLength = StatInt[7];

            _ndeIndex = new int[_heightOfTree];
            for (int i = 0; i < _heightOfTree; i++)
            {
                _ndeIndex[i] = StatInt[8 + i];
            }

            _heightOfNodes = new List <int>();
            for (int i = 0; i < tailLength; i++)
            {
                _heightOfNodes.Add(StatInt[8 + _heightOfTree + i]);
            }

            // decode statByte
            _treeRoot = StatByte[0];

            _authPath = ArrayUtils.CreateJagged <byte[][]>(_heightOfTree, _mdLength);
            for (int i = 0; i < _heightOfTree; i++)
            {
                _authPath[i] = StatByte[1 + i];
            }

            _tailStack = new List <byte[]>();
            for (int i = 0; i < tailLength; i++)
            {
                _tailStack.Add(StatByte[1 + _heightOfTree + i]);
            }

            // decode treeH
            _treehash = GMSSUtil.Clone(TreeH);

            // decode ret
            _ndeRetain = GMSSUtil.Clone(NodeRet);
        }
예제 #3
0
 /// <summary>
 /// Returns the retain stacks storing all right nodes near to the root
 /// </summary>
 ///
 /// <returns>The retain stacks storing all right nodes near to the root</returns>
 public List <byte[]>[] GetRetain()
 {
     return(GMSSUtil.Clone(_ndeRetain));
 }
예제 #4
0
 /// <summary>
 /// Returns the initial treehash instances, storing value y_3(i)
 /// </summary>
 ///
 /// <returns>The initial treehash instances, storing value y_3(i)</returns>
 public Treehash[] GetTreehash()
 {
     return(GMSSUtil.Clone(_treehash));
 }
예제 #5
0
 /// <summary>
 /// Returns the authentication path of the first leaf of the tree
 /// </summary>
 ///
 /// <returns>The authentication path of the first leaf of the tree</returns>
 public byte[][] GetAuthPath()
 {
     return(GMSSUtil.Clone(_authPath));
 }
예제 #6
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);
        }