Beispiel #1
0
        public void _ProvingAndVerifyingTest2(BigInteger Exp, int keySize, int k, out double ProvingTime, out double VerifyingTime)
        {
            var setup = new PoupardSternSetup(ps, keySize, k);
            // PoupardStern Protocol
            var keyPair = TestUtils.GeneratePrivate(Exp, keySize);

            sw.Restart(); //Proving start
            var outputTuple = ((RsaPrivateCrtKeyParameters)keyPair.Private).ProvePoupardStern(setup);

            sw.Stop();  //Proving ends

            ProvingTime = sw.Elapsed.TotalSeconds;

            sw.Restart(); //Verifying start
            ((RsaKeyParameters)keyPair.Public).VerifyPoupardStern(outputTuple, setup);
            sw.Stop();    //Verifying stops

            VerifyingTime = sw.Elapsed.TotalSeconds;
        }
        /// <summary>
        /// Proving algorithm as specified in section 3.2.1 of the setup.
        /// </summary>
        /// <param name="privKey">The secret key</param>
        /// <param name="setup">The setup parameters</param>
        /// <returns>The PoupardStern proof</returns>
        public static PoupardSternProof ProvePoupardStern(this RsaPrivateCrtKeyParameters privKey, PoupardSternSetup setup)
        {
            if (privKey == null)
            {
                throw new ArgumentNullException(nameof(privKey));
            }
            if (setup == null)
            {
                throw new ArgumentNullException(nameof(setup));
            }

            BigInteger p       = privKey.P;
            BigInteger q       = privKey.Q;
            BigInteger Modulus = privKey.Modulus;

            int k         = setup.SecurityParameter;
            var psBytes   = setup.PublicString;
            int keyLength = setup.KeySize;

            BigInteger Two = BigInteger.Two;
            // 2^{|N| - 1}
            BigInteger lowerLimit = Two.Pow(keyLength - 1);
            // 2^{|N|}
            BigInteger upperLimit = Two.Pow(keyLength);

            // Rounding up k to the closest multiple of 8
            k = Utils.GetByteLength(k) * 8;

            // Check if N < 2^{|N|-1}
            if (Modulus.CompareTo(lowerLimit) < 0)
            {
                throw new ArgumentOutOfRangeException("RSA modulus smaller than expected");
            }

            // if N >= 2^{KeySize}
            if (Modulus.CompareTo(upperLimit) >= 0)
            {
                throw new ArgumentOutOfRangeException("RSA modulus larger than expected");
            }

            // if even
            if ((Modulus.IntValue & 1) == 0)
            {
                throw new ArgumentException("RSA modulus is even");
            }

            // p and q don't produce a modulus N that has the expected bitLength
            if (!(Modulus.BitLength.Equals(keyLength)))
            {
                throw new ArgumentException("RSA P and Q are bad");
            }

            // Calculating phi
            BigInteger pSub1 = p.Subtract(BigInteger.One);
            BigInteger qSub1 = q.Subtract(BigInteger.One);
            BigInteger phi   = pSub1.Multiply(qSub1);
            // N - phi(N)
            BigInteger NsubPhi = Modulus.Subtract(phi);

            // if 2^{|N|-1}/{(N-phi)*2^k} <= 2^k
            var p11 = Two.Pow(k);
            var p1  = lowerLimit.Divide(NsubPhi.Multiply(p11));

            if (p1.CompareTo(p11) <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(Modulus), "Bad RSA modulus N");
            }

            // Generate K
            GetK(k, out int BigK);

            // Extract public key (N, e) from private key.
            var pubKey = privKey.ToPublicKey();

            // Initialize and generate list of z values
            BigInteger[] zValues = new BigInteger[BigK];
            for (int i = 0; i < BigK; i++)
            {
                zValues[i] = SampleFromZnStar(pubKey, psBytes, i, BigK, keyLength);
            }
            BigInteger y;

            for (; ;)
            {
                // Initialize list of x values.
                BigInteger[] xValues = new BigInteger[BigK];

                // Get r
                GetR(keyLength, out BigInteger r);

                for (int i = 0; i < BigK; i++)
                {
                    // Compute x_i
                    xValues[i] = zValues[i].ModPow(r, Modulus);
                }

                // Compute w
                GetW(pubKey, psBytes, xValues, k, keyLength, out BigInteger w);

                // Compute y
                y = r.Add(NsubPhi.Multiply(w));

                // if y >= 2^{ |N| - 1 }
                if (y.CompareTo(lowerLimit) >= 0)
                {
                    continue;
                }

                // if y < 0
                if (y.CompareTo(BigInteger.Zero) < 0)
                {
                    continue;
                }

                return(new PoupardSternProof(new Tuple <BigInteger[], BigInteger>(xValues, y)));
            }
        }
        /// <summary>
        /// Verifying Algorithm as specified in section 3.3 of the setup.
        /// </summary>
        /// <param name="pubKey">Public key used</param>
        /// <param name="proof">The proof.</param>
        /// <param name="setup">Setup parameters.</param>
        /// <returns>true if the proof verifies, false otherwise</returns>
        public static bool VerifyPoupardStern(this RsaKeyParameters pubKey, PoupardSternProof proof, PoupardSternSetup setup)
        {
            if (pubKey == null)
            {
                throw new ArgumentNullException(nameof(pubKey));
            }
            if (proof == null)
            {
                throw new ArgumentNullException(nameof(proof));
            }
            if (setup == null)
            {
                throw new ArgumentNullException(nameof(setup));
            }

            int keyLength = setup.KeySize;
            int k         = setup.SecurityParameter;
            var y         = proof.YValue;

            BigInteger rPrime;
            BigInteger Two = BigInteger.Two;
            // 2^{|N| - 1}
            BigInteger lowerLimit = Two.Pow(keyLength - 1);
            // 2^{|N|}
            BigInteger upperLimit = Two.Pow(keyLength);

            // Rounding up k to the closest multiple of 8
            k = Utils.GetByteLength(k) * 8;

            var Modulus  = pubKey.Modulus;
            var Exponent = pubKey.Exponent;

            // Checking that:
            // if y >= 2^{ |N| - 1 }
            if (y.CompareTo(lowerLimit) >= 0)
            {
                return(false);
            }
            // if y < 0
            if (y.CompareTo(BigInteger.Zero) < 0)
            {
                return(false);
            }
            // if N < 2^{KeySize-1}
            if (Modulus.CompareTo(lowerLimit) < 0)
            {
                return(false);
            }
            // if even
            if ((Modulus.IntValue & 1) == 0)
            {
                return(false);
            }
            // if N >= 2^{KeySize}
            if (Modulus.CompareTo(upperLimit) >= 0)
            {
                return(false);
            }

            // Computing K
            GetK(k, out int BigK);

            // Check if the number of x_values is not equal to K
            if (proof.XValues.Length != BigK)
            {
                return(false);
            }

            // Get w
            GetW(pubKey, setup.PublicString, proof.XValues, k, keyLength, out BigInteger w);

            // Computing rPrime
            rPrime = y.Subtract(Modulus.Multiply(w));

            // Verifying x values
            for (int i = 0; i < BigK; i++)
            {
                var z_i = SampleFromZnStar(pubKey, setup.PublicString, i, BigK, keyLength);
                // Compute right side of the equality
                var rs = z_i.ModPow(rPrime, Modulus);
                // If the two sides are not equal
                if (!(proof.XValues[i].Equals(rs)))
                {
                    return(false);
                }
            }

            return(true);
        }