Пример #1
0
        private BouncyCastle.FpFieldElement GetX(
            byte[] input,
            BouncyCastle.FpCurve curve,
            int index,
            int counter)
        {
            int numIterations = (int)System.Math.Ceiling(
                (double)(curve.Q.BitLength / 8) / (double)hashByteSize);

            byte[] digest = new byte[numIterations * hashByteSize];

            for (int iteration = 0; iteration < numIterations; iteration++)
            {
                byte[] hashInput = ProtocolHelper.Concatenate(
                    input,
                    encoding.GetBytes(
                        index.ToString() + counter.ToString() + iteration.ToString()));
                hash.HashWithoutFormatting(hashInput);
                Array.Copy(hash.Digest, 0, digest, hashByteSize * iteration, hashByteSize);
            }

            BCBigInt x = new BCBigInt(1, digest).Mod(curve.Q);

            return(curve.FromBigInteger(x) as BouncyCastle.FpFieldElement);
        }
Пример #2
0
        /// <summary>
        /// Verifies that e is an element of the group.
        /// </summary>
        /// <param name="e">The element to test.</param>
        /// <exception cref="InvalidUProveArtifactException">
        /// Thrown if i is not in the group.</exception>
        public override void ValidateGroupElement(GroupElement e)
        {
            SubgroupGroupElementBCImpl sge = e as SubgroupGroupElementBCImpl;

            if (sge == null)
            {
                throw new InvalidUProveArtifactException(
                          "Invalid group element (wrong construction)");
            }

            // verify that 1 < g < p
            if (sge.i <= BCBigInt.One || sge.i >= pValue)
            {
                throw new InvalidUProveArtifactException(
                          "Invalid group element (out of range)");
            }

            // verify that g^q mod p = 1
            BCBigInt modpow = sge.i.ModPow(qValue, pValue);

            if (sge.i.ModPow(qValue, pValue) != BCBigInt.One)
            {
                throw new InvalidUProveArtifactException(
                          "Invalid group element (i^Q mod P != 1)");
            }
        }
Пример #3
0
        /// <summary>
        /// Returns a random BigInteger x such that 0 &lt;= x &lt; max.
        /// </summary>
        /// <param name="max">Maximal value (exclusive).</param>
        /// <returns>A random BigInteger.</returns>
        private static BCBigInt GetRandomValue(BCBigInt max)
        {
            if (max <= BCBigInt.Zero)
            {
                throw new ArgumentException("max must be greater than zero");
            }

            int      length = max.ToByteArray().Length;
            BCBigInt bi;

            do
            {
                // randomly generate an array with a trailing 0 byte
                byte[] randomBytes = new byte[length];
                rngCSP.GetBytes(randomBytes);
                // generate a random positive BigInteger
                bi = new BCBigInt(1, randomBytes);
            } while (
                // Make sure the value is smaller than max to avoid
                // bias in the RNG. This would open up
                // attacks on the system (see Bleichenbacher's attack
                // on FIPS 186's RNG). This technique is equivalent to
                // NIST SP 800-90 (draft)'s "simple discard method"
                // (section B.5.1.1).
                (bi >= max));

            return(bi);
        }
Пример #4
0
        /// <summary>
        /// Generates a random Zq element.
        /// </summary>
        /// <param name="nonZero">True to return a non-zero element.</param>
        /// <param name="maxBitLength">Maximum lenght of the random element, or -1 for full size elements.</param>
        /// <returns>A random Zq element.</returns>
        public override FieldZqElement GetRandomElement(bool nonZero, int maxBitLength = -1)
        {
            BCBigInt element = null;

            do
            {
                BCBigInt max = null;
                if (maxBitLength > 0)
                {
                    if (TwoToTheX.ContainsKey(maxBitLength))
                    {
                        max = TwoToTheX[maxBitLength];
                    }
                    else
                    {
                        max = BCBigInt.Two.Pow(maxBitLength);
                        TwoToTheX.Add(maxBitLength, max);
                    }
                }
                else
                {
                    max = this.modulus;
                }
                element = GetRandomValue(max);
            } while (nonZero && element == 0);

            return(new FieldZqElementBCImpl(element, this));
        }
Пример #5
0
 /// <summary>
 /// Constructs a FieldZqImpl.
 /// </summary>
 /// <param name="modulus">The field modulus</param>
 public FieldZqBCImpl(byte[] modulus)
 {
     if (modulus == null) throw new ArgumentNullException("modulus");
     this.modulusBytes = modulus;
     this.modulus = new BCBigInt(1, modulus);
     Zero = new FieldZqElementBCImpl(BCBigInt.Zero, this);
     One = new FieldZqElementBCImpl(BCBigInt.One, this);
 }
        /// <summary>
        /// Constructs a new SubgroupGroupElement.
        /// </summary>
        /// <param name="i">The element value.</param>
        /// <param name="p">The modulus.</param>
        internal SubgroupGroupElementBCImpl(BCBigInt i, BCBigInt p)
        {
            if (i == null || p == null)
            {
                throw new ArgumentNullException();
            }

            this.i = i;
            this.p = p;
        }
        /// <summary>
        /// Constructs a new SubgroupGroupElement.
        /// </summary>
        /// <param name="i">The element value.</param>
        /// <param name="p">The modulus.</param>
        internal SubgroupGroupElementBCImpl(BCBigInt i, BCBigInt p)
        {
            if (i == null || p == null)
            {
                throw new ArgumentNullException();
            }

            this.i = i;
            this.p = p;
        }
Пример #8
0
 /// <summary>
 /// Constructs a FieldZqImpl.
 /// </summary>
 /// <param name="modulus">The field modulus</param>
 public FieldZqBCImpl(byte[] modulus)
 {
     if (modulus == null)
     {
         throw new ArgumentNullException("modulus");
     }
     this.modulusBytes = modulus;
     this.modulus      = new BCBigInt(1, modulus);
     Zero = new FieldZqElementBCImpl(BCBigInt.Zero, this);
     One  = new FieldZqElementBCImpl(BCBigInt.One, this);
 }
Пример #9
0
        /// <summary>
        /// Verifies that the group is correctly constructed.
        /// </summary>
        /// <exception cref="InvalidUProveArtifactException">
        /// Thrown if the group parameters are invalid.</exception>
        public override void Verify()
        {
            // verify that p is an odd prime
            if (pValue <= BCBigInt.Two ||
                !pValue.IsProbablePrime(ProtocolHelper.PrimalityTestingCertainty))
            {
                throw new InvalidUProveArtifactException(
                          "Invalid group: P is not an odd prime");
            }

            // verify that q is an odd prime
            if (qValue <= BCBigInt.Two ||
                !qValue.IsProbablePrime(ProtocolHelper.PrimalityTestingCertainty))
            {
                throw new InvalidUProveArtifactException(
                          "Invalid group: Q is not an odd prime");
            }

            // verify that q divides p - 1
            BCBigInt remainder;

            BCBigInt.DivRem(pValue - BCBigInt.One, qValue, out remainder);
            if (remainder != BCBigInt.Zero)
            {
                throw new InvalidUProveArtifactException(
                          "Invalid group: Q does not divide P-1)");
            }

            // verify that g is a group element
            try
            {
                ValidateGroupElement(G);
            }
            catch (InvalidUProveArtifactException)
            {
                throw new InvalidUProveArtifactException(
                          "Invalid group: G is not a group element");
            }
        }
 /// <summary>
 /// Internal only constructor for a Bouncy Castle based field Zq element.
 /// </summary>
 /// <param name="i">The value of the element.</param>
 /// <param name="field">The field to which the element belongs.</param>
 internal FieldZqElementBCImpl(BCBigInt i, FieldZqBCImpl field)
 {
     this.i = i;
     this.field = field;
 }
Пример #11
0
        /// <summary>
        /// Returns a random BigInteger x such that 0 &lt;= x &lt; max. 
        /// </summary>
        /// <param name="max">Maximal value (exclusive).</param>
        /// <returns>A random BigInteger.</returns>
        private static BCBigInt GetRandomValue(BCBigInt max)
        {
            if (max <= BCBigInt.Zero)
            {
                throw new ArgumentException("max must be greater than zero");
            }
            
            int length = max.ToByteArray().Length;
            BCBigInt bi;
            do
            {
                // randomly generate an array with a trailing 0 byte
                byte[] randomBytes = new byte[length];
                rngCSP.GetBytes(randomBytes);
                // generate a random positive BigInteger
                bi = new BCBigInt(1, randomBytes);
            } while (
                // Make sure the value is smaller than max to avoid
                // bias in the RNG. This would open up
                // attacks on the system (see Bleichenbacher's attack
                // on FIPS 186's RNG). This technique is equivalent to
                // NIST SP 800-90 (draft)'s "simple discard method"
                // (section B.5.1.1).
                    (bi >= max));

            return bi;
        }
Пример #12
0
        /// <summary>
        /// This method implements the method defined in recommended parameters spec
        /// </summary>
        public override GroupElement DeriveElement(
            byte[] context,
            byte index,
            out int counter)
        {
            byte[] ggen = new byte[] { (byte)0x67, (byte)0x67, (byte)0x65, (byte)0x6E };

            string hashAlg   = null;
            int    bitlength = qValue.BitLength;

            if (bitlength >= 512)
            {
                hashAlg = "SHA-512";
            }
            else if (bitlength >= 256)
            {
                hashAlg = "SHA-256";
            }
            else if (bitlength >= 160)
            {
                hashAlg = "SHA1";
            }
            else
            {
                throw new ArgumentException("q is too small");
            }
            HashFunction hash = new HashFunction(hashAlg);

            // references to "step x" in comments refer to alg from apendix A.2.3 of FIPS 186-3
            // int N = this.q.BitLength; // step 2 (usused)
            BCBigInt e = (pValue - BCBigInt.One) / qValue; // step 3

            // prepare U array =  context || "ggen" || index || count
            byte[] contextBytes  = (context == null ? new byte[] {} : context);
            int    contextLength = (contextBytes == null ? 0 : contextBytes.Length);

            byte[] U = new byte[contextLength +
                                ggen.Length + 2];
            int arrayIndex = 0;

            if (contextLength > 0)
            {
                Array.Copy(contextBytes, 0, U, arrayIndex, contextLength);
                arrayIndex += contextLength;
            }
            Array.Copy(ggen, 0, U, arrayIndex, ggen.Length);
            U[U.Length - 2] = index;

            byte     count = 0; // step 4
            BCBigInt g     = BCBigInt.Zero;

            while (g < BCBigInt.Two) // step 10
            {
                if (count == 255)
                {
                    throw new InvalidUProveArtifactException(
                              "can't derive an element; count exceeded");
                }
                count++;                 // step 5
                // complete U array
                U[U.Length - 1] = count; // step 7
                hash.HashWithoutFormatting(U);

                // BUGBUG: is that ok, will that wrap correctly?
                BCBigInt W = new BCBigInt(1, hash.Digest); // step 8
                g = W.ModPow(e, pValue);                   // step 9
            }

            counter = count;
            return(new SubgroupGroupElementBCImpl(g, pValue));
        }
        /// <summary>
        /// This method implements the method defined in recommended parameters spec
        /// </summary>
        public override GroupElement DeriveElement(
            byte[] context, 
            byte index, 
            out int counter)
        {
            byte[] ggen = new byte[] { (byte)0x67, (byte)0x67, (byte)0x65, (byte)0x6E };

            string hashAlg = null;
            int bitlength = qValue.BitLength;
            if (bitlength >= 512)
            {
                hashAlg = "SHA-512";
            }
            else if (bitlength >= 256)
            {
                hashAlg = "SHA-256";
            }
            else if (bitlength >= 160)
            {
                hashAlg = "SHA1";
            }
            else
            {
                throw new ArgumentException("q is too small");
            }
            HashFunction hash = new HashFunction(hashAlg);

            // references to "step x" in comments refer to alg from apendix A.2.3 of FIPS 186-3
            // int N = this.q.BitLength; // step 2 (usused)
            BCBigInt e = (pValue - BCBigInt.One) / qValue; // step 3
            
            // prepare U array =  context || "ggen" || index || count
            byte[] contextBytes = (context == null ? new byte[] {} : context);
            int contextLength = (contextBytes == null ? 0 : contextBytes.Length);
            byte[] U = new byte[contextLength + 
                ggen.Length + 2];
            int arrayIndex = 0;
            if (contextLength > 0)
            {
                Array.Copy(contextBytes, 0, U, arrayIndex, contextLength);
                arrayIndex += contextLength;
            }
            Array.Copy(ggen, 0, U, arrayIndex, ggen.Length);
            U[U.Length - 2] = index;

            byte count = 0; // step 4
            BCBigInt g = BCBigInt.Zero;
            while (g < BCBigInt.Two) // step 10
            {
                if (count == 255)
                {
                    throw new InvalidUProveArtifactException(
                        "can't derive an element; count exceeded");
                }
                count++; // step 5
                // complete U array
                U[U.Length - 1] = count; // step 7
                hash.HashWithoutFormatting(U);

                // BUGBUG: is that ok, will that wrap correctly?
                BCBigInt W = new BCBigInt(1, hash.Digest); // step 8 
                g = W.ModPow(e, pValue); // step 9
            }

            counter = count;
            return new SubgroupGroupElementBCImpl(g, pValue);
        }
 /// <summary>
 /// Internal only constructor for a Bouncy Castle based field Zq element.
 /// </summary>
 /// <param name="i">The value of the element.</param>
 /// <param name="field">The field to which the element belongs.</param>
 internal FieldZqElementBCImpl(BCBigInt i, FieldZqBCImpl field)
 {
     this.i     = i;
     this.field = field;
 }
Пример #15
0
        private BouncyCastle.FpFieldElement GetX(
            byte[] input, 
            BouncyCastle.FpCurve curve, 
            int index, 
            int counter)
        {
            int numIterations = (int)System.Math.Ceiling(
                (double)(curve.Q.BitLength / 8) / (double)hashByteSize);

            byte[] digest = new byte[numIterations * hashByteSize];

            for (int iteration = 0; iteration < numIterations; iteration++)
            {
                byte[] hashInput = ProtocolHelper.Concatenate(
                    input, 
                    encoding.GetBytes(
                        index.ToString() + counter.ToString() + iteration.ToString()));
                hash.HashWithoutFormatting(hashInput);
                Array.Copy(hash.Digest, 0, digest, hashByteSize * iteration, hashByteSize);
            }

            BCBigInt x = new BCBigInt(1, digest).Mod(curve.Q);
            return curve.FromBigInteger(x) as BouncyCastle.FpFieldElement;
        }