private void TestSign(GMSSParameters CipherParam) { GMSSKeyGenerator mkgen = new GMSSKeyGenerator(CipherParam); IAsymmetricKeyPair akp = mkgen.GenerateKeyPair(); byte[] data = new byte[200]; new VTDev.Libraries.CEXEngine.Crypto.Prng.CSPRng().GetBytes(data); using (GMSSSign sgn = new GMSSSign(CipherParam)) { // sign the array sgn.Initialize(akp.PrivateKey); byte[] code = sgn.Sign(data, 0, data.Length); // verify the signature sgn.Initialize(akp.PublicKey); if (!sgn.Verify(data, 0, data.Length, code)) throw new Exception("RLWESignTest: Sign operation failed!"); // get the next available key (private sub-key is used only once) GMSSPrivateKey nk = ((GMSSPrivateKey)akp.PrivateKey).NextKey(); sgn.Initialize(nk); code = sgn.Sign(new MemoryStream(data)); // verify the signature sgn.Initialize(akp.PublicKey); if (!sgn.Verify(new MemoryStream(data), code)) throw new Exception("RLWESignTest: Verify test failed!"); } }
/// <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); }
static double KeyGenerator(int Iterations, GMSSParameters Param) { // new SP20Prng(SeedGenerators.CSPRsg, 16384, 32, 10) // salsa20 GMSSKeyGenerator mkgen = new GMSSKeyGenerator(Param); IAsymmetricKeyPair akp; Stopwatch runTimer = new Stopwatch(); runTimer.Start(); for (int i = 0; i < Iterations; i++) akp = mkgen.GenerateKeyPair(); runTimer.Stop(); return runTimer.Elapsed.TotalMilliseconds; }
/// <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(); }
/// <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> /// Compare this object instance with another /// </summary> /// /// <param name="Obj">Object to compare</param> /// /// <returns>True if equal, otherwise false</returns> public override bool Equals(Object Obj) { if (this == Obj) { return(true); } if (Obj == null && this != null) { return(false); } GMSSParameters other = (GMSSParameters)Obj; if (!Compare.IsEqual(_heightOfTrees, other.HeightOfTrees)) { return(false); } if (!Compare.IsEqual(_winternitzParameter, other.WinternitzParameter)) { return(false); } if (!Compare.IsEqual(m_K, other.K)) { return(false); } if (_numLayers != other.NumLayers) { return(false); } if (m_dgtEngineType != other.DigestEngine) { return(false); } return(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(); }
/// <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> /// 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; } }
/// <summary> /// Generates a new GMSS private key /// </summary> /// /// <param name="CurrentSeed">A seed for the generation of private OTS keys for the current subtrees</param> /// <param name="NextNextSeed">A seed for the generation of private OTS keys for the next subtrees</param> /// <param name="CurrentAuthPath">Array of current authentication paths</param> /// <param name="NextAuthPath">Array of next authentication paths</param> /// <param name="CurrentTreehash">Array of current treehash instances</param> /// <param name="NextTreehash">Array of next treehash instances</param> /// <param name="CurrentStack">Array of current shared stacks</param> /// <param name="NextStack">Array of next shared stacks</param> /// <param name="CurrentRetain">Array of current retain stacks</param> /// <param name="NextRetain">Array of next retain stacks</param> /// <param name="NextRoot">The roots of the next subtree</param> /// <param name="CurrentRootSig">Array of signatures of the roots of the current subtrees</param> /// <param name="ParameterSet">The GMSS Parameterset</param> /// <param name="Digest">The digest type</param> internal GMSSPrivateKey(byte[][] CurrentSeed, byte[][] NextNextSeed, byte[][][] CurrentAuthPath, byte[][][] NextAuthPath, Treehash[][] CurrentTreehash, Treehash[][] NextTreehash, List<byte[]>[] CurrentStack, List<byte[]>[] NextStack, List<byte[]>[][] CurrentRetain, List<byte[]>[][] NextRetain, byte[][] NextRoot, byte[][] CurrentRootSig, GMSSParameters ParameterSet, Digests Digest) : this(null, CurrentSeed, NextNextSeed, CurrentAuthPath, NextAuthPath, null, CurrentTreehash, NextTreehash, CurrentStack, NextStack, CurrentRetain, NextRetain, null, null, null, null, NextRoot, null, CurrentRootSig, null, ParameterSet, Digest) { }
/// <summary> /// Reconstructs a public key from its <c>byte</c> array representation. /// </summary> /// /// <param name="KeyStream">An input stream containing an encoded key</param> /// /// <exception cref="CryptoAsymmetricSignException">Thrown if the key could not be loaded</exception> public GMSSPrivateKey(Stream KeyStream) { try { BinaryReader reader = new BinaryReader(KeyStream); int len; int len2; byte[] data; len = reader.ReadInt32(); data = reader.ReadBytes(len); _gmssPS = new GMSSParameters(data); len = reader.ReadInt32(); if (len < 1) { _currentSeeds = ArrayUtils.CreateJagged<byte[][]>(0, 0); } else { data = reader.ReadBytes(len); _currentSeeds = ArrayUtils.ToArray2x8(data); } len = reader.ReadInt32(); if (len < 1) { _nextNextSeeds = ArrayUtils.CreateJagged<byte[][]>(0, 0); } else { data = reader.ReadBytes(len); _nextNextSeeds = ArrayUtils.ToArray2x8(data); } len = reader.ReadInt32(); if (len < 1) { _currentAuthPaths = ArrayUtils.CreateJagged<byte[][][]>(0, 0); } else { data = reader.ReadBytes(len); _currentAuthPaths = ArrayUtils.ToArray3x8(data); } len = reader.ReadInt32(); if (len < 1) { _nextAuthPaths = ArrayUtils.CreateJagged<byte[][][]>(0, 0); } else { data = reader.ReadBytes(len); _nextAuthPaths = ArrayUtils.ToArray3x8(data); } len = reader.ReadInt32(); if (len < 1) { _keep = ArrayUtils.CreateJagged<byte[][][]>(0, 0); } else { data = reader.ReadBytes(len); _keep = ArrayUtils.ToArray3x8(data); } len = reader.ReadInt32(); if (len < 1) { _currentTreehash = ArrayUtils.CreateJagged<Treehash[][]>(0, 0); } else { len2 = reader.ReadInt32(); _currentTreehash = ArrayUtils.CreateJagged<Treehash[][]>(len, len2); for (int i = 0; i < _currentTreehash.Length; i++) { for (int j = 0; j < _currentTreehash[i].Length; j++) { len = reader.ReadInt32(); data = reader.ReadBytes(len); _currentTreehash[i][j] = new Treehash(GetDigest(_gmssPS.DigestEngine), data); } } } len = reader.ReadInt32(); if (len < 1) { _nextTreehash = ArrayUtils.CreateJagged<Treehash[][]>(0, 0); } else { len2 = reader.ReadInt32(); _nextTreehash = ArrayUtils.CreateJagged<Treehash[][]>(len, len2); for (int i = 0; i < _nextTreehash.Length; i++) { for (int j = 0; j < _nextTreehash[i].Length; j++) { len = reader.ReadInt32(); data = reader.ReadBytes(len); _nextTreehash[i][j] = new Treehash(GetDigest(_gmssPS.DigestEngine), data); } } } len = reader.ReadInt32(); if (len < 1) { _currentStack = new List<byte[]>[0]; } else { _currentStack = new List<byte[]>[len]; for (int i = 0; i < _currentStack.Length; i++) { len = reader.ReadInt32(); data = reader.ReadBytes(len); _currentStack[i].Add(data); } } len = reader.ReadInt32(); if (len < 1) { _nextStack = new List<byte[]>[0]; } else { _nextStack = new List<byte[]>[len]; for (int i = 0; i < _nextStack.Length; i++) { len = reader.ReadInt32(); data = reader.ReadBytes(len); _nextStack[i].Add(data); } } len = reader.ReadInt32(); if (len < 1) { _currentRetain = ArrayUtils.CreateJagged<List<byte[]>[][]>(0, 0); } else { len2 = reader.ReadInt32(); _currentRetain = ArrayUtils.CreateJagged<List<byte[]>[][]>(len, len2); for (int i = 0; i < _currentRetain.Length; i++) { for (int j = 0; j < _currentRetain[i].Length; j++) { len = reader.ReadInt32(); data = reader.ReadBytes(len); _currentRetain[i][j] = new List<byte[]>(); _currentRetain[i][j].Add(data); } } } len = reader.ReadInt32(); if (len < 1) { _nextRetain = ArrayUtils.CreateJagged<List<byte[]>[][]>(0, 0); } else { len2 = reader.ReadInt32(); _nextRetain = ArrayUtils.CreateJagged<List<byte[]>[][]>(len, len2); for (int i = 0; i < _nextRetain.Length; i++) { for (int j = 0; j < _nextRetain[i].Length; j++) { len = reader.ReadInt32(); data = reader.ReadBytes(len); _nextRetain[i][j] = new List<byte[]>(); _nextRetain[i][j].Add(data); } } } len = reader.ReadInt32(); if (len < 1) { _nextRoot = ArrayUtils.CreateJagged<byte[][]>(0, 0); } else { data = reader.ReadBytes(len); _nextRoot = ArrayUtils.ToArray2x8(data); } len = reader.ReadInt32(); if (len < 1) { _currentRootSig = ArrayUtils.CreateJagged<byte[][]>(0, 0); } else { data = reader.ReadBytes(len); _currentRootSig = ArrayUtils.ToArray2x8(data); } } catch (Exception ex) { throw new CryptoAsymmetricException("GMSSPrivateKey:CTor", "The GMSSPrivateKey could not be loaded!", ex); } }
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; } }
static double SignTest(int Iterations, GMSSParameters Param, bool Sign = true) { Stopwatch runTimer = new Stopwatch(); byte[] code; GMSSKeyGenerator mkgen = new GMSSKeyGenerator(Param); IAsymmetricKeyPair akp = mkgen.GenerateKeyPair(); byte[] data = new byte[200]; new CSPRng().GetBytes(data); using (GMSSSign sgn = new GMSSSign(Param)) { if (Sign) { sgn.Initialize(akp.PrivateKey); runTimer.Start(); for (int i = 0; i < Iterations; i++) code = sgn.Sign(data, 0, data.Length); runTimer.Stop(); } else { // sign the array first sgn.Initialize(akp.PrivateKey); code = sgn.Sign(data, 0, data.Length); // init for verify sgn.Initialize(akp.PublicKey); runTimer.Start(); for (int i = 0; i < Iterations; i++) sgn.Verify(data, 0, data.Length, code); runTimer.Stop(); } } return runTimer.Elapsed.TotalMilliseconds; }