예제 #1
0
        public override void GenerateKey(ECCurve curve)
        {
            curve.Validate();
            int keySizeInByted = curve.Prime.Length;

            KeySize = keySizeInByted * 8;

            BigInteger
                prime         = Normalize(new BigInteger(curve.Prime), s_modulus),
                subgroupOrder = Normalize(new BigInteger(curve.Order), s_modulus) / Normalize(new BigInteger(curve.Cofactor), s_modulus),
                a             = Normalize(new BigInteger(curve.A), s_modulus);

            byte[]     privateKey = new byte[keySizeInByted];
            BigInteger key;

            do
            {
                StaticRandomNumberGenerator.GetBytes(privateKey);
                key = Normalize(new BigInteger(privateKey), s_modulus);
            } while (BigInteger.Zero >= key || key >= subgroupOrder);

            var basePoint = new BigIntegerPoint(curve.G, s_modulus);

            ECPoint publicKey = BigIntegerPoint.Multiply(basePoint, key, prime, a).ToECPoint(KeySize);

            EraseData(ref _privateKey);
            _curve         = curve.Clone();
            _publicKey     = publicKey;
            _privateKey    = privateKey;
            _parametersSet = true;
        }
예제 #2
0
        public static BigIntegerPoint Multiply(BigIntegerPoint point, BigInteger multiplier, BigInteger prime, BigInteger a)
        {
            BigIntegerPoint result = point;

            multiplier--;

            while (multiplier > BigInteger.Zero)
            {
                if ((multiplier % s_two) != BigInteger.Zero)
                {
                    if ((result.X == point.X) && (result.Y == point.Y))
                    {
                        result = MultipleTwo(result, prime, a);
                    }
                    else
                    {
                        result = Add(result, point, prime);
                    }
                    multiplier--;
                }

                multiplier /= s_two;
                point       = MultipleTwo(point, prime, a);
            }

            return(result);
        }
예제 #3
0
        private static BigIntegerPoint MultipleTwo(BigIntegerPoint value, BigInteger prime, BigInteger a)
        {
            BigInteger
                dy     = Normalize(s_three * BigInteger.Pow(value.X, 2) + a, prime),
                dx     = Normalize(s_two * value.Y, prime),
                lambda = (dy * BigInteger.ModPow(dx, prime - s_two, prime)) % prime,
                x      = Normalize((BigInteger.Pow(lambda, 2) - s_two * value.X) % prime, prime);

            return(new BigIntegerPoint
            {
                X = x,
                Y = Normalize((lambda * (value.X - x) - value.Y) % prime, prime)
            });
        }
예제 #4
0
        public static BigIntegerPoint Add(BigIntegerPoint left, BigIntegerPoint right, BigInteger prime)
        {
            BigInteger
                dy     = Normalize(right.Y - left.Y, prime),
                dx     = Normalize(right.X - left.X, prime),
                lambda = Normalize((dy * BigInteger.ModPow(dx, prime - s_two, prime)) % prime, prime),
                x      = Normalize((BigInteger.Pow(lambda, 2) - left.X - right.X) % prime, prime);

            return(new BigIntegerPoint()
            {
                X = x,
                Y = Normalize((lambda * (left.X - x) - left.Y) % prime, prime),
            });
        }
예제 #5
0
        /// <summary>
        /// Verifies a digital signature against the specified hash value.
        /// </summary>
        /// <param name="hash">
        /// The hash value of a block of data.
        /// </param>
        /// <param name="signature">
        /// The digital signature to be verified.
        /// </param>
        /// <returns>
        /// <c>true</c> if the hash value equals the decrypted signature;
        /// otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="hash"/> parameter is <c>null</c>.
        /// -or-
        /// The <paramref name="signature"/> parameter is <c>null</c>.
        /// </exception>
        public override bool VerifyHash(byte[] hash, byte[] signature)
        {
            if (hash == null)
            {
                throw new ArgumentNullException(nameof(hash));
            }
            if (signature == null)
            {
                throw new ArgumentNullException(nameof(signature));
            }

            ThrowIfDisposed();

            if (KeySize / 8 != hash.Length)
            {
                throw new CryptographicException(string.Format(CultureInfo.CurrentCulture, CryptographicInvalidHashSize, KeySize / 8));
            }
            if (KeySize / 4 != signature.Length)
            {
                throw new CryptographicException(string.Format(CultureInfo.CurrentCulture, CryptographicInvalidSignatureSize, KeySize / 4));
            }

            // There is no necessity to generate new parameter, just return false
            if (!_parametersSet)
            {
                return(false);
            }

            int keySizeInByted = KeySize / 8;

            BigInteger
                subgroupOrder = Normalize(new BigInteger(_curve.Order), s_modulus) / Normalize(new BigInteger(_curve.Cofactor), s_modulus);

            byte[] array = new byte[keySizeInByted];

            BlockCopy(signature, 0, array, 0, keySizeInByted);
            BigInteger s = Normalize(new BigInteger(array), s_modulus);

            if (s < BigInteger.One || s > subgroupOrder)
            {
                return(false);
            }

            BlockCopy(signature, keySizeInByted, array, 0, keySizeInByted);
            BigInteger r = Normalize(new BigInteger(array), s_modulus);

            if (r < BigInteger.One || r > subgroupOrder)
            {
                return(false);
            }

            BigInteger e = Normalize(new BigInteger(hash), s_modulus) % subgroupOrder;

            if (e == BigInteger.Zero)
            {
                e = BigInteger.One;
            }

            BigInteger
                v     = BigInteger.ModPow(e, subgroupOrder - 2, subgroupOrder),
                z1    = (s * v) % subgroupOrder,
                z2    = (subgroupOrder - r) * v % subgroupOrder,
                prime = Normalize(new BigInteger(_curve.Prime), s_modulus),
                a     = Normalize(new BigInteger(_curve.A), s_modulus);

            BigIntegerPoint c = BigIntegerPoint.Add(
                BigIntegerPoint.Multiply(new BigIntegerPoint(_curve.G, s_modulus), z1, prime, a),
                BigIntegerPoint.Multiply(new BigIntegerPoint(_publicKey, s_modulus), z2, prime, a),
                prime);

            return(c.X == r);
        }
예제 #6
0
        /// <summary>
        /// Generates a digital signature for the specified hash value.
        /// </summary>
        /// <param name="hash">
        /// The hash value of the data that is being signed.
        /// </param>
        /// <returns>
        /// A digital signature that consists of the given hash value encrypted with the private key.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="hash"/> parameter is <c>null</c>.
        /// </exception>
        public override byte[] SignHash(byte[] hash)
        {
            if (hash == null)
            {
                throw new ArgumentNullException(nameof(hash));
            }

            ThrowIfDisposed();

            if (KeySize / 8 != hash.Length)
            {
                throw new CryptographicException(string.Format(CultureInfo.CurrentCulture, CryptographicInvalidHashSize, KeySize / 8));
            }

            int keySizeInByted = KeySize / 8;

            if (!_parametersSet)
            {
                GenerateKey(GetDefaultCurve());
            }

            BigInteger
                subgroupOrder = Normalize(new BigInteger(_curve.Order), s_modulus) / Normalize(new BigInteger(_curve.Cofactor), s_modulus);

            BigInteger e = Normalize(new BigInteger(hash), s_modulus) % subgroupOrder;

            if (e == BigInteger.Zero)
            {
                e = BigInteger.One;
            }

            BigInteger
                prime = Normalize(new BigInteger(_curve.Prime), s_modulus),
                a = Normalize(new BigInteger(_curve.A), s_modulus),
                d = Normalize(new BigInteger(_privateKey), s_modulus),
                k, r, s;

            var rgb = new byte[keySizeInByted];

            do
            {
                do
                {
                    do
                    {
                        StaticRandomNumberGenerator.GetBytes(rgb);
                        k = Normalize(new BigInteger(rgb), s_modulus);
                    } while (k <= BigInteger.Zero || k >= subgroupOrder);

                    r = BigIntegerPoint.Multiply(new BigIntegerPoint(_curve.G, s_modulus), k, prime, a).X;
                } while (r == BigInteger.Zero);

                s = (r * d + k * e) % subgroupOrder;
            } while (s == BigInteger.Zero);

            byte[]
            signature = new byte[keySizeInByted * 2],
            array = s.ToByteArray();

            BlockCopy(array, 0, signature, 0, Min(array.Length, keySizeInByted));
            array = r.ToByteArray();
            BlockCopy(array, 0, signature, keySizeInByted, Min(array.Length, keySizeInByted));

            return(signature);
        }