Example #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);
        }
Example #2
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));
            }
        }
Example #3
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."));
            }
        }