/// <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); }
private void Dispose(bool Disposing) { if (!m_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; m_keySize = 0; _W = 0; _msgSize = 0; m_K = 0; _R = 0; _testCtr = 0; _Counter = 0; _iI = 0; _test8 = 0; _big8 = 0; _steps = 0; _chkSum = 0; _height = 0; } catch { } m_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; m_K = (1 << W) - 1; int mdsizeBit = _mdSize << 3; _msgSize = (int)Math.Ceiling((double)(mdsizeBit) / (double)W); }
private void Dispose(bool Disposing) { if (!m_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; m_keySize = 0; _ctr1 = 0; _ctr2 = 0; _twoPowerW = 0; _W = 0; _steps = 0; } catch { } m_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; m_rndEngineType = _gmssParams.RandomEngine; _msDigestTree = GetDigest(CiphersParams.DigestEngine); // construct randomizer _gmssRand = new GMSSRandom(_msDigestTree); // set mdLength _mdLength = _msDigestTree.DigestSize; // construct Random for initial seed generation m_rndEngine = RngEngine; Initialize(); }
private void Dispose(bool Disposing) { if (!m_isDisposed && Disposing) { try { if (_gmssRand != null) { _gmssRand.Dispose(); _gmssRand = null; } if (m_rndEngine != null) { m_rndEngine.Dispose(); m_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 { } m_isDisposed = true; } }
private GMSSLeaf(GMSSLeaf original) { _msgDigestOTS = original._msgDigestOTS; _mdsize = original._mdsize; m_keySize = original.m_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> /// 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; m_rndEngineType = _gmssParams.RandomEngine; _msDigestTree = GetDigest(CiphersParams.DigestEngine); // construct randomizer _gmssRand = new GMSSRandom(_msDigestTree); // set mdLength _mdLength = _msDigestTree.DigestSize; // construct Random for initial seed generation m_rndEngine = GetPrng(m_rndEngineType); Initialize(); }
/// <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]; m_keySize = StatInt[5]; _height = StatInt[6]; _W = StatInt[7]; _chkSum = StatInt[8]; _mdSize = _msgDigestOTS.DigestSize; m_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)) | ((byte)(StatByte[4][1] & 0xff) << 8) | ((byte)(StatByte[4][2] & 0xff) << 16) | ((byte)(StatByte[4][3] & 0xff)) << 24 | ((byte)(StatByte[4][4] & 0xff)) << 32 | ((byte)(StatByte[4][5] & 0xff)) << 40 | ((byte)(StatByte[4][6] & 0xff)) << 48 | ((byte)(StatByte[4][7] & 0xff)) << 56; _big8 = ((StatByte[4][8] & 0xff)) | ((byte)(StatByte[4][9] & 0xff) << 8) | ((byte)(StatByte[4][10] & 0xff) << 16) | ((byte)(StatByte[4][11] & 0xff)) << 24 | ((byte)(StatByte[4][12] & 0xff)) << 32 | ((byte)(StatByte[4][13] & 0xff)) << 40 | ((byte)(StatByte[4][14] & 0xff)) << 48 | ((byte)(StatByte[4][15] & 0xff)) << 56; }
/// <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> internal GMSSLeaf(IDigest Digest, int W, int NumLeafs) { _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); m_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) * m_keySize + 1 + m_keySize) / (double)(NumLeafs)); // initialize arrays _seed = new byte[_mdsize]; _leaf = new byte[_mdsize]; _privateKeyOTS = new byte[_mdsize]; _concHashs = new byte[_mdsize * m_keySize]; }
/// <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); m_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]; }
private void Dispose(bool Disposing) { if (!m_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 { } m_isDisposed = true; } }
/// <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 (!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; } }