/// <summary> /// This constructor regenerates a prior GMSSLeaf object /// </summary> /// /// <param name="Digest">The hash function</param> /// <param name="OtsIndex">The status bytes</param> /// <param name="NumLeafs">The status ints</param> public GMSSLeaf(IDigest Digest, byte[][] OtsIndex, int[] NumLeafs) { _ctr1 = NumLeafs[0]; _ctr2 = NumLeafs[1]; _steps = NumLeafs[2]; _W = NumLeafs[3]; _msgDigestOTS = Digest; _gmssRandom = new GMSSRandom(_msgDigestOTS); // calulate keysize for private key and the help array _mdsize = _msgDigestOTS.DigestSize; int mdsizeBit = _mdsize << 3; int messagesize = (int)Math.Ceiling((double)(mdsizeBit) / (double)_W); int checksumsize = GetLog((messagesize << _W) + 1); _keysize = messagesize + (int)Math.Ceiling((double)checksumsize / (double)_W); _twoPowerW = 1 << _W; // initialize arrays _privateKeyOTS = OtsIndex[0]; _seed = OtsIndex[1]; _concHashs = OtsIndex[2]; _leaf = OtsIndex[3]; }
/// <summary> /// The constructor generates an OTS key pair, using <c>seed0</c> and the PRNG /// </summary> /// /// <param name="Seed">The seed for the PRGN</param> /// <param name="Digest">The used hash function</param> /// <param name="W">The Winternitz parameter</param> public WinternitzOTSignature(byte[] Seed, IDigest Digest, int W) { _W = W; _msgDigestOTS = Digest; _gmssRandom = new GMSSRandom(_msgDigestOTS); // calulate keysize for private and public key and also the help array _mdsize = _msgDigestOTS.DigestSize; int mdsizeBit = _mdsize << 3; _msgSize = (int)Math.Ceiling((double)(mdsizeBit) / (double)W); _ckmSize = GetLog((_msgSize << W) + 1); _keysize = _msgSize + (int)Math.Ceiling((double)_ckmSize / (double)W); // define the private key messagesize _privateKeyOTS = ArrayUtils.CreateJagged<byte[][]>(_keysize, _mdsize); // gmssRandom.setSeed(seed0); byte[] dummy = new byte[_mdsize]; Array.Copy(Seed, 0, dummy, 0, dummy.Length); // generate random bytes and assign them to the private key for (int i = 0; i < _keysize; i++) _privateKeyOTS[i] = _gmssRandom.NextSeed(dummy); }
/// <summary> /// This constructor regenerates a prior GMSSRootSig object used by the GMSSPrivateKeyASN.1 class /// </summary> /// /// <param name="Digest">The hash function</param> /// <param name="StatByte">The status byte array</param> /// <param name="StatInt">The status int array</param> public GMSSRootSig(IDigest Digest, byte[][] StatByte, int[] StatInt) { _msgDigestOTS = Digest; _gmssRand = new GMSSRandom(_msgDigestOTS); _Counter = StatInt[0]; _testCtr = StatInt[1]; _iI = StatInt[2]; _R = StatInt[3]; _steps = StatInt[4]; _keySize = StatInt[5]; _height = StatInt[6]; _W = StatInt[7]; _chkSum = StatInt[8]; _mdSize = _msgDigestOTS.DigestSize; _K = (1 << _W) - 1; int mdsizeBit = _mdSize << 3; _msgSize = (int)Math.Ceiling((double)(mdsizeBit) / (double)_W); _privateKeyOTS = StatByte[0]; _otsSeed = StatByte[1]; _msgHash = StatByte[2]; _sgnCode = StatByte[3]; _test8 = ((StatByte[4][0] & 0xff)) | ((long)(StatByte[4][1] & 0xff) << 8) | ((long)(StatByte[4][2] & 0xff) << 16) | ((long)(StatByte[4][3] & 0xff)) << 24 | ((long)(StatByte[4][4] & 0xff)) << 32 | ((long)(StatByte[4][5] & 0xff)) << 40 | ((long)(StatByte[4][6] & 0xff)) << 48 | ((long)(StatByte[4][7] & 0xff)) << 56; _big8 = ((StatByte[4][8] & 0xff)) | ((long)(StatByte[4][9] & 0xff) << 8) | ((long)(StatByte[4][10] & 0xff) << 16) | ((long)(StatByte[4][11] & 0xff)) << 24 | ((long)(StatByte[4][12] & 0xff)) << 32 | ((long)(StatByte[4][13] & 0xff)) << 40 | ((long)(StatByte[4][14] & 0xff)) << 48 | ((long)(StatByte[4][15] & 0xff)) << 56; }
/// <summary> /// The constructor generates an OTS key pair, using <c>seed0</c> and the PRNG /// </summary> /// /// <param name="Seed">The seed for the PRGN</param> /// <param name="Digest">The used hash function</param> /// <param name="W">The Winternitz parameter</param> public WinternitzOTSignature(byte[] Seed, IDigest Digest, int W) { _W = W; _msgDigestOTS = Digest; _gmssRandom = new GMSSRandom(_msgDigestOTS); // calulate keysize for private and public key and also the help array _mdsize = _msgDigestOTS.DigestSize; int mdsizeBit = _mdsize << 3; _msgSize = (int)Math.Ceiling((double)(mdsizeBit) / (double)W); _ckmSize = GetLog((_msgSize << W) + 1); m_keySize = _msgSize + (int)Math.Ceiling((double)_ckmSize / (double)W); // define the private key messagesize _privateKeyOTS = ArrayUtils.CreateJagged <byte[][]>(m_keySize, _mdsize); // gmssRandom.setSeed(seed0); byte[] dummy = new byte[_mdsize]; Array.Copy(Seed, 0, dummy, 0, dummy.Length); // generate random bytes and assign them to the private key for (int i = 0; i < m_keySize; i++) { _privateKeyOTS[i] = _gmssRandom.NextSeed(dummy); } }
/// <summary> /// Initialize this class /// </summary> /// /// <param name="CipherParams">The GMSS cipher used to encrypt the hash</param> public GMSSSign(GMSSParameters CipherParams) { _gmssPS = CipherParams; _msgDigestTrees = GetDigest(CipherParams.DigestEngine); _msgDigestOTS = _msgDigestTrees; _mdLength = _msgDigestTrees.DigestSize; _gmssRandom = new GMSSRandom(_msgDigestTrees); }
/// <summary> /// Copy Constructor /// </summary> /// /// <param name="PrivateKey">The GMSSPrivateKey to copy</param> private GMSSPrivateKey(GMSSPrivateKey PrivateKey) { _index = ArrayUtils.Clone(PrivateKey._index); _currentSeeds = GMSSUtil.Clone(PrivateKey._currentSeeds); _nextNextSeeds = GMSSUtil.Clone(PrivateKey._nextNextSeeds); _currentAuthPaths = GMSSUtil.Clone(PrivateKey._currentAuthPaths); _nextAuthPaths = GMSSUtil.Clone(PrivateKey._nextAuthPaths); _keep = GMSSUtil.Clone(PrivateKey._keep); _currentTreehash = PrivateKey._currentTreehash; _nextTreehash = PrivateKey._nextTreehash; _currentStack = PrivateKey._currentStack; _nextStack = PrivateKey._nextStack; _currentRetain = PrivateKey._currentRetain; _nextRetain = PrivateKey._nextRetain; _nextNextLeaf = PrivateKey._nextNextLeaf; //N _upperLeaf = PrivateKey._upperLeaf; //N _upperTreehashLeaf = PrivateKey._upperTreehashLeaf; //N _minTreehash = PrivateKey._minTreehash; //N _nextRoot = GMSSUtil.Clone(PrivateKey._nextRoot); _nextNextRoot = PrivateKey._nextNextRoot; //N _currentRootSig = PrivateKey._currentRootSig; _nextRootSig = PrivateKey._nextRootSig; //N _gmssPS = PrivateKey._gmssPS; _msgDigestType = PrivateKey._msgDigestType; _heightOfTrees = PrivateKey._heightOfTrees; _otsIndex = PrivateKey._otsIndex; _K = PrivateKey._K; _numLayer = PrivateKey._numLayer; _msgDigestTrees = PrivateKey._msgDigestTrees; _mdLength = PrivateKey._mdLength; _gmssRandom = PrivateKey._gmssRandom; _numLeafs = PrivateKey._numLeafs; }
/// <summary> /// /// </summary> /// /// <param name="Index">The tree indices</param> /// <param name="CurrentSeeds">A seed for the generation of private OTS keys for the current subtrees</param> /// <param name="NextNextSeeds">A seed for the generation of private OTS keys for the next subtrees</param> /// <param name="CurrentAuthPaths">Array of current authentication paths</param> /// <param name="NextAuthPaths">Array of next authentication paths</param> /// <param name="Keep">Keep array for the authPath algorithm</param> /// <param name="CurrentTreehash">Treehash for authPath algorithm of current tree</param> /// <param name="NextTreehash">Treehash for authPath algorithm of next tree (TREE+)</param> /// <param name="CurrentStack">Shared stack for authPath algorithm of current tree</param> /// <param name="NextStack">Shared stack for authPath algorithm of next tree (TREE+)</param> /// <param name="CurrentRetain">Retain stack for authPath algorithm of current tree</param> /// <param name="NextRetain">Retain stack for authPath algorithm of next tree (TREE+)</param> /// <param name="NextNextLeaf">Array of upcoming leafs of the tree after next (LEAF++) of each layer</param> /// <param name="UpperLeaf">Needed for precomputation of upper nodes</param> /// <param name="UpperTreehashLeaf">Needed for precomputation of upper treehash nodes</param> /// <param name="MinTreehash">Index of next treehash instance to receive an update</param> /// <param name="NextRoot">The roots of the next trees (ROOT+)</param> /// <param name="NextNextRoot">The roots of the tree after next (ROOT++)</param> /// <param name="CurrentRootSig">Array of signatures of the roots of the current subtrees (SIG)</param> /// <param name="NextRootSig">Array of signatures of the roots of the next subtree (SIG+)</param> /// <param name="ParameterSet">The GMSS Parameterset</param> /// <param name="Digest">The digest type</param> internal GMSSPrivateKey(int[] Index, byte[][] CurrentSeeds, byte[][] NextNextSeeds, byte[][][] CurrentAuthPaths, byte[][][] NextAuthPaths, byte[][][] Keep, Treehash[][] CurrentTreehash, Treehash[][] NextTreehash, List<byte[]>[] CurrentStack, List<byte[]>[] NextStack, List<byte[]>[][] CurrentRetain, List<byte[]>[][] NextRetain, GMSSLeaf[] NextNextLeaf, GMSSLeaf[] UpperLeaf, GMSSLeaf[] UpperTreehashLeaf, int[] MinTreehash, byte[][] NextRoot, GMSSRootCalc[] NextNextRoot, byte[][] CurrentRootSig, GMSSRootSig[] NextRootSig, GMSSParameters ParameterSet, Digests Digest) { _msgDigestType = Digest; // construct message digest _msgDigestTrees = GetDigest(Digest); _mdLength = _msgDigestTrees.DigestSize; // Parameter _gmssPS = ParameterSet; _otsIndex = ParameterSet.WinternitzParameter; _K = ParameterSet.K; _heightOfTrees = ParameterSet.HeightOfTrees; // initialize numLayer _numLayer = _gmssPS.NumLayers; // initialize index if null if (Index == null) { _index = new int[_numLayer]; for (int i = 0; i < _numLayer; i++) _index[i] = 0; } else { _index = Index; } _currentSeeds = CurrentSeeds; _nextNextSeeds = NextNextSeeds; _currentAuthPaths = CurrentAuthPaths; _nextAuthPaths = NextAuthPaths; // initialize keep if null if (Keep == null) { _keep = new byte[_numLayer][][]; for (int i = 0; i < _numLayer; i++) _keep[i] = ArrayUtils.CreateJagged<byte[][]>((int)Math.Floor((decimal)_heightOfTrees[i] / 2), _mdLength); } else { _keep = Keep; } // initialize stack if null if (CurrentStack == null) { _currentStack = new List<byte[]>[_numLayer]; for (int i = 0; i < _numLayer; i++) _currentStack[i] = new List<byte[]>(); } else { _currentStack = CurrentStack; } // initialize nextStack if null if (NextStack == null) { _nextStack = new List<byte[]>[_numLayer - 1]; for (int i = 0; i < _numLayer - 1; i++) _nextStack[i] = new List<byte[]>(); } else { _nextStack = NextStack; } _currentTreehash = CurrentTreehash; _nextTreehash = NextTreehash; _currentRetain = CurrentRetain; _nextRetain = NextRetain; _nextRoot = NextRoot; if (NextNextRoot == null) { NextNextRoot = new GMSSRootCalc[_numLayer - 1]; for (int i = 0; i < _numLayer - 1; i++) NextNextRoot[i] = new GMSSRootCalc(_heightOfTrees[i + 1], _K[i + 1], GetDigest(Digest)); } else { _nextNextRoot = NextNextRoot; } _currentRootSig = CurrentRootSig; // calculate numLeafs _numLeafs = new int[_numLayer]; for (int i = 0; i < _numLayer; i++) _numLeafs[i] = 1 << _heightOfTrees[i]; // construct PRNG _gmssRandom = new GMSSRandom(_msgDigestTrees); if (_numLayer > 1) { // construct the nextNextLeaf (LEAFs++) array for upcoming leafs in // tree after next (TREE++) if (NextNextLeaf == null) { _nextNextLeaf = new GMSSLeaf[_numLayer - 2]; for (int i = 0; i < _numLayer - 2; i++) _nextNextLeaf[i] = new GMSSLeaf(GetDigest(Digest), _otsIndex[i + 1], _numLeafs[i + 2], _nextNextSeeds[i]); } else { _nextNextLeaf = NextNextLeaf; } } else { _nextNextLeaf = new GMSSLeaf[0]; } // construct the upperLeaf array for upcoming leafs in tree over the // actual if (UpperLeaf == null) { _upperLeaf = new GMSSLeaf[_numLayer - 1]; for (int i = 0; i < _numLayer - 1; i++) _upperLeaf[i] = new GMSSLeaf(GetDigest(Digest), _otsIndex[i], _numLeafs[i + 1], _currentSeeds[i]); } else { _upperLeaf = UpperLeaf; } // construct the leafs for upcoming leafs in treehashs in tree over the actual if (UpperTreehashLeaf == null) { _upperTreehashLeaf = new GMSSLeaf[_numLayer - 1]; for (int i = 0; i < _numLayer - 1; i++) _upperTreehashLeaf[i] = new GMSSLeaf(GetDigest(Digest), _otsIndex[i], _numLeafs[i + 1]); } else { _upperTreehashLeaf = UpperTreehashLeaf; } if (MinTreehash == null) { _minTreehash = new int[_numLayer - 1]; for (int i = 0; i < _numLayer - 1; i++) _minTreehash[i] = -1; } else { _minTreehash = MinTreehash; } // construct the nextRootSig (RootSig++) byte[] dummy = new byte[_mdLength]; byte[] OTSseed = new byte[_mdLength]; if (NextRootSig == null) { _nextRootSig = new GMSSRootSig[_numLayer - 1]; for (int i = 0; i < _numLayer - 1; i++) { Array.Copy(CurrentSeeds[i], 0, dummy, 0, _mdLength); _gmssRandom.NextSeed(dummy); OTSseed = _gmssRandom.NextSeed(dummy); _nextRootSig[i] = new GMSSRootSig(GetDigest(Digest), _otsIndex[i], _heightOfTrees[i + 1]); _nextRootSig[i].InitSign(OTSseed, NextRoot[i]); } } else { _nextRootSig = NextRootSig; } }
private void Dispose(bool Disposing) { if (!_isDisposed && Disposing) { try { if (_index != null) { Array.Clear(_index, 0, _index.Length); _index = null; } if (_currentSeeds != null) { Array.Clear(_currentSeeds, 0, _currentSeeds.Length); _currentSeeds = null; } if (_nextNextSeeds != null) { Array.Clear(_nextNextSeeds, 0, _nextNextSeeds.Length); _nextNextSeeds = null; } if (_currentAuthPaths != null) { Array.Clear(_currentAuthPaths, 0, _currentAuthPaths.Length); _currentAuthPaths = null; } if (_nextAuthPaths != null) { Array.Clear(_nextAuthPaths, 0, _nextAuthPaths.Length); _nextAuthPaths = null; } if (_currentTreehash != null) { for (int i = 0; i < _currentTreehash.Length; i++) { for (int j = 0; j < _currentTreehash[i].Length; j++) _currentTreehash[i][j].Dispose(); } _nextAuthPaths = null; } if (_nextTreehash != null) { for (int i = 0; i < _nextTreehash.Length; i++) { for (int j = 0; j < _nextTreehash[i].Length; j++) _nextTreehash[i][j].Dispose(); } _nextAuthPaths = null; } if (_currentStack != null) { Array.Clear(_currentStack, 0, _currentStack.Length); _currentStack = null; } if (_nextStack != null) { Array.Clear(_nextStack, 0, _nextStack.Length); _nextStack = null; } if (_currentRetain != null) { Array.Clear(_currentRetain, 0, _currentRetain.Length); _currentRetain = null; } if (_nextRetain != null) { Array.Clear(_nextRetain, 0, _nextRetain.Length); _nextRetain = null; } if (_keep != null) { Array.Clear(_keep, 0, _keep.Length); _keep = null; } if (_nextNextLeaf != null) { for (int i = 0; i < _nextNextLeaf.Length; i++) _nextNextLeaf[i].Dispose(); _nextNextLeaf = null; } if (_upperLeaf != null) { for (int i = 0; i < _upperLeaf.Length; i++) _upperLeaf[i].Dispose(); _upperLeaf = null; } if (_upperTreehashLeaf != null) { for (int i = 0; i < _upperTreehashLeaf.Length; i++) _upperTreehashLeaf[i].Dispose(); _upperTreehashLeaf = null; } if (_minTreehash != null) { Array.Clear(_minTreehash, 0, _minTreehash.Length); _minTreehash = null; } if (_gmssPS != null) { _gmssPS.Dispose(); _gmssPS = null; } if (_nextRoot != null) { Array.Clear(_nextRoot, 0, _nextRoot.Length); _nextRoot = null; } if (_nextNextRoot != null) { for (int i = 0; i < _nextNextRoot.Length; i++) _nextNextRoot[i].Dispose(); _nextNextRoot = null; } if (_currentRootSig != null) { Array.Clear(_currentRootSig, 0, _currentRootSig.Length); _currentRootSig = null; } if (_nextRootSig != null) { for (int i = 0; i < _nextRootSig.Length; i++) _nextRootSig[i].Dispose(); _nextRootSig = null; } if (_heightOfTrees != null) { Array.Clear(_heightOfTrees, 0, _heightOfTrees.Length); _heightOfTrees = null; } if (_otsIndex != null) { Array.Clear(_otsIndex, 0, _otsIndex.Length); _otsIndex = null; } if (_K != null) { Array.Clear(_K, 0, _K.Length); _K = null; } if (_numLeafs != null) { Array.Clear(_numLeafs, 0, _numLeafs.Length); _numLeafs = null; } if (_msgDigestTrees != null) { _msgDigestTrees.Dispose(); _msgDigestTrees = null; } if (_gmssRandom != null) { _gmssRandom.Dispose(); _gmssRandom = null; } _mdLength = 0; _numLayer = 0; } catch { } _isDisposed = true; } }
private void Dispose(bool Disposing) { if (!_isDisposed && Disposing) { try { if (_msgDigestOTS != null) { _msgDigestOTS.Dispose(); _msgDigestOTS = null; } if (_privateKeyOTS != null) { Array.Clear(_privateKeyOTS, 0, _privateKeyOTS.Length); _privateKeyOTS = null; } if (_msgHash != null) { Array.Clear(_msgHash, 0, _msgHash.Length); _msgHash = null; } if (_sgnCode != null) { Array.Clear(_sgnCode, 0, _sgnCode.Length); _sgnCode = null; } if (_gmssRand != null) { _gmssRand.Dispose(); _gmssRand = null; } if (_otsSeed != null) { Array.Clear(_otsSeed, 0, _otsSeed.Length); _otsSeed = null; } _mdSize = 0; _keySize = 0; _W = 0; _msgSize = 0; _K = 0; _R = 0; _testCtr = 0; _Counter = 0; _iI = 0; _test8 = 0; _big8 = 0; _steps = 0; _chkSum = 0; _height = 0; } catch { } _isDisposed = true; } }
/// <summary> /// Use an initialized prng to generate the key; use this constructor with an Rng that requires pre-initialization, i.e. PBPrng /// </summary> /// /// <param name="CiphersParams">The GMSSParameters instance containing the cipher settings</param> /// <param name="RngEngine">An initialized random generator instance</param> public GMSSKeyGenerator(GMSSParameters CiphersParams, IRandom RngEngine) { _gmssParams = CiphersParams; _msgDigestType = CiphersParams.DigestEngine; _rndEngineType = _gmssParams.RandomEngine; _msDigestTree = GetDigest(CiphersParams.DigestEngine); // construct randomizer _gmssRand = new GMSSRandom(_msDigestTree); // set mdLength _mdLength = _msDigestTree.DigestSize; // construct Random for initial seed generation _rndEngine = RngEngine; Initialize(); }
private void Dispose(bool Disposing) { if (!_isDisposed && Disposing) { try { if (_msgDigestOTS != null) { _msgDigestOTS.Dispose(); _msgDigestOTS = null; } if (_gmssRandom != null) { _gmssRandom.Dispose(); _gmssRandom = null; } if (_leaf != null) { Array.Clear(_leaf, 0, _leaf.Length); _leaf = null; } if (_concHashs != null) { Array.Clear(_concHashs, 0, _concHashs.Length); _concHashs = null; } if (_seed != null) { Array.Clear(_seed, 0, _seed.Length); _seed = null; } if (_privateKeyOTS != null) { Array.Clear(_privateKeyOTS, 0, _privateKeyOTS.Length); _privateKeyOTS = null; } _mdsize = 0; _keysize = 0; _ctr1 = 0; _ctr2 = 0; _twoPowerW = 0; _W = 0; _steps = 0; } catch { } _isDisposed = true; } }
private GMSSLeaf(GMSSLeaf original) { _msgDigestOTS = original._msgDigestOTS; _mdsize = original._mdsize; _keysize = original._keysize; _gmssRandom = original._gmssRandom; _leaf = ArrayUtils.Clone(original._leaf); _concHashs = ArrayUtils.Clone(original._concHashs); _ctr1 = original._ctr1; _ctr2 = original._ctr2; _twoPowerW = original._twoPowerW; _W = original._W; _steps = original._steps; _seed = ArrayUtils.Clone(original._seed); _privateKeyOTS = ArrayUtils.Clone(original._privateKeyOTS); }
/// <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); }
/// <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 (!_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; }
private void Dispose(bool Disposing) { if (!_isDisposed && Disposing) { try { if (_msgDigestTrees != null) { _msgDigestTrees.Dispose(); _msgDigestTrees = null; } if (_gmssRandom != null) { _gmssRandom.Dispose(); _gmssRandom = null; } if (_index != null) { Array.Clear(_index, 0, _index.Length); _index = null; } if (_currentAuthPaths != null) { Array.Clear(_currentAuthPaths, 0, _currentAuthPaths.Length); _currentAuthPaths = null; } if (_subtreeRootSig != null) { Array.Clear(_subtreeRootSig, 0, _subtreeRootSig.Length); _subtreeRootSig = null; } _mdLength = 0; _numLayer = 0; } catch { } _isDisposed = true; } }
/// <summary> /// Initialize this class /// </summary> /// /// <param name="CiphersParams">The GMSSParameters instance containing the cipher settings</param> /// /// <exception cref="CryptoAsymmetricSignException">Thrown if a Prng that requires pre-initialization is specified; (wrong constructor)</exception> public GMSSKeyGenerator(GMSSParameters CiphersParams) { if (CiphersParams.RandomEngine == Prngs.PBPrng) throw new CryptoAsymmetricSignException("GMSSKeyGenerator:Ctor", "Passphrase based digest and CTR generators must be pre-initialized, use the other constructor!", new ArgumentException()); _gmssParams = CiphersParams; _msgDigestType = CiphersParams.DigestEngine; _rndEngineType = _gmssParams.RandomEngine; _msDigestTree = GetDigest(CiphersParams.DigestEngine); // construct randomizer _gmssRand = new GMSSRandom(_msDigestTree); // set mdLength _mdLength = _msDigestTree.DigestSize; // construct Random for initial seed generation _rndEngine = GetPrng(_rndEngineType); Initialize(); }
/// <summary> /// The constructor precomputes some needed variables for distributed leaf calculation /// </summary> /// /// <param name="Digest">The hash function</param> /// <param name="W">The winterniz parameter of that tree the leaf is computed for</param> /// <param name="NumLeafs">The number of leafs of the tree from where the distributed computation is called</param> /// <param name="Seed">The hash seed value</param> public GMSSLeaf(IDigest Digest, int W, int NumLeafs, byte[] Seed) { _W = W; _msgDigestOTS = Digest; _gmssRandom = new GMSSRandom(_msgDigestOTS); // calulate keysize for private key and the help array _mdsize = _msgDigestOTS.DigestSize; int mdsizeBit = _mdsize << 3; int messagesize = (int)Math.Ceiling((double)(mdsizeBit) / (double)W); int checksumsize = GetLog((messagesize << W) + 1); _keysize = messagesize + (int)Math.Ceiling((double)checksumsize / (double)W); _twoPowerW = 1 << W; // calculate steps ((2^w)-1)*keysize + keysize + 1 / (2^h -1) _steps = (int)Math.Ceiling((double)(((1 << W) - 1) * _keysize + 1 + _keysize) / (double)(NumLeafs)); // initialize arrays _seed = new byte[_mdsize]; _leaf = new byte[_mdsize]; _privateKeyOTS = new byte[_mdsize]; _concHashs = new byte[_mdsize * _keysize]; InitLeafCalc(Seed); }
private void Dispose(bool Disposing) { if (!_isDisposed && Disposing) { try { if (_gmssRand != null) { _gmssRand.Dispose(); _gmssRand = null; } if (_rndEngine != null) { _rndEngine.Dispose(); _rndEngine = null; } if (_msDigestTree != null) { _msDigestTree.Dispose(); _msDigestTree = null; } if (_currentSeeds != null) { Array.Clear(_currentSeeds, 0, _currentSeeds.Length); _currentSeeds = null; } if (_nextNextSeeds != null) { Array.Clear(_nextNextSeeds, 0, _nextNextSeeds.Length); _nextNextSeeds = null; } if (_currentRootSigs != null) { Array.Clear(_currentRootSigs, 0, _currentRootSigs.Length); _currentRootSigs = null; } if (_currentRootSigs != null) { Array.Clear(_currentRootSigs, 0, _currentRootSigs.Length); _currentRootSigs = null; } _mdLength = 0; } catch { } _isDisposed = true; } }
/// <summary> /// The constructor generates the PRNG and initializes some variables /// </summary> /// /// <param name="Digest">The hash function</param> /// <param name="W">The winternitz parameter</param> /// <param name="Height">The heigth of the tree</param> public GMSSRootSig(IDigest Digest, int W, int Height) { _msgDigestOTS = Digest; _gmssRand = new GMSSRandom(_msgDigestOTS); _mdSize = _msgDigestOTS.DigestSize; _W = W; _height = Height; _K = (1 << W) - 1; int mdsizeBit = _mdSize << 3; _msgSize = (int)Math.Ceiling((double)(mdsizeBit) / (double)W); }