コード例 #1
0
        public static BigInteger AssociateValueFunction(int qExactLength, EccKeyPair publicKey)
        {
            int f = (qExactLength + 1) / 2;

            BigInteger pow2 = NumberTheory.Pow2(f);

            return(pow2 + (publicKey.PublicQ.X % pow2));
        }
コード例 #2
0
ファイル: CounterKdf.cs プロジェクト: usnistgov/ACVP-Server
        public KdfResult DeriveKey(BitString kI, BitString fixedData, int len, BitString iv = null, int breakLocation = 0)
        {
            // 1
            var n = len.CeilingDivide(Mac.OutputLength);

            // 2
            if (n > NumberTheory.Pow2(_counterLength) - 1)
            {
                return(new KdfResult("Counter length too long for operation"));
            }

            // 3
            var result = new BitString(0);

            // 4
            if (_counterLocation == CounterLocations.MiddleFixedData)
            {
                if (breakLocation < 1 || breakLocation > fixedData.BitLength - 1)
                {
                    return(new KdfResult("Invalid break location"));
                }
            }

            for (var i = 1; i <= n; i++)
            {
                var counterBits = BitString.To32BitString(i).GetLeastSignificantBits(_counterLength);
                var data        = new BitString(0);

                switch (_counterLocation)
                {
                case CounterLocations.BeforeFixedData:
                    data = data.ConcatenateBits(counterBits).ConcatenateBits(fixedData);
                    break;

                case CounterLocations.AfterFixedData:
                    data = data.ConcatenateBits(fixedData).ConcatenateBits(counterBits);
                    break;

                case CounterLocations.MiddleFixedData:
                    var firstPart  = fixedData.GetMostSignificantBits(breakLocation);
                    var secondPart = fixedData.MSBSubstring(breakLocation, fixedData.BitLength - breakLocation);
                    data = data.ConcatenateBits(firstPart).ConcatenateBits(counterBits).ConcatenateBits(secondPart);
                    break;

                default:
                    return(new KdfResult("Invalid Counter location"));
                }

                var kTemp = PseudoRandomFunction(kI, data);

                result = result.ConcatenateBits(kTemp);
            }

            // 5
            var kOut = result.GetMostSignificantBits(len);

            return(new KdfResult(kOut));
        }
コード例 #3
0
ファイル: EdDsa.cs プロジェクト: usnistgov/ACVP-Server
        public EdSignatureResult Sign(EdDomainParameters domainParameters, EdKeyPair keyPair, BitString message, BitString context, bool preHash = false)
        {
            Sha = domainParameters.Hash;

            // If preHash version, then the message becomes the hash of the message
            if (preHash)
            {
                message = Sha.HashMessage(message, 512).Digest;
            }

            // 1. Hash the private key
            var hashResult = HashPrivate(domainParameters, keyPair.PrivateD);

            // 2. Compute r
            // Determine dom. Empty if ed25519. Different for preHash function
            BitString dom;
            if (preHash)
            {
                dom = domainParameters.CurveE.CurveName == Curve.Ed448 ? Dom4(1, context) : Dom2(1, context);
            }
            else
            {
                dom = domainParameters.CurveE.CurveName == Curve.Ed448 ? Dom4(0, context) : new BitString("");
            }

            // Hash (dom4 || Prefix || message)
            var rBits = Sha.HashMessage(BitString.ConcatenateBits(dom, BitString.ConcatenateBits(hashResult.HDigest2, message)), 912).Digest;

            // Convert rBits to little endian and mod order n
            var r = BitString.ReverseByteOrder(rBits).ToPositiveBigInteger() % domainParameters.CurveE.OrderN;

            // 3. Compute [r]G. R is the encoding of [r]G
            var rG = domainParameters.CurveE.Multiply(domainParameters.CurveE.BasePointG, r);

            // Encode the point rG into a b-bit bitstring
            var R = domainParameters.CurveE.Encode(rG);

            // 4. Define S
            // Hash (dom4 || R || Q || M). Need to use dom4 if ed448
            var hashData = BitString.ConcatenateBits(keyPair.PublicQ, message);
            hashData = BitString.ConcatenateBits(dom, BitString.ConcatenateBits(R, hashData));
            var hash = Sha.HashMessage(hashData, 912).Digest;

            // Convert hash to int from little endian and mod order n
            var hashInt = BitString.ReverseByteOrder(hash).ToPositiveBigInteger() % domainParameters.CurveE.OrderN;

            // Determine s as done in key generation
            var s = NumberTheory.Pow2(domainParameters.CurveE.VariableN) + hashResult.Buffer.ToPositiveBigInteger();

            // Calculate S as an BigInteger
            var Sint = (r + (hashInt * s)).PosMod(domainParameters.CurveE.OrderN);

            // Encode S in little endian
            var S = BitString.ReverseByteOrder(new BitString(Sint, domainParameters.CurveE.VariableB));

            // 5. Form the signature by concatenating R and S
            return new EdSignatureResult(new EdSignature(R, S));
        }
コード例 #4
0
        public static bool IsValidExponent(BigInteger e)
        {
            if (e <= NumberTheory.Pow2(16) || e >= NumberTheory.Pow2(256) || e.IsEven)
            {
                return(false);
            }

            return(true);
        }
        private PrimeGeneratorResult GeneratePrimes(PrimeGeneratorParameters param)
        {
            BigInteger p, p1, p2, q, q1, q2;

            // 1, 2, 3, 4 covered by Guards

            // 5
            var workingSeed = param.Seed.ToPositiveBigInteger();

            // 6
            var pResult = PrimeGeneratorHelper.ProvablePrimeConstruction(_sha, param.Modulus / 2, param.BitLens[0], param.BitLens[1], workingSeed, param.PublicE);

            if (!pResult.Success)
            {
                return(new PrimeGeneratorResult($"Bad p gen: {pResult.ErrorMessage}"));
            }

            p           = pResult.Prime;
            p1          = pResult.Prime1;
            p2          = pResult.Prime2;
            workingSeed = pResult.PrimeSeed;

            do
            {
                // 7
                var qResult = PrimeGeneratorHelper.ProvablePrimeConstruction(_sha, param.Modulus / 2, param.BitLens[2], param.BitLens[3], workingSeed, param.PublicE);
                if (!qResult.Success)
                {
                    return(new PrimeGeneratorResult($"Bad q gen: {qResult.ErrorMessage}"));
                }

                q           = qResult.Prime;
                q1          = qResult.Prime1;
                q2          = qResult.Prime2;
                workingSeed = qResult.PrimeSeed;

                // 8
            } while (BigInteger.Abs(p - q) <= NumberTheory.Pow2(param.Modulus / 2 - 100));

            var auxValues = new AuxiliaryResult();
            var primePair = new PrimePair {
                P = p, Q = q
            };

            return(new PrimeGeneratorResult(primePair, auxValues));
        }
コード例 #6
0
        private PrimeGeneratorResult GeneratePrimes(PrimeGeneratorParameters param)
        {
            // 1, 2, 3, 4 covered by guards

            // 5
            var workingSeed = param.Seed.ToPositiveBigInteger();

            // 6
            var ppcResult = PrimeGeneratorHelper.ProvablePrimeConstruction(_sha, param.Modulus / 2, 1, 1, workingSeed, param.PublicE);

            if (!ppcResult.Success)
            {
                return(new PrimeGeneratorResult($"Bad Provable Prime Construction for p: {ppcResult.ErrorMessage}"));
            }
            var p = ppcResult.Prime;

            workingSeed = ppcResult.PrimeSeed;

            BigInteger q;

            do
            {
                // 7
                ppcResult = PrimeGeneratorHelper.ProvablePrimeConstruction(_sha, param.Modulus / 2, 1, 1, workingSeed, param.PublicE);
                if (!ppcResult.Success)
                {
                    return(new PrimeGeneratorResult($"Bad Provable Prime Construction for q: {ppcResult.ErrorMessage}"));
                }
                q           = ppcResult.Prime;
                workingSeed = ppcResult.PrimeSeed;

                // 8
            } while (BigInteger.Abs(p - q) <= NumberTheory.Pow2(param.Modulus / 2 - 100));

            // 9, 10
            var auxValues = new AuxiliaryResult();
            var primePair = new PrimePair {
                P = p, Q = q
            };

            return(new PrimeGeneratorResult(primePair, auxValues));
        }
コード例 #7
0
        /// <summary>
        /// A.1.2.1.1 Get a first seed value
        /// </summary>
        /// <param name="N"></param>
        /// <param name="seedLen"></param>
        /// <returns></returns>
        private BigInteger GetFirstSeed(int L, int N, int seedLen)
        {
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(0);
            }

            if (seedLen < N)
            {
                return(0);
            }

            BitString firstSeed;

            do
            {
                firstSeed = _entropy.GetEntropy(seedLen);
            } while (firstSeed.ToPositiveBigInteger() < NumberTheory.Pow2(N - 1));

            return(firstSeed.ToPositiveBigInteger());
        }
コード例 #8
0
ファイル: EdDsa.cs プロジェクト: usnistgov/ACVP-Server
        public EdKeyPairGenerateResult GenerateKeyPair(EdDomainParameters domainParameters)
        {
            Sha = domainParameters.Hash;

            // Generate random number d
            var d = _entropyProvider.GetEntropy(1, NumberTheory.Pow2(domainParameters.CurveE.VariableB) - 1);

            // 1. Hash the private key
            // 2. Prune the buffer
            // Both accomplished by this function
            var h = HashPrivate(domainParameters, new BitString(d, domainParameters.CurveE.VariableB)).Buffer;

            // 3. Determine s
            var s = NumberTheory.Pow2(domainParameters.CurveE.VariableN) + h.ToPositiveBigInteger();

            // 4. Compute Q such that Q = s * G
            var Q = domainParameters.CurveE.Multiply(domainParameters.CurveE.BasePointG, s);

            // Encode Q
            var qEncoded = EdPointEncoder.Encode(Q, domainParameters.CurveE.VariableB);

            // Return key pair (Q, d)
            return new EdKeyPairGenerateResult(new EdKeyPair(qEncoded, new BitString(d, domainParameters.CurveE.VariableB)));
        }
コード例 #9
0
        /// <summary>
        /// A.1.1.3 from FIPS 186-4
        /// </summary>
        /// <param name="p"></param>
        /// <param name="q"></param>
        /// <param name="seed"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public PQValidateResult Validate(BigInteger p, BigInteger q, DomainSeed seed, Counter count)
        {
            if (seed.Mode != PrimeGenMode.Probable && count.Mode != PrimeGenMode.Probable)
            {
                return(new PQValidateResult("Invalid DomainSeed and Counter"));
            }

            // 1, 2
            var L = new BitString(p).BitLength;
            var N = new BitString(q).BitLength;

            // 3
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(new PQValidateResult("Invalid L, N pair"));
            }

            // 4
            if (count.Count > (4 * L - 1))
            {
                return(new PQValidateResult("Invalid counter"));
            }

            // 5, 6

            /*
             *  Appending 0s to the bitstring representation of the seed as to make it mod 32 (if it isn't already), as this is the mod of the original seed that is hashed.
             *  In instances (as an example) when the chosen seed starts with eight zero bits in a row, the biginteger representation of said bitstring is 1 byte smaller than it should be,
             *  thus failing the check that it is at least the length of N
             */
            var seedBitString = new BitString(seed.Seed);

            if (seedBitString.BitLength % 32 != 0)
            {
                seedBitString = BitString.ConcatenateBits(BitString.Zeroes(32 - seedBitString.BitLength % 32), seedBitString);
            }
            var seedLen = seedBitString.BitLength;

            if (seedLen < N)
            {
                return(new PQValidateResult("Invalid seed"));
            }

            // 7
            var U = _sha.HashNumber(seed.Seed).ToBigInteger() % NumberTheory.Pow2(N - 1);

            // 8
            var computed_q = NumberTheory.Pow2(N - 1) + U + 1 - (U % 2);

            // 9
            if (!NumberTheory.MillerRabin(computed_q, DSAHelper.GetMillerRabinIterations(L, N)) || computed_q != q)
            {
                return(new PQValidateResult("Q not prime, or doesn't match expected value"));
            }

            // 10, 11, 12
            var outLen = _sha.HashFunction.OutputLen;
            var n      = L.CeilingDivide(outLen) - 1;
            var b      = L - 1 - (n * outLen);
            var offset = 1;

            // 13
            BigInteger computed_p = 0;
            int        i;

            for (i = 0; i <= count.Count; i++)
            {
                // 13.1, 13.2
                var W = _sha.HashNumber(seed.Seed + offset).ToBigInteger();
                for (var j = 1; j < n; j++)
                {
                    W += (_sha.HashNumber(seed.Seed + offset + j).ToBigInteger()) * NumberTheory.Pow2(j * outLen);
                }
                W += ((_sha.HashNumber(seed.Seed + offset + n).ToBigInteger()) % NumberTheory.Pow2(b)) * NumberTheory.Pow2(n * outLen);

                // 13.3
                var X = W + NumberTheory.Pow2(L - 1);

                // 13.4
                var c = X % (2 * q);

                // 13.5
                computed_p = X - (c - 1);

                // 13.6, 13.7, 13.8
                if (computed_p >= NumberTheory.Pow2(L - 1))
                {
                    // Check if p is prime, if so return
                    if (NumberTheory.MillerRabin(computed_p, DSAHelper.GetMillerRabinIterations(L, N)))
                    {
                        break;
                    }
                }

                // 13.9
                offset += n + 1;
            }

            // 14
            if (i != count.Count || computed_p != p || !NumberTheory.MillerRabin(computed_p, DSAHelper.GetMillerRabinIterations(L, N)))
            {
                return(new PQValidateResult($"Invalid p value or counter. computed_p = {new BitString(computed_p).ToHex()}"));
            }

            // 15
            return(new PQValidateResult());
        }
コード例 #10
0
        private PrimeGeneratorResult GeneratePrimes(PrimeGeneratorParameters param)
        {
            BigInteger p, p1, p2, q, q1, q2, xp, xq;

            // 1, 2, 3, 4 covered by guards

            // 5
            var p1Result = PrimeGen186_4.ShaweTaylorRandomPrime(param.BitLens[0], param.Seed.ToPositiveBigInteger(), _sha);

            if (!p1Result.Success)
            {
                return(new PrimeGeneratorResult($"Failed to generate p1: {p1Result.ErrorMessage}"));
            }

            var p2Result = PrimeGen186_4.ShaweTaylorRandomPrime(param.BitLens[1], p1Result.PrimeSeed, _sha);

            if (!p2Result.Success)
            {
                return(new PrimeGeneratorResult($"Failed to generate p2: {p2Result.ErrorMessage}"));
            }

            p1 = p1Result.Prime;
            p2 = p2Result.Prime;

            var pResult = PrimeGeneratorHelper.ProbablePrimeFactor(_primeTest, _entropyProvider, _pBound, param.A, p1, p2, param.Modulus, param.PublicE);

            if (!pResult.Success)
            {
                return(new PrimeGeneratorResult($"Failed to generate p: {pResult.ErrorMessage}"));
            }

            p  = pResult.Prime;
            xp = pResult.XPrime;

            do
            {
                // 6
                var q1Result = PrimeGen186_4.ShaweTaylorRandomPrime(param.BitLens[2], p2Result.PrimeSeed, _sha);
                if (!q1Result.Success)
                {
                    return(new PrimeGeneratorResult($"Failed to generate q1: {q1Result.ErrorMessage}"));
                }

                var q2Result = PrimeGen186_4.ShaweTaylorRandomPrime(param.BitLens[3], q1Result.PrimeSeed, _sha);
                if (!q2Result.Success)
                {
                    return(new PrimeGeneratorResult($"Failed to generate q2: {q2Result.ErrorMessage}"));
                }

                q1 = q1Result.Prime;
                q2 = q2Result.Prime;

                var qResult = PrimeGeneratorHelper.ProbablePrimeFactor(_primeTest, _entropyProvider, _pBound, param.B, q1, q2, param.Modulus, param.PublicE);
                if (!qResult.Success)
                {
                    return(new PrimeGeneratorResult($"Failed to generate q: {qResult.ErrorMessage}"));
                }

                q  = qResult.Prime;
                xq = qResult.XPrime;

                // 7
            } while (BigInteger.Abs(p - q) <= NumberTheory.Pow2(param.Modulus / 2 - 100) ||
                     BigInteger.Abs(xp - xq) <= NumberTheory.Pow2(param.Modulus / 2 - 100));

            var auxValues = new AuxiliaryResult {
                XP = xp, XQ = xq
            };
            var primePair = new PrimePair {
                P = p, Q = q
            };

            return(new PrimeGeneratorResult(primePair, auxValues));
        }
コード例 #11
0
        private PrimeGeneratorResult GeneratePrimes(PrimeGeneratorParameters param)
        {
            BigInteger p, p1, p2, q, q1, q2, xp, xq, xp1, xp2, xq1, xq2;

            // 1, 2, 3 covered by guards

            // 4
            xp1 = _entropyProvider.GetEntropy(param.BitLens[0]).ToPositiveBigInteger();
            if (xp1.IsEven)
            {
                xp1++;
            }

            xp2 = _entropyProvider.GetEntropy(param.BitLens[1]).ToPositiveBigInteger();
            if (xp2.IsEven)
            {
                xp2++;
            }

            p1 = xp1;
            while (!PrimeGeneratorHelper.MillerRabin(_primeTestMode, param.Modulus, p1, true))
            {
                p1 += 2;
            }

            p2 = xp2;
            while (!PrimeGeneratorHelper.MillerRabin(_primeTestMode, param.Modulus, p2, true))
            {
                p2 += 2;
            }

            var pResult = PrimeGeneratorHelper.ProbablePrimeFactor(_primeTestMode, _entropyProvider, _pBound, param.A, p1, p2, param.Modulus, param.PublicE);

            if (!pResult.Success)
            {
                return(new PrimeGeneratorResult($"Failed to generate p: {pResult.ErrorMessage}"));
            }
            p  = pResult.Prime;
            xp = pResult.XPrime;

            // 5
            do
            {
                xq1 = _entropyProvider.GetEntropy(param.BitLens[2]).ToPositiveBigInteger();
                if (xq1.IsEven)
                {
                    xq1++;
                }

                xq2 = _entropyProvider.GetEntropy(param.BitLens[3]).ToPositiveBigInteger();
                if (xq2.IsEven)
                {
                    xq2++;
                }

                q1 = xq1;
                while (!PrimeGeneratorHelper.MillerRabin(_primeTestMode, param.Modulus, q1, true))
                {
                    q1 += 2;
                }

                q2 = xq2;
                while (!PrimeGeneratorHelper.MillerRabin(_primeTestMode, param.Modulus, q2, true))
                {
                    q2 += 2;
                }

                var qResult = PrimeGeneratorHelper.ProbablePrimeFactor(_primeTestMode, _entropyProvider, _pBound, param.B, q1, q2, param.Modulus, param.PublicE);
                if (!qResult.Success)
                {
                    return(new PrimeGeneratorResult($"Failed to generate q: {qResult.ErrorMessage}"));
                }
                q  = qResult.Prime;
                xq = qResult.XPrime;

                // 6
            } while (BigInteger.Abs(xp - xq) <= NumberTheory.Pow2(param.Modulus / 2 - 100) ||
                     BigInteger.Abs(p - q) <= NumberTheory.Pow2(param.Modulus / 2 - 100));

            var auxValues = new AuxiliaryResult {
                XP1 = xp1, XP2 = xp2, XP = xp, XQ1 = xq1, XQ2 = xq2, XQ = xq
            };
            var primePair = new PrimePair {
                P = p, Q = q
            };

            return(new PrimeGeneratorResult(primePair, auxValues));
        }
コード例 #12
0
ファイル: EdDsa.cs プロジェクト: usnistgov/ACVP-Server
        public EdVerificationResult Verify(EdDomainParameters domainParameters, EdKeyPair keyPair, BitString message, EdSignature signature, BitString context, bool preHash = false)
        {
            Sha = domainParameters.Hash;

            // If preHash version, then the message becomes the hash of the message
            if (preHash)
            {
                message = Sha.HashMessage(message, 512).Digest;
            }

            // 1. Decode R, s, and Q
            EdPoint R;
            BigInteger s;
            EdPoint Q;
            try
            {
                var sigDecoded = SignatureDecoderHelper.DecodeSig(domainParameters, signature);
                R = sigDecoded.R;
                s = sigDecoded.s;
                Q = domainParameters.CurveE.Decode(keyPair.PublicQ);
            }
            catch (Exception e)
            {
                return new EdVerificationResult(e.Message);
            }

            // 2. Concatenate R || Q || M
            var hashData = BitString.ConcatenateBits(domainParameters.CurveE.Encode(R), BitString.ConcatenateBits(keyPair.PublicQ, message));

            // 3. Compute t
            // Determine dom. Empty if ed25519. Different for preHash function
            BitString dom;
            if (preHash)
            {
                dom = domainParameters.CurveE.CurveName == Curve.Ed448 ? Dom4(1, context) : Dom2(1, context);
            }
            else
            {
                dom = domainParameters.CurveE.CurveName == Curve.Ed448 ? Dom4(0, context) : new BitString("");
            }

            // Compute Hash(dom4 || HashData)
            var hash = Sha.HashMessage(BitString.ConcatenateBits(dom, hashData), 912).Digest;

            // Interpret hash as a little endian integer
            var t = BitString.ReverseByteOrder(hash).ToPositiveBigInteger();

            // 4. Check the verification equation [2^c * s]G = [2^c]R + [2^c * t]Q
            // 2^c
            var powC = NumberTheory.Pow2(domainParameters.CurveE.VariableC);

            // [2^c * s]G
            var lhs = domainParameters.CurveE.Multiply(domainParameters.CurveE.BasePointG, (powC * s).PosMod(domainParameters.CurveE.OrderN));

            // [2^c]R
            var rhs1 = domainParameters.CurveE.Multiply(R, powC);

            // [2^c * t]Q
            var rhs2 = domainParameters.CurveE.Multiply(Q, (powC * t).PosMod(domainParameters.CurveE.OrderN));

            // [2^c]R + [2^c * t]Q
            var rhs = domainParameters.CurveE.Add(rhs1, rhs2);

            if (lhs.Equals(rhs))
            {
                return new EdVerificationResult();
            }

            return new EdVerificationResult("The verification equation is not satisfied. Signature not valid");
        }
コード例 #13
0
        public KdfResult DeriveKey(BitString kI, BitString fixedData, int len, BitString iv, int breakLocation = 0)
        {
            // 1
            var n = len.CeilingDivide(Mac.OutputLength);

            // 2
            if (n > NumberTheory.Pow2(32) - 1)
            {
                return(new KdfResult("Counter length too long for operation"));
            }

            // 3
            var result = new BitString(0);

            // 4
            if (_counterLocation == CounterLocations.None)
            {
                if (_counterLength != 0)
                {
                    return(new KdfResult("Counter must have 0 length"));
                }
            }

            var prevK = iv?.GetDeepCopy() ?? new BitString(0);

            for (var i = 1; i <= n; i++)
            {
                var counterBits = BitString.To32BitString(i).GetLeastSignificantBits(_counterLength);
                var data        = new BitString(0);

                switch (_counterLocation)
                {
                case CounterLocations.BeforeIterator:
                    // counter || prevK || fixedData
                    data = data.ConcatenateBits(counterBits).ConcatenateBits(prevK).ConcatenateBits(fixedData);
                    break;

                case CounterLocations.AfterFixedData:
                    // prevK || fixedData || counter
                    data = data.ConcatenateBits(prevK).ConcatenateBits(fixedData).ConcatenateBits(counterBits);
                    break;

                case CounterLocations.MiddleFixedData:
                case CounterLocations.BeforeFixedData:
                    // prevK || counter || fixedData
                    data = data.ConcatenateBits(prevK).ConcatenateBits(counterBits).ConcatenateBits(fixedData);
                    break;

                case CounterLocations.None:
                    // prevK || fixedData
                    data = data.ConcatenateBits(prevK).ConcatenateBits(fixedData);
                    break;

                default:
                    return(new KdfResult("Invalid Counter location"));
                }

                prevK = PseudoRandomFunction(kI, data);

                result = result.ConcatenateBits(prevK);
            }

            // 5
            var kOut = result.GetMostSignificantBits(len);

            return(new KdfResult(kOut));
        }
コード例 #14
0
        /// <summary>
        /// A.1.2.1.2
        /// </summary>
        /// <param name="L"></param>
        /// <param name="N"></param>
        /// <param name="firstSeed"></param>
        /// <returns></returns>
        private PQGenerateResult Generate(int L, int N, BigInteger firstSeed)
        {
            // 1
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(new PQGenerateResult("Bad L, N pair"));
            }

            // 2
            var qResult = PrimeGen186_4.ShaweTaylorRandomPrime(N, firstSeed, _sha);

            if (!qResult.Success)
            {
                return(new PQGenerateResult("Failed to generate q from ShaweTaylor"));
            }
            var q        = qResult.Prime;
            var qSeed    = qResult.PrimeSeed;
            var qCounter = qResult.PrimeGenCounter;

            // 3
            var pLen    = L.CeilingDivide(2) + 1;
            var pResult = PrimeGen186_4.ShaweTaylorRandomPrime(pLen, qSeed, _sha);

            if (!pResult.Success)
            {
                return(new PQGenerateResult("Failed to generate p0 from ShaweTaylor"));
            }
            var p0       = pResult.Prime;
            var pSeed    = pResult.PrimeSeed;
            var pCounter = pResult.PrimeGenCounter;

            // 4, 5
            var outLen     = _sha.HashFunction.OutputLen;
            var iterations = L.CeilingDivide(outLen) - 1;
            var oldCounter = pCounter;

            // 6, 7
            BigInteger x = 0;

            for (var i = 0; i <= iterations; i++)
            {
                x += _sha.HashNumber(pSeed + i).ToBigInteger() * NumberTheory.Pow2(i * outLen);
            }

            // 8
            pSeed += iterations + 1;

            // 9
            x = NumberTheory.Pow2(L - 1) + (x % NumberTheory.Pow2(L - 1));

            // 10
            var t = x.CeilingDivide(2 * q * p0);

            do
            {
                // 11
                if (2 * t * q * p0 + 1 > NumberTheory.Pow2(L))
                {
                    t = NumberTheory.Pow2(L - 1).CeilingDivide(2 * q * p0);
                }

                // 12, 13
                var p = 2 * t * q * p0 + 1;
                pCounter++;

                // 14, 15
                BigInteger a = 0;
                for (var i = 0; i <= iterations; i++)
                {
                    a += _sha.HashNumber(pSeed + i).ToBigInteger() * NumberTheory.Pow2(i * outLen);
                }

                // 16
                pSeed += iterations + 1;

                // 17
                a = 2 + (a % (p - 3));

                // 18
                var z = BigInteger.ModPow(a, 2 * t * q, p);

                // 19
                if (1 == NumberTheory.GCD(z - 1, p) && 1 == BigInteger.ModPow(z, p0, p))
                {
                    return(new PQGenerateResult(p, q, new DomainSeed(firstSeed, pSeed, qSeed), new Counter(pCounter, qCounter)));
                }

                // 20
                if (pCounter > 4 * L + oldCounter)
                {
                    return(new PQGenerateResult("Too many iterations"));
                }

                // 21
                t++;

                // 22
            } while (true);
        }
コード例 #15
0
        /// <summary>
        /// A.1.2.2
        /// </summary>
        /// <param name="p"></param>
        /// <param name="q"></param>
        /// <param name="seed"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public PQValidateResult Validate(BigInteger p, BigInteger q, DomainSeed seed, Counter count)
        {
            // 0, domain type check
            if (seed.Mode != PrimeGenMode.Provable && count.Mode != PrimeGenMode.Provable)
            {
                return(new PQValidateResult("Invalid DomainSeed and Counter"));
            }

            // 1, 2
            var L = new BitString(p).BitLength;
            var N = new BitString(q).BitLength;

            // 3
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(new PQValidateResult("Invalid L, N pair"));
            }

            // 4
            if (seed.Seed < NumberTheory.Pow2(N - 1))
            {
                return(new PQValidateResult("Bad first seed"));
            }

            // 5
            if (NumberTheory.Pow2(N) <= q)
            {
                return(new PQValidateResult("Bad q, too small"));
            }

            // 6
            if (NumberTheory.Pow2(L) <= p)
            {
                return(new PQValidateResult("Bad p, too large"));
            }

            // 7
            if ((p - 1) % q != 0)
            {
                return(new PQValidateResult("p - 1 % q != 0, bad values"));
            }

            // 8
            var computed_result = Generate(L, N, seed.Seed);

            if (!computed_result.Success)
            {
                return(new PQValidateResult("Failed to generate p and q"));
            }

            if (q != computed_result.Q || seed.QSeed != computed_result.Seed.QSeed || count.QCount != computed_result.Count.QCount)
            {
                return(new PQValidateResult("Failed to generate given q"));
            }

            if (p != computed_result.P || seed.PSeed != computed_result.Seed.PSeed || count.PCount != computed_result.Count.PCount)
            {
                return(new PQValidateResult("Failed to generate given p"));
            }

            return(new PQValidateResult());
        }
コード例 #16
0
        public VerifyResult VerifyPadding(int nlen, BitString message, BigInteger embededMessage, PublicKey pubKey)
        {
            // 1. Signature Opening
            BigInteger irPrime;

            if (embededMessage % 16 == 12)
            {
                irPrime = embededMessage;
            }
            else if ((pubKey.N - embededMessage) % 16 == 12)
            {
                irPrime = pubKey.N - embededMessage;
            }
            else
            {
                return(new VerifyResult("Reject signature, failing modulo check"));
            }

            if (irPrime < NumberTheory.Pow2(nlen - 2) || irPrime > NumberTheory.Pow2(nlen - 1) - 1)
            {
                return(new VerifyResult("irPrime not within required range"));
            }

            // 2. Encapsulated Hash Verification
            var bsIrPrime = new BitString(irPrime, nlen);

            if (bsIrPrime.BitLength != nlen)
            {
                return(new VerifyResult("Bad bitlength for irPrime"));
            }

            if (!bsIrPrime.GetMostSignificantBits(4).Equals(Header))
            {
                return(new VerifyResult("Header not found within first 4 bits"));
            }

            if (!bsIrPrime.GetLeastSignificantBits(8).Equals(Tail))
            {
                return(new VerifyResult("Tail not found within last 8 bits"));
            }

            // check nibbles for Bs and A
            var expectedPaddingLen = nlen - Header.BitLength - Sha.HashFunction.OutputLen - GetTrailer().BitLength;
            var expectedPadding    = GetPadding(expectedPaddingLen);
            var padding            = bsIrPrime.MSBSubstring(4, expectedPaddingLen);

            if (!padding.Equals(expectedPadding))
            {
                return(new VerifyResult("Improper padding, must be 'B's followed by 'A'"));
            }

            var beginOfHashIndex = expectedPaddingLen + 4;

            // 3. Hash Recovery
            var hashDigest = bsIrPrime.MSBSubstring(beginOfHashIndex, Sha.HashFunction.OutputLen);

            // 4. Message Hashing and Comparison
            var expectedHash = Sha.HashMessage(message).Digest;

            // check trailer for accuracy, including hash function
            var expectedTrailer = GetTrailer();
            var trailer         = bsIrPrime.GetLeastSignificantBits(expectedTrailer.BitLength);

            if (!expectedTrailer.Equals(trailer))
            {
                return(new VerifyResult("Trailer hash functions do not match, bad signature"));
            }

            if (expectedHash.Equals(hashDigest))
            {
                return(new VerifyResult());
            }
            else
            {
                return(new VerifyResult("Hashes do not match, bad signature"));
            }
        }
コード例 #17
0
        /// <summary>
        /// A.1.1.2 from FIPS 186-4
        /// </summary>
        /// <param name="L"></param>
        /// <param name="N"></param>
        /// <param name="seedLen"></param>
        /// <returns></returns>
        public PQGenerateResult Generate(int L, int N, int seedLen)
        {
            // 1. Check L/N pair
            if (!DSAHelper.VerifyLenPair(L, N))
            {
                return(new PQGenerateResult("Invalid L, N pair"));
            }

            // 2. Check seedLen
            if (seedLen < N)
            {
                return(new PQGenerateResult("Invalid seedLen"));
            }

            // 3, 4 Compute n, b
            var outLen = _sha.HashFunction.OutputLen;
            var n      = L.CeilingDivide(outLen) - 1;
            var b      = L - 1 - (n * outLen);

            do
            {
                BigInteger seed, q;

                do
                {
                    // 5. Get random seed
                    seed = _entropy.GetEntropy(seedLen).ToPositiveBigInteger();

                    // 6. Hash seed
                    var U = _sha.HashNumber(seed).ToBigInteger() % NumberTheory.Pow2(N - 1);

                    // 7. Compute q
                    q = NumberTheory.Pow2(N - 1) + U + 1 - (U % 2);

                    // Check if q is prime, if not go back to 5, assume highest security strength
                } while (!NumberTheory.MillerRabin(q, DSAHelper.GetMillerRabinIterations(L, N)));

                // 10, 11 Compute p
                var offset     = 1;
                var upperBound = (4 * L - 1);
                for (var ctr = 0; ctr <= upperBound; ctr++)
                {
                    // 11.1, 11.2
                    var W = _sha.HashNumber(seed + offset).ToBigInteger();
                    for (var j = 1; j < n; j++)
                    {
                        W += _sha.HashNumber(seed + offset + j).ToBigInteger() * NumberTheory.Pow2(j * outLen);
                    }
                    W += (_sha.HashNumber(seed + offset + n).ToBigInteger() % NumberTheory.Pow2(b)) * NumberTheory.Pow2(n * outLen);

                    // 11.3
                    var X = W + NumberTheory.Pow2(L - 1);

                    // 11.4
                    var c = X % (2 * q);

                    // 11.5
                    var p = X - (c - 1);

                    // 11.6, 11.7, 11.8
                    if (p >= NumberTheory.Pow2(L - 1))
                    {
                        // Check if p is prime, if so return
                        if (NumberTheory.MillerRabin(p, DSAHelper.GetMillerRabinIterations(L, N)))
                        {
                            return(new PQGenerateResult(p, q, new DomainSeed(seed), new Counter(ctr)));
                        }
                    }

                    // 11.9
                    offset += n + 1;
                }

                // 12
            } while (true);
        }
コード例 #18
0
        private PrimeGeneratorResult GeneratePrimes(PrimeGeneratorParameters param)
        {
            // 1, 2, 3 performed by guards

            // 4, 4.1
            var        i            = 0;
            BigInteger p            = 0;
            var        pqLowerBound = GetBound(param.Modulus);

            do
            {
                do
                {
                    // 4.2
                    if (p != 0 && _kat)
                    {
                        return(new PrimeGeneratorResult("Given p less than sqrt(2) * 2 ^ (n/2) - 1, need to get a new random number."));
                    }
                    p = _entropyProvider.GetEntropy(param.Modulus / 2).ToPositiveBigInteger();

                    // 4.3
                    if (_performAShift)
                    {
                        p += (param.A - p).PosMod(8);
                    }
                    else if (p.IsEven)
                    {
                        p++;
                    }

                    // 4.4
                } while (p < pqLowerBound);

                // 4.5
                if (NumberTheory.GCD(p - 1, param.PublicE) == 1)
                {
                    if (PrimeGeneratorHelper.MillerRabin(_primeTestMode, param.Modulus, p, false))
                    {
                        break;
                    }
                }

                // 4.6, 4.7
                i++;
                if (i >= _iBoundForP * (param.Modulus / 2))
                {
                    return(new PrimeGeneratorResult("Too many iterations for p"));
                }

                if (_kat)
                {
                    return(new PrimeGeneratorResult("Given p is not prime"));
                }
            } while (!_kat);

            // 5, 5.1
            i = 0;
            BigInteger q = 0;

            do
            {
                do
                {
                    // 5.2
                    if (q != 0 && _kat)
                    {
                        return(new PrimeGeneratorResult("Given q less than sqrt(2) * 2 ^ (n/2) - 1, need to get a new random number."));
                    }
                    q = _entropyProvider.GetEntropy(param.Modulus / 2).ToPositiveBigInteger();

                    // 5.3
                    if (_performBShift)
                    {
                        q += (param.B - q).PosMod(8);
                    }
                    else if (q.IsEven)
                    {
                        q++;
                    }

                    // 5.4
                    // 5.5
                } while (BigInteger.Abs(p - q) <= NumberTheory.Pow2(param.Modulus / 2 - 100) || q < pqLowerBound);

                // 5.6
                if (NumberTheory.GCD(q - 1, param.PublicE) == 1)
                {
                    if (PrimeGeneratorHelper.MillerRabin(_primeTestMode, param.Modulus, q, false))
                    {
                        break;
                    }
                }

                // 5.7, 5.8
                i++;
                if (i >= _iBoundForQ * (param.Modulus / 2))
                {
                    return(new PrimeGeneratorResult("Too many iterations for q"));
                }

                if (_kat)
                {
                    return(new PrimeGeneratorResult("Given q is not prime"));
                }
            } while (!_kat);

            var auxValues = new AuxiliaryResult();
            var primePair = new PrimePair {
                P = p, Q = q
            };

            return(new PrimeGeneratorResult(primePair, auxValues));
        }
コード例 #19
0
ファイル: EdDsa.cs プロジェクト: usnistgov/ACVP-Server
        public EdKeyPairValidateResult ValidateKeyPair(EdDomainParameters domainParameters, EdKeyPair keyPair)
        {
            // If D is out of bounds, reject
            if (keyPair.PrivateD.ToPositiveBigInteger() < 1 || keyPair.PrivateD.ToPositiveBigInteger() > NumberTheory.Pow2(domainParameters.CurveE.VariableB) - 1)
            {
                return new EdKeyPairValidateResult("D must be able to be a b-bit string");
            }

            EdPoint Q;
            try
            {
                Q = domainParameters.CurveE.Decode(keyPair.PublicQ);
            }
            catch (Exception e)
            {
                return new EdKeyPairValidateResult(e.Message);
            }

            // If Q == (0, 1), invalid
            if (Q.Equals(new EdPoint(0, 1)))
            {
                return new EdKeyPairValidateResult("Q cannot be neutral element");
            }

            // If Q is not a valid point on the specific curve, invalid
            // could make this more efficient
            if (!domainParameters.CurveE.PointExistsOnCurve(Q))
            {
                return new EdKeyPairValidateResult("Q does not lie on the curve");
            }

            // If n * Q == 0, valid
            // This is fast because the scalar (n) is taken modulo n... so it's 0
            if (domainParameters.CurveE.Multiply(Q, domainParameters.CurveE.OrderN).Equals(new EdPoint(0, 1)))
            {
                return new EdKeyPairValidateResult();
            }

            // Otherwise invalid
            return new EdKeyPairValidateResult("n * Q must equal (0, 1)");
        }