/// <summary> /// A wrapper for the interop function that is safe within Orleans. /// The task factory forces the new thread to be on the NonOrleansThreadScheduler /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="ots_priv"></param> /// <param name="pub_piece"></param> private async Task GeneratePubPiece(long start, long end, byte[] ots_priv, byte[] pub) { var taskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskContinuationOptions.None, TaskScheduler.Current); await taskFactory.StartNew(() => { LmsDllLoader.GenPubPiece(start, end, _h, _m, ots_priv, _lmots.GetP(), _lmots.GetN(), _lmots.GetW(), pub); }); }
// Computes Kc as described in rfc 8554 public BitString Algorithm4b(BitString sig, BitString msg, BitString pubType, BitString I, BitString q) { // 1. If the signature is not at least four bytes long, return INVALID. if (sig.BitLength < 32) { return(null); } // 2. Parse sigtype, C, and y from the signature as follows: // a. sigtype = strTou32(first 4 bytes of signature) var sigType = sig.MSBSubstring(0, 32); // b. If sigtype is not equal to pubtype, return INVALID. if (!pubType.Equals(sigType)) { return(null); } // c. Set n and p according to the pubtype and Table 1; if the signature is not exactly 4 + n * (p + 1) // bytes long, return INVALID. var p = LmotsModeMapping.GetPFromCode(sigType); var n = LmotsModeMapping.GetNFromCode(sigType); if (sig.BitLength != (4 + (n * (p + 1))) * 8) { return(null); } // d. C = next n bytes of signature var C = sig.MSBSubstring(32, n * 8); // e. y[0] = next n bytes of signature // y[1] = next n bytes of signature // ... // y[p - 1] = next n bytes of signature var y = sig.MSBSubstring((n * 8) + 32, p * n * 8); // 3. Compute the string Kc as described in rfc 8554 var Q = _sha256.HashMessage(I .ConcatenateBits(q) .ConcatenateBits(D_MESG) .ConcatenateBits(C) .ConcatenateBits(msg)).Digest; var cksmQ = CheckSum(Q); var QcksmQ = Q.ConcatenateBits(cksmQ); var z = LmsDllLoader.GenZ(_p, _n, _w, y.ToBytes(), QcksmQ.ToBytes(), I.ToBytes(), q.ToBytes()); var concatenated = I.ConcatenateBits(q).ConcatenateBits(D_PBLC); concatenated = concatenated.ConcatenateBits(new BitString(z)); var Kc = _sha256.HashMessage(concatenated).Digest; // 4. Return Kc. return(Kc); }
/// <summary> /// Builds tree from pub and also the public key as a BitString /// </summary> /// <param name="pub">A bunch of last 32 bytes of public keys</param> /// <returns>LMS public key</returns> private BitString GenerateLmsPublicKey(byte[] pub) { var tree = LmsDllLoader.BuildTreeWithPub(_h, _m, _I.ToBytes(), pub, _lmots.GetP(), _lmots.GetN(), _lmots.GetW()); _tree = new LmsTree(_h, _m, tree); var publicKey = _typecode.ConcatenateBits(_lmotsTypecode) .ConcatenateBits(_I) .ConcatenateBits(_tree.GetRoot()); return(publicKey); }
// Uses algorithm described in Appendix A of rfc 8554 public BitString GenerateLmotsPrivateKey(BitString q, BitString I, BitString seed = null) { if (_isRandom) { var rand = _entropyProvider.GetEntropy(_n * 8 * _p); return(_typecode.ConcatenateBits(q).ConcatenateBits(I).ConcatenateBits(rand)); } else { var priv = LmsDllLoader.GenPrivLmots(_n, _p, q.ToBytes(), I.ToBytes(), seed.ToBytes(), _typecode.ToBytes()); return(new BitString(priv)); } }
// To generate the randomized value C, we will adapt algorithm A, by using the I value of the LMS tree, // the q value to be the LMS index, and the i value to be 65533 // Algorithm A: // x_q[i] = H(I || u32str(q) || u16str(i) || u8str(0xff) || SEED). public BitString GenerateLmotsSignature(BitString msg, BitString privateKey, BitString seed = null) { if (_isRandom) { var C = _entropyProvider.GetEntropy(_n * 8); var sig = LmsDllLoader.GenSigLmotsNonDeterministic(_n, _p, _w, _ls, msg.ToBytes().Length, privateKey.ToBytes(), C.ToBytes(), msg.ToBytes()); return(new BitString(sig)); } else { var sig = LmsDllLoader.GenSigLmots(_n, _p, _w, _ls, msg.ToBytes().Length, privateKey.ToBytes(), seed.ToBytes(), msg.ToBytes()); return(new BitString(sig)); } }
public BitString GenerateLmsSignature(BitString msg, LmsPrivateKey privateKey) { // 0. Use pub to generate tree if it is not null if (privateKey.Pub != null) { var tree = LmsDllLoader.BuildTreeWithPub(_h, _m, _I.ToBytes(), privateKey.Pub, _lmots.GetP(), _lmots.GetN(), _lmots.GetW()); _tree = new LmsTree(_h, _m, tree); } // 1. Generate ots with next available leaf (in private key) var q = privateKey.Q; if (q * ((_lmots.GetN() * _lmots.GetP()) + 24) >= privateKey.OTS_PRIV.Length) { return(null); } var lmots_signature = _lmots.GenerateLmotsSignature(msg, new BitString(privateKey.GetLmotsPrivateKeyQ(q)), SEED); // 2. Increment q in private key to ensure no reusablility of key // privateKey.UpdateQ(); // currently done in hss // 3. Determine path[] var path = new BitString(""); int currentIndex = (1 << _h) + q; for (int i = 0; i < _h; i++) { path = path.ConcatenateBits(_tree.GetSibling(currentIndex)); currentIndex /= 2; } // 4. u32str(q) || lmots_signature || u32str(type) || path[0] || path[1] || path[2] || ... || path[h - 1] return(new BitString(q, 32) .ConcatenateBits(lmots_signature) .ConcatenateBits(_typecode) .ConcatenateBits(path)); }
public byte[] GenerateLmotsPublicKey(BitString privateKey) { return(LmsDllLoader.GenPubLmots(_n, _p, _w, privateKey.ToBytes())); }
/// <summary> /// Wrapper function for interop call to create OTS_PRIV /// </summary> /// <returns>OTS_PRIV as a byte array</returns> private byte[] GenerateOtsPriv() { return(LmsDllLoader.GenOtsPrivLms(_h, _I.ToBytes(), SEED.ToBytes(), _lmots.GetN(), _lmots.GetP(), _lmotsTypecode.ToBytes())); }