示例#1
0
        // 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);
        }
示例#2
0
 public Lmots(LmotsType type, EntropyProviderTypes entropyType = EntropyProviderTypes.Random)
 {
     var(n, w, p, ls, siglen, typecode) = LmotsModeMapping.GetValsFromType(type);
     _n               = n;
     _w               = w;
     _p               = p;
     _ls              = ls;
     _siglen          = siglen;
     _typecode        = typecode;
     _entropyProvider = _entropyFactory.GetEntropyProvider(entropyType);
     _isRandom        = entropyType == EntropyProviderTypes.Random;
     _sha256          = new NativeFastSha2_256();
 }
示例#3
0
        public LmotsVerificationResult VerifyLmotsSignature(BitString sig, BitString publicKey, BitString msg)
        {
            // 1. If the public key is not at least four bytes long, return INVALID.
            if (publicKey.BitLength < 32)
            {
                return(new LmotsVerificationResult("Validation failed. Public key wrong length."));
            }

            // 2.  Parse pubtype, I, q, and K from the public key as follows:
            // a. pubtype = strTou32(first 4 bytes of public key)
            var pubType = publicKey.MSBSubstring(0, 32);

            // b. Set n according to the pubkey and Table 1; if the public key is not exactly 24 + n bytes long, return INVALID.
            var n = LmotsModeMapping.GetNFromCode(pubType);

            if (publicKey.BitLength != (n + 24) * 8)
            {
                return(new LmotsVerificationResult("Validation failed. Public key wrong length."));
            }

            // c. I = next 16 bytes of public key
            var I = publicKey.MSBSubstring(32, 128);

            // d. q = strTou32(next 4 bytes of public key)
            var q = publicKey.MSBSubstring(160, 32);

            // e. K = next n bytes of public key
            var K = publicKey.MSBSubstring(192, n * 8);

            // 3. Compute the public key candidate Kc from the signature, message, pubtype, and the identifiers I and q
            //    obtained from the public key, using Algorithm 4b.If Algorithm 4b returns INVALID, then return INVALID.
            var Kc = Algorithm4b(sig, msg, pubType, I, q);

            if (Kc == null)
            {
                return(new LmotsVerificationResult("Validation failed. Computing Kc failed."));
            }

            // 4. If Kc is equal to K, return VALID; otherwise, return INVALID.
            if (K.Equals(Kc))
            {
                return(new LmotsVerificationResult());
            }
            else
            {
                return(new LmotsVerificationResult("Validation failed. Signature does not match."));
            }
        }
示例#4
0
        private const int H25_PIECE_SIZE = 32768;   // creates 1024 threads

        #endregion Fields

        #region Constructors

        // From an email from Scott Fluhrer:
        // To generate the I value for the LMS tree, we will adapt algorithm A,
        // by setting the I value input to be the all-zeros value, the q value
        // to be 0 and the i value to be 65535; we will use the first 16 bytes of the hash output.
        // Algorithm A:
        // x_q[i] = H(I || u32str(q) || u16str(i) || u8str(0xff) || SEED).
        // UPDATE: I value is now generated separate from SEED. Child I values still computed the same
        public Lms(LmsType lmsType, LmotsType lmotsType,
                   EntropyProviderTypes entropyType = EntropyProviderTypes.Random, BitString seed = null, BitString I = null)
        {
            var(m, h, typecode) = LmsModeMapping.GetValsFromType(lmsType);
            _m        = m;
            _h        = h;
            _typecode = typecode;
            var param = LmotsModeMapping.GetValsFromType(lmotsType);

            _lmotsTypecode   = param.typecode;
            _entropyProvider = _entropyFactory.GetEntropyProvider(entropyType);
            _entropyProvider.AddEntropy(seed);
            SEED = _entropyProvider.GetEntropy(_m * 8);
            _entropyProvider.AddEntropy(I);
            _I        = _entropyProvider.GetEntropy(128);
            _lmots    = new Lmots(lmotsType, entropyType);
            _isRandom = entropyType == EntropyProviderTypes.Random;
            _sha256   = new NativeFastSha2_256();

            // For optimization the balance between interop calls and asynchronization
            if (_h == 5)
            {
                _pieceSize = H5_PIECE_SIZE;
            }
            else if (_h == 10)
            {
                _pieceSize = H10_PIECE_SIZE;
            }
            else if (_h == 15)
            {
                _pieceSize = H15_PIECE_SIZE;
            }
            else if (_h == 20)
            {
                _pieceSize = H20_PIECE_SIZE;
            }
            else
            {
                _pieceSize = H25_PIECE_SIZE;
            }
        }
示例#5
0
        public HssVerificationResult VerifyHssSignature(BitString msg, BitString publicKey, BitString signature)
        {
            // 1. The signature S is parsed into its components as follows:
            // a. Nspk = strTou32(first four bytes of S)
            //    if Nspk+1 is not equal to the number of levels L in pub return INVALID
            var Nspk           = (int)signature.MSBSubstring(0, 32).ToPositiveBigInteger();
            var lengthInPublic = (int)publicKey.MSBSubstring(0, 32).ToPositiveBigInteger();

            if (Nspk + 1 != lengthInPublic)
            {
                return(new HssVerificationResult("Validation failed. L values do not match."));
            }

            // b. for (i = 0; i<Nspk; i = i + 1) {
            //        siglist[i] = next LMS signature parsed from S
            //        publist[i] = next LMS public key parsed from S
            //    }
            var siglist   = new BitString[Nspk + 1];
            var publist   = new BitString[Nspk + 1];
            var currIndex = 32;

            for (int i = 0; i < Nspk; i++)
            {
                // assume sig and pub have same LMS mode
                var otsCode = signature.MSBSubstring(currIndex + 32, 32);
                var n       = LmotsModeMapping.GetNFromCode(otsCode);
                var p       = LmotsModeMapping.GetPFromCode(otsCode);
                var sigtype = signature.MSBSubstring((8 + n * (p + 1)) * 8 + currIndex, 32);
                var m       = LmsModeMapping.GetMFromCode(sigtype);
                var h       = LmsModeMapping.GetHFromCode(sigtype);
                var siglen  = (12 + n * (p + 1) + m * h) * 8;
                var publen  = 192 + (m * 8);
                siglist[i] = signature.MSBSubstring(currIndex, siglen);
                currIndex += siglen;
                publist[i] = signature.MSBSubstring(currIndex, publen);
                currIndex += publen;
            }

            // c. siglist[Nspk] = next LMS signature parsed from S
            var otsCodeLast = signature.MSBSubstring(currIndex + 32, 32);
            var nLast       = LmotsModeMapping.GetNFromCode(otsCodeLast);
            var pLast       = LmotsModeMapping.GetPFromCode(otsCodeLast);
            var sigtypeLast = signature.MSBSubstring((8 + nLast * (pLast + 1)) * 8 + currIndex, 32);
            var mLast       = LmsModeMapping.GetMFromCode(sigtypeLast);
            var hLast       = LmsModeMapping.GetHFromCode(sigtypeLast);
            var siglenLast  = (12 + nLast * (pLast + 1) + mLast * hLast) * 8;

            siglist[Nspk] = signature.MSBSubstring(currIndex, siglenLast);

            // 2. Verify each part of the signature
            var key = publicKey.MSBSubstring(32, publicKey.BitLength - 32);

            for (int i = 0; i < Nspk; i++)
            {
                var result = _lms[i].VerifyLmsSignature(publist[i], key, siglist[i]);
                if (!result.Success)
                {
                    return(new HssVerificationResult("LMS Validation failed: " + result.ErrorMessage));
                }
                key = publist[i];
            }

            // 3. return lms_verify(message, key, siglist[Nspk])
            var finalResult = _lms[Nspk].VerifyLmsSignature(msg, key, siglist[Nspk]);

            if (finalResult.Success)
            {
                return(new HssVerificationResult());
            }
            else
            {
                return(new HssVerificationResult("Validation failed. Final check failed: " + finalResult.ErrorMessage));
            }
        }
示例#6
0
        public LmsVerificationResult VerifyLmsSignature(BitString msg, BitString publicKey, BitString signature)
        {
            // 1. If the public key is not at least eight bytes long, return INVALID.
            if (publicKey.BitLength < 64)
            {
                return(new LmsVerificationResult("Validation failed. Public key wrong length."));
            }

            // 2. Parse pubtype, I, and T[1] from the public key as follows:
            // a. pubtype = strTou32(first 4 bytes of public key)
            var pubType = publicKey.MSBSubstring(0, 32);

            // b. ots_typecode = strTou32(next 4 bytes of public key)
            var ots_typecode = publicKey.MSBSubstring(32, 32);

            // c. Set m according to pubtype, based on Table 2.
            var m = LmsModeMapping.GetMFromCode(pubType);

            // d. If the public key is not exactly 24 + m bytes long, return INVALID.
            if (publicKey.BitLength != (24 + m) * 8)
            {
                return(new LmsVerificationResult("Validation failed. Public key wrong length."));
            }

            // e. I = next 16 bytes of the public key
            var I = publicKey.MSBSubstring(64, 128);

            // f. T[1] = next m bytes of the public key
            var root = publicKey.MSBSubstring(192, m * 8);

            // 3. Compute the LMS Public Key Candidate Tc from the signature, message, identifier,
            //    pubtype, and ots_typecode, using Algorithm 6a.

            // Algorithm 6a:

            // 1. If the signature is not at least eight bytes long, return INVALID.
            if (signature.BitLength < 64)
            {
                return(new LmsVerificationResult("Validation failed. Signature wrong length."));
            }

            // 2.  Parse sigtype, q, lmots_signature, and path from the signature as follows:
            // a. q = strTou32(first 4 bytes of signature)
            var q = signature.MSBSubstring(0, 32);

            // b. otssigtype = strTou32(next 4 bytes of signature)
            var otssigtype = signature.MSBSubstring(32, 32);

            // c. If otssigtype is not the OTS typecode from the public key, return INVALID.
            if (!otssigtype.Equals(ots_typecode))
            {
                return(new LmsVerificationResult("Validation failed. OTS Code incongruent."));
            }

            // d. Set n, p according to otssigtype and Table 1; if the signature is not
            //    at least 12 + n* (p + 1) bytes long, return INVALID.
            var n = LmotsModeMapping.GetNFromCode(otssigtype);
            var p = LmotsModeMapping.GetPFromCode(otssigtype);

            if (signature.BitLength < (12 + n * (p - 1)) * 8)
            {
                return(new LmsVerificationResult("Validation failed. Signature wrong length."));
            }

            // e. lmots_signature = bytes 4 through 7 + n* (p + 1) of signature
            var lmots_signature = signature.MSBSubstring(32, (4 + n * (p + 1)) * 8);

            // f. sigtype = strTou32(bytes 8 + n* (p + 1)) through 11 + n* (p + 1) of signature)
            var sigtype = signature.MSBSubstring((8 + n * (p + 1)) * 8, 32);

            // g. If sigtype is not the LM typecode from the public key, return INVALID.
            if (!sigtype.Equals(pubType))
            {
                return(new LmsVerificationResult("Verification failed. Type mismatch."));
            }

            // h. Set m, h according to sigtype and Table 2.
            // m already set from above
            var h = LmsModeMapping.GetHFromCode(sigtype);

            // i. If q >= 2^h or the signature is not exactly 12 + n* (p + 1) + m* h bytes long, return INVALID.
            if (q.ToPositiveBigInteger() >= (1 << h) || signature.BitLength != (12 + n * (p + 1) + m * h) * 8)
            {
                return(new LmsVerificationResult("Verification failed. Signature wrong length."));
            }

            // j. Set path as follows:
            //    path[0] = next m bytes of signature
            //    path[1] = next m bytes of signature
            //    ...
            //    path[h-1] = next m bytes of signature
            var path = new BitString[h];

            for (int i = 0; i < h; i++)
            {
                path[i] = signature.MSBSubstring(((12 + n * (p + 1)) * 8) + (i * m * 8), m * 8);
            }

            // 3.  Kc = candidate public key computed by applying Algorithm 4b to the signature lmots_signature,
            //     the message, and the identifiers I, q
            var Kc = _lmots.Algorithm4b(lmots_signature, msg, otssigtype, I, q);

            if (Kc == null)
            {
                return(new LmsVerificationResult("Verification failed. Algorithm 4b failed."));
            }

            // 4. Compute the candidate LMS root value Tc as described in rfc 8554
            var node_num = (1 << h) + q.ToPositiveBigInteger();

            var tmp = _sha256.HashMessage(I
                                          .ConcatenateBits(new BitString(node_num, 32))
                                          .ConcatenateBits(D_LEAF)
                                          .ConcatenateBits(Kc)).Digest;

            for (int i = 0; node_num > 1; node_num /= 2)
            {
                if (node_num % 2 == 1)
                {
                    tmp = _sha256.HashMessage(I
                                              .ConcatenateBits(new BitString(node_num / 2, 32))
                                              .ConcatenateBits(D_INTR)
                                              .ConcatenateBits(path[i])
                                              .ConcatenateBits(tmp)).Digest;
                }
                else
                {
                    tmp = _sha256.HashMessage(I
                                              .ConcatenateBits(new BitString(node_num / 2, 32))
                                              .ConcatenateBits(D_INTR)
                                              .ConcatenateBits(tmp)
                                              .ConcatenateBits(path[i])).Digest;
                }
                i++;
            }

            // 5. Return Tc
            var Tc = tmp;

            // END Algorithm 6a

            // 4. If Tc is equal to T[1], return VALID; otherwise, return INVALID.
            if (Tc.Equals(root))
            {
                return(new LmsVerificationResult());
            }
            else
            {
                return(new LmsVerificationResult("Verification failed. Signature invalid."));
            }
        }