public void TestRsaDigestSigner()
        {
            BigInteger rsaPubMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
            BigInteger rsaPubExp = new BigInteger(Base64.Decode("EQ=="));
            BigInteger rsaPrivMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
            BigInteger rsaPrivDP = new BigInteger(Base64.Decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ=="));
            BigInteger rsaPrivDQ = new BigInteger(Base64.Decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ=="));
            BigInteger rsaPrivExp = new BigInteger(Base64.Decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E="));
            BigInteger rsaPrivP = new BigInteger(Base64.Decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE="));
            BigInteger rsaPrivQ = new BigInteger(Base64.Decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0="));
            BigInteger rsaPrivQinv = new BigInteger(Base64.Decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg=="));
            RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaPubMod, rsaPubExp);
			RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);

            byte[] msg = new byte[] { 1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23 };

            RsaDigestSigner signer = new RsaDigestSigner(new Sha1Digest());
            signer.Init(true, rsaPrivate);
            signer.BlockUpdate(msg, 0, msg.Length);
            byte[] sig = signer.GenerateSignature();

            signer.Init(false,rsaPublic);
            signer.BlockUpdate(msg, 0, msg.Length);
            Assert.IsTrue(signer.VerifySignature(sig), "RSA IDigest Signer failed.");
        }
        internal BigInteger CalculatePublic(
			BigInteger	p,
			BigInteger	g,
			BigInteger	x)
        {
            return g.ModPow(x, p);
        }
示例#3
0
        /// <summary>
        /// Derive the public key by doing a point multiply of G * priv.
        /// </summary>
        private static byte[] pPublicKeyFromPrivate(Org.BouncyCastle.Math.BigInteger privKey, bool compressedPublicKey)
        {
            if (!compressedPublicKey)
            {
                //not compressed public key
                return(_ecParams.G.Multiply(privKey).GetEncoded());
            }

            //below is for compressed public key
            int Y = _ecParams.G.Multiply(privKey).YCoord.ToBigInteger().IntValue;

            byte b;

            if (Y % 2 == 0)
            {
                b = 2;
            }
            else
            {
                b = 3;
            }

            byte[] pub = _ecParams.G.Multiply(privKey).GetEncoded().Take(33).ToArray();
            pub[0] = b;
            return(pub);
        }
 protected ECPublicBcpgKey(
     DerObjectIdentifier oid,
     ECPoint point)
 {
     this.point = new BigInteger(1, point.GetEncoded());
     this.oid = oid;
 }
        /// <summary>
        /// Computes the public key from the private key.
        /// </summary>
        protected override byte[] ComputePublicKey()
        {
            var     ps    = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");
            ECPoint point = ps.G;

            Org.BouncyCastle.Math.BigInteger Db = new Org.BouncyCastle.Math.BigInteger(1, _privKey);
            ECPoint dd = point.Multiply(Db);


            if (IsCompressedPoint)
            {
                dd = ps.Curve.CreatePoint(dd.X.ToBigInteger(), dd.Y.ToBigInteger(), true);
                return(dd.GetEncoded());
            }
            else
            {
                byte[] pubaddr = new byte[65];
                byte[] Y       = dd.Y.ToBigInteger().ToByteArray();
                Array.Copy(Y, 0, pubaddr, 64 - Y.Length + 1, Y.Length);
                byte[] X = dd.X.ToBigInteger().ToByteArray();
                Array.Copy(X, 0, pubaddr, 32 - X.Length + 1, X.Length);
                pubaddr[0] = 4;
                return(pubaddr);
            }
        }
 protected ECPublicBcpgKey(
     DerObjectIdentifier oid,
     BigInteger encodedPoint)
 {
     this.point = encodedPoint;
     this.oid = oid;
 }
示例#7
0
		private static ECPoint ImplShamirsTrick(ECPoint P, BigInteger k,
			ECPoint Q, BigInteger l)
		{
			int m = System.Math.Max(k.BitLength, l.BitLength);
			ECPoint Z = P.Add(Q);
			ECPoint R = P.Curve.Infinity;

			for (int i = m - 1; i >= 0; --i)
			{
				R = R.Twice();

				if (k.TestBit(i))
				{
					if (l.TestBit(i))
					{
						R = R.Add(Z);
					}
					else
					{
						R = R.Add(P);
					}
				}
				else
				{
					if (l.TestBit(i))
					{
						R = R.Add(Q);
					}
				}
			}

			return R;
		}
		public DHPrivateKeyParameters(
            BigInteger		x,
            DHParameters	parameters)
			: base(true, parameters)
        {
            this.x = x;
        }
示例#9
0
        public RSA(int bits)
        {
            p = Helper.GenerateBigIntegerPrimes(bits);
            //p = new Org.BouncyCastle.Math.BigInteger("3557");
            q = Helper.GenerateBigIntegerPrimes(bits);
            //q = new Org.BouncyCastle.Math.BigInteger("2579");
            Console.WriteLine("p generated " + p);
            Console.WriteLine("q generated " + q);
            n = p.Multiply(q);
            Console.WriteLine("n = " + n);
            BigInteger p1 = p.Subtract(new BigInteger("1"));
            BigInteger q1 = q.Subtract(new BigInteger("1"));

            fn = p1.Multiply(q1);
            Console.WriteLine("Функция Эйлера = " + fn);
            int[]  er   = new[] { 17, 257, 65537 };
            Random rand = new Random((int)System.DateTime.Now.Ticks);

            e = new BigInteger(er[rand.Next(0, er.Length)].ToString());
            Console.WriteLine("e = " + e);

            d = e.ModInverse(fn);
            Console.WriteLine("d = " + d);

            Console.WriteLine("Public Key: " + e + ", " + n);
            Console.WriteLine("Private Key: " + d + ", " + n);
        }
		/// <param name="n">The modulus.</param>
		/// <param name="e">The public exponent.</param>
		public RsaPublicBcpgKey(
			BigInteger	n,
			BigInteger	e)
		{
			this.n = new MPInteger(n);
			this.e = new MPInteger(e);
		}
		public X9ECParameters(
            ECCurve		curve,
            ECPoint		g,
            BigInteger	n)
            : this(curve, g, n, BigInteger.One, null)
        {
        }
		public ECPrivateKeyStructure(
            BigInteger key)
        {
			this.seq = new DerSequence(
				new DerInteger(1),
				new DerOctetString(key.ToByteArrayUnsigned()));
        }
示例#13
0
        /**
         * generate a signature for the given message using the key we were
         * initialised with. For conventional Gost3410 the message should be a Gost3411
         * hash of the message of interest.
         *
         * @param message the message that will be verified later.
         */
        public BigInteger[] GenerateSignature(
			byte[] message)
        {
            byte[] mRev = new byte[message.Length]; // conversion is little-endian
            for (int i = 0; i != mRev.Length; i++)
            {
                mRev[i] = message[mRev.Length - 1 - i];
            }

            BigInteger m = new BigInteger(1, mRev);
            Gost3410Parameters parameters = key.Parameters;
            BigInteger k;

            do
            {
                k = new BigInteger(parameters.Q.BitLength, random);
            }
            while (k.CompareTo(parameters.Q) >= 0);

            BigInteger r = parameters.A.ModPow(k, parameters.P).Mod(parameters.Q);

            BigInteger s = k.Multiply(m).
                Add(((Gost3410PrivateKeyParameters)key).X.Multiply(r)).
                Mod(parameters.Q);

            return new BigInteger[]{ r, s };
        }
		public TimeStampRequest Generate(
			string		digestAlgorithmOid,
			byte[]		digest,
			BigInteger	nonce)
		{
			if (digestAlgorithmOid == null)
			{
				throw new ArgumentException("No digest algorithm specified");
			}

			DerObjectIdentifier digestAlgOid = new DerObjectIdentifier(digestAlgorithmOid);

			AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOid, DerNull.Instance);
			MessageImprint messageImprint = new MessageImprint(algID, digest);

			X509Extensions  ext = null;

			if (extOrdering.Count != 0)
			{
				ext = new X509Extensions(extOrdering, extensions);
			}

			DerInteger derNonce = nonce == null
				?	null
				:	new DerInteger(nonce);

			return new TimeStampRequest(
				new TimeStampReq(messageImprint, reqPolicy, derNonce, certReq, ext));
		}
		public RsaPrivateCrtKeyParameters(
            BigInteger	modulus,
            BigInteger	publicExponent,
            BigInteger	privateExponent,
            BigInteger	p,
            BigInteger	q,
            BigInteger	dP,
            BigInteger	dQ,
            BigInteger	qInv)
			: base(true, modulus, privateExponent)
        {
			ValidateValue(publicExponent, "publicExponent", "exponent");
			ValidateValue(p, "p", "P value");
			ValidateValue(q, "q", "Q value");
			ValidateValue(dP, "dP", "DP value");
			ValidateValue(dQ, "dQ", "DQ value");
			ValidateValue(qInv, "qInv", "InverseQ value");

			this.e = publicExponent;
            this.p = p;
            this.q = q;
            this.dP = dP;
            this.dQ = dQ;
            this.qInv = qInv;
        }
        /**
        * Return a random BigInteger not less than 'min' and not greater than 'max'
        * 
        * @param min the least value that may be generated
        * @param max the greatest value that may be generated
        * @param random the source of randomness
        * @return a random BigInteger value in the range [min,max]
        */
        public static BigInteger CreateRandomInRange(
            BigInteger		min,
            BigInteger		max,
            // TODO Should have been just Random class
            SecureRandom	random)
        {
            int cmp = min.CompareTo(max);
            if (cmp >= 0)
            {
                if (cmp > 0)
                    throw new ArgumentException("'min' may not be greater than 'max'");

                return min;
            }

            if (min.BitLength > max.BitLength / 2)
            {
                return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min);
            }

            for (int i = 0; i < MaxIterations; ++i)
            {
                BigInteger x = new BigInteger(max.BitLength, random);
                if (x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0)
                {
                    return x;
                }
            }

            // fall back to a faster (restricted) method
            return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min);
        }
示例#17
0
        internal BigInteger CalculatePrivate(
			BigInteger		p,
			SecureRandom	random,
			int				limit)
        {
            //
            // calculate the private key
            //
            BigInteger pSub2 = p.Subtract(BigInteger.Two);
            BigInteger x;

            if (limit == 0)
            {
                x = createInRange(pSub2, random);
            }
            else
            {
                do
                {
                    // TODO Check this (should the generated numbers always be odd,
                    // and length 'limit'?)
                    x = new BigInteger(limit, 0, random);
                }
                while (x.SignValue == 0);
            }

            return x;
        }
示例#18
0
		public ECDomainParameters(
            ECCurve     curve,
            ECPoint     g,
            BigInteger  n)
			: this(curve, g, n, BigInteger.One)
        {
        }
示例#19
0
        public BigInteger ConvertInput(
			byte[]	inBuf,
			int		inOff,
			int		inLen)
        {
            int maxLength = (bitSize + 7) / 8;

            if (inLen > maxLength)
                throw new DataLengthException("input too large for RSA cipher.");

            byte[] block;
            if (inOff != 0 || inLen != inBuf.Length)
            {
                block = new byte[inLen];
                Array.Copy(inBuf, inOff, block, 0, inLen);
            }
            else
            {
                block = inBuf;
            }

            BigInteger input = new BigInteger(1, block);

            if (input.CompareTo(key.Modulus) >= 0)
                throw new DataLengthException("input too large for RSA cipher.");

            return input;
        }
示例#20
0
		public void TestECNR239bitPrime()
		{
			BigInteger r = new BigInteger("308636143175167811492623515537541734843573549327605293463169625072911693");
			BigInteger s = new BigInteger("852401710738814635664888632022555967400445256405412579597015412971797143");

			byte[] kData = new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655").ToByteArrayUnsigned();

			SecureRandom k = FixedSecureRandom.From(kData);

			ECCurve curve = new FpCurve(
				new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
				new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
				new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b

			ECDomainParameters spec = new ECDomainParameters(
				curve,
				curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
				new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n

			ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
				new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
				spec);

			ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
				curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
				spec);

			ISigner sgr = SignerUtilities.GetSigner("SHA1withECNR");
			byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };

			checkSignature(239, priKey, pubKey, sgr, k, message, r, s);
		}
        /**
         * which Generates the p and g values from the given parameters,
         * returning the DHParameters object.
         * <p>
         * Note: can take a while...</p>
         */
        public virtual DHParameters GenerateParameters()
        {
            //
            // find a safe prime p where p = 2*q + 1, where p and q are prime.
            //
            BigInteger[] safePrimes = DHParametersHelper.GenerateSafePrimes(size, certainty, random);

            BigInteger p = safePrimes[0];
            BigInteger q = safePrimes[1];

            BigInteger g;
            int qLength = size - 1;

            //
            // calculate the generator g - the advantage of using the 2q+1
            // approach is that we know the prime factorisation of (p - 1)...
            //
            do
            {
                g = new BigInteger(qLength, random);
            }
            while (g.ModPow(BigInteger.Two, p).Equals(BigInteger.One)
                || g.ModPow(q, p).Equals(BigInteger.One));

            return new DHParameters(p, g, q, 2);
        }
		public RsaPublicKeyStructure(
            BigInteger	modulus,
            BigInteger	publicExponent)
        {
            this.modulus = modulus;
            this.publicExponent = publicExponent;
        }
		public Gost3410Parameters(
			BigInteger	p,
			BigInteger	q,
			BigInteger	a)
			: this(p, q, a, null)
		{
		}
        /**
         * Given the domain parameters this routine Generates an EC key
         * pair in accordance with X9.62 section 5.2.1 pages 26, 27.
         */
        public IAsymmetricCipherKeyPair GenerateKeyPair()
        {
            var n = _parameters.N;
            IBigInteger d;
            do
            {
                d = new BigInteger(n.BitLength, _random);
            }
            while (d.SignValue == 0 || (d.CompareTo(n) >= 0));

            var isEcdh = _algorithm == "ECDH";

            var q = _parameters.G.Multiply(d);

            if (_publicKeyParamSet != null)
            {
                return new AsymmetricCipherKeyPair(
                    isEcdh
                        ? new ECDHPublicKeyParameters(q, _publicKeyParamSet, _hashAlgorithm, _symmetricKeyAlgorithm)
                        : new ECPublicKeyParameters(_algorithm, q, _publicKeyParamSet),
                    new ECPrivateKeyParameters(_algorithm, d, _publicKeyParamSet));
            }
            return new AsymmetricCipherKeyPair(
                isEcdh
                    ? new ECDHPublicKeyParameters(q, _parameters, _hashAlgorithm, _symmetricKeyAlgorithm)
                    : new ECPublicKeyParameters(_algorithm, q, _parameters),
                new ECPrivateKeyParameters(_algorithm, d, _parameters));
        }
示例#25
0
	    /**
	     * Initialises the client to begin new authentication attempt
	     * @param N The safe prime associated with the client's verifier
	     * @param g The group parameter associated with the client's verifier
	     * @param digest The digest algorithm associated with the client's verifier
	     * @param random For key generation
	     */
	    public virtual void Init(BigInteger N, BigInteger g, IDigest digest, SecureRandom random)
	    {
	        this.N = N;
	        this.g = g;
	        this.digest = digest;
	        this.random = random;
	    }
    public static BigInteger Base64StringToBigInteger(string str)
    {
      byte[] binModulus = Convert.FromBase64String(str);
      BigInteger modulus = new BigInteger(1, binModulus);

      return modulus;
    }
示例#27
0
		public RsaSecretBcpgKey(
			BigInteger d,
			BigInteger p,
			BigInteger q)
		{
			// PGP requires (p < q)
			int cmp = p.CompareTo(q);
			if (cmp >= 0)
			{
				if (cmp == 0)
					throw new ArgumentException("p and q cannot be equal");

				BigInteger tmp = p;
				p = q;
				q = tmp;
			}

			this.d = new MPInteger(d);
			this.p = new MPInteger(p);
			this.q = new MPInteger(q);
			this.u = new MPInteger(p.ModInverse(q));

			this.expP = d.Remainder(p.Subtract(BigInteger.One));
			this.expQ = d.Remainder(q.Subtract(BigInteger.One));
			this.crt = q.ModInverse(p);
		}
示例#28
0
		public void TestECNR192bitPrime()
		{
			BigInteger r  = new BigInteger("2474388605162950674935076940284692598330235697454145648371");
			BigInteger s  = new BigInteger("2997192822503471356158280167065034437828486078932532073836");

			byte[] kData = new BigInteger("dcc5d1f1020906df2782360d36b2de7a17ece37d503784af", 16).ToByteArrayUnsigned();

			SecureRandom k = FixedSecureRandom.From(kData);

			FpCurve curve = new FpCurve(
				new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q (or p)
				new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", 16),   // a
				new BigInteger("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", 16));  // b

			ECDomainParameters spec = new ECDomainParameters(
				curve,
				curve.DecodePoint(Hex.Decode("03188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")), // G
				new BigInteger("6277101735386680763835789423176059013767194773182842284081")); // n


			ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
				new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
				spec);

			ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
				curve.DecodePoint(Hex.Decode("0262B12D60690CDCF330BABAB6E69763B471F994DD702D16A5")), // Q
				spec);

			ISigner sgr = SignerUtilities.GetSigner("SHA1withECNR");
			byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };

			checkSignature(192, priKey, pubKey, sgr, k, message, r, s);
		}
示例#29
0
        private RsaKeyParameters MakeKey(String modulusHexString, String exponentHexString, bool isPrivateKey)
        {
            var modulus  = new Org.BouncyCastle.Math.BigInteger(modulusHexString, 16);
            var exponent = new Org.BouncyCastle.Math.BigInteger(exponentHexString, 16);

            return(new RsaKeyParameters(isPrivateKey, modulus, exponent));
        }
示例#30
0
		static TspTestUtil()
		{
			rand = new SecureRandom();

			kpg = GeneratorUtilities.GetKeyPairGenerator("RSA");
			kpg.Init(new RsaKeyGenerationParameters(
				BigInteger.ValueOf(0x10001), rand, 1024, 25));

			desede128kg = GeneratorUtilities.GetKeyGenerator("DESEDE");
			desede128kg.Init(new KeyGenerationParameters(rand, 112));

			desede192kg = GeneratorUtilities.GetKeyGenerator("DESEDE");
			desede192kg.Init(new KeyGenerationParameters(rand, 168));

			rc240kg = GeneratorUtilities.GetKeyGenerator("RC2");
			rc240kg.Init(new KeyGenerationParameters(rand, 40));

			rc264kg = GeneratorUtilities.GetKeyGenerator("RC2");
			rc264kg.Init(new KeyGenerationParameters(rand, 64));

			rc2128kg = GeneratorUtilities.GetKeyGenerator("RC2");
			rc2128kg.Init(new KeyGenerationParameters(rand, 128));

			serialNumber = BigInteger.One;
		}
示例#31
0
        public static string ByteArrayToBase58(byte[] ba)
        {
            Org.BouncyCastle.Math.BigInteger addrremain = new Org.BouncyCastle.Math.BigInteger(1, ba);

            Org.BouncyCastle.Math.BigInteger big0  = new Org.BouncyCastle.Math.BigInteger("0");
            Org.BouncyCastle.Math.BigInteger big58 = new Org.BouncyCastle.Math.BigInteger("58");

            string b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

            string rv = "";

            while (addrremain.CompareTo(big0) > 0)
            {
                int d = Convert.ToInt32(addrremain.Mod(big58).ToString());
                addrremain = addrremain.Divide(big58);
                rv         = b58.Substring(d, 1) + rv;
            }

            // handle leading zeroes
            foreach (byte b in ba)
            {
                if (b != 0)
                {
                    break;
                }
                rv = "1" + rv;
            }
            return(rv);
        }
示例#32
0
        /// <summary>
        /// Creates ECDSA from imported data
        /// </summary>
        /// <param name="type">0 or 1 (1 faster)</param>
        /// <param name="forSign">if created for signing, otherwise for verifying</param>
        /// <param name="import">Imporeted public or private key</param>
        public ECDSAWrapper(int type, bool forSign, byte[] import)
        {
            this.initCurveandParams(type);

            if (forSign)
            {
                try
                {
                    //import - D (BigInteger)
                    SecureRandom random = new SecureRandom();
                    BigInteger Drec = new BigInteger(import);
                    ECPrivateKeyParameters ecPrivImported = new ECPrivateKeyParameters(Drec, this.parameters);
                    ParametersWithRandom ecPrivImportedpwr = new ParametersWithRandom(ecPrivImported, random);
                    this.ecdsa.Init(true, ecPrivImportedpwr);
                }
                catch (Exception ex)
                {
                    throw new Exception("Error while creating ECDSAWrapper from import for signing", ex);
                }
            }
            else
            {
                try
                {
                    //import - Q (ECPoint)
                    ECPoint Qrec = this.ecCurve.DecodePoint(import);
                    ECPublicKeyParameters recPub = new ECPublicKeyParameters(Qrec, this.parameters);
                    this.ecdsa.Init(false, recPub);
                }
                catch (Exception ex)
                {
                    throw new Exception("Error while creating ECDSAWrapperfom import for verifying", ex);
                }
            }
        }
示例#33
0
		public DsaParameters(
            BigInteger	p,
            BigInteger	q,
            BigInteger	g)
			: this(p, q, g, null)
        {
        }
		public IssuerAndSerialNumber(
            X509Name	name,
            BigInteger	serialNumber)
        {
            this.name = name;
            this.serialNumber = new DerInteger(serialNumber);
        }
示例#35
0
        /**
        * Reason being as indicated by ReasonFlags, i.e. ReasonFlags.keyCompromise
        * or 0 if ReasonFlags are not to be used
        **/
        public void AddCrlEntry(
			BigInteger	userCertificate,
			DateTime	revocationDate,
			int			reason)
        {
            tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), reason);
        }
示例#36
0
 public BigInteger Encrypt(BigInteger m)
 {
     /* e = new BigInteger("3");
      * m = new BigInteger("111111");
      * n = new BigInteger("9173503");*/
     Console.WriteLine("Encrypt message: " + m);
     return(m.ModPow(e, n));
 }
示例#37
0
        private static ECPoint DecompressKey(Org.BouncyCastle.Math.BigInteger xBN, bool yBit)
        {
            var curve = ECKey.CreateCurve().Curve;

            byte[] compEnc = X9IntegerConverter.IntegerToBytes(xBN, 1 + X9IntegerConverter.GetByteLength(curve));
            compEnc[0] = (byte)(yBit ? 0x03 : 0x02);
            return(curve.DecodePoint(compEnc));
        }
示例#38
0
        static FixedSecureRandom()
        {
            M.BigInteger check1 = new M.BigInteger(128, new RandomChecker());
            M.BigInteger check2 = new M.BigInteger(120, new RandomChecker());

            isAndroidStyle   = check1.Equals(ANDROID);
            isRegularStyle   = check1.Equals(REGULAR);
            isClasspathStyle = check2.Equals(CLASSPATH);
        }
示例#39
0
        public static string GetPublicKeyFromPrivateKeyEx(string privateKey)

        {
            var curve     = SecNamedCurves.GetByName("secp256k1");
            var domain    = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
            var d         = new Org.BouncyCastle.Math.BigInteger(privateKey);
            var q         = domain.G.Multiply(d);
            var publicKey = new ECPublicKeyParameters(q, domain);

            return(Convert.ToBase64String(publicKey.Q.GetEncoded()));
        }
        /// <summary>
        /// Returns error message in a string if private key is not within the valid range (2 ... N-1)
        /// </summary>
        private string validateRange()
        {
            Org.BouncyCastle.Math.BigInteger Db = new Org.BouncyCastle.Math.BigInteger(1, _privKey);
            BigInteger N = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1").N;

            if (Db == BigInteger.Zero || Db.CompareTo(N) >= 0)
            {
                return("Not a valid private key");
            }
            return(null);
        }
示例#41
0
        public String decipher(List <Org.BouncyCastle.Math.BigInteger> cipher, MHPrivateKey key)
        {
            String decrypted = "";

            Org.BouncyCastle.Math.BigInteger temp = Org.BouncyCastle.Math.BigInteger.ValueOf(0);
            int tmp = 0;

            Org.BouncyCastle.Math.BigInteger bits = Org.BouncyCastle.Math.BigInteger.ValueOf(0);

            for (int i = 0; i < cipher.Count; i++)
            {
                temp = cipher.ElementAt(i);
                int bitlen = temp.BitLength;
                int ff     = 0;
                while (bitlen < (int)Math.Pow(2, ff))
                {
                    ff++;
                }
                if (ff > bitlen)
                {
                    bitlen = ff;
                }

                for (int j = 0; j < bitlen; j++)
                {
                    if (temp.Mod(Org.BouncyCastle.Math.BigInteger.ValueOf(2)).CompareTo(Org.BouncyCastle.Math.BigInteger.ValueOf(1)) == 0)
                    {
                        bits = bits.Add(key.w1.Multiply(Org.BouncyCastle.Math.BigInteger.ValueOf((long)Math.Pow(2, j))));
                    }
                    temp = temp.ShiftRight(1);
                }
                bits = bits.Mod(key.n);
                List <Org.BouncyCastle.Math.BigInteger> list = key.a;
                Org.BouncyCastle.Math.BigInteger        temper;

                int k = key.a.Count - 1;
                while (k >= 0)
                {
                    temper = list.ElementAt(k);
                    if (bits.CompareTo(temper) > -1)
                    {
                        tmp += (int)Math.Pow(2, k);
                        bits = bits.Subtract(temper);
                    }
                    k--;
                }
                decrypted += (binaryToChar(Convert.ToString(tmp, 2))).ToString();

                bits = Org.BouncyCastle.Math.BigInteger.ValueOf(0);
                tmp  = 0;
            }
            return(decrypted);
        }
示例#42
0
 public Org.BouncyCastle.Math.BigInteger getGCD(Org.BouncyCastle.Math.BigInteger bd1, Org.BouncyCastle.Math.BigInteger bd2)
 {
     Org.BouncyCastle.Math.BigInteger bigger  = (bd1.CompareTo(bd2) > 0) ? bd1 : bd2;
     Org.BouncyCastle.Math.BigInteger smaller = (bd1.CompareTo(bd2) < 0) ? bd1 : bd2;
     Org.BouncyCastle.Math.BigInteger gcd     = smaller;
     while (!Org.BouncyCastle.Math.BigInteger.Zero.Equals(smaller))
     {
         gcd     = smaller;
         smaller = bigger.Mod(smaller);
         bigger  = gcd;
     }
     return(gcd);
 }
示例#43
0
        public static BigInteger DefaultServerOnce()
        {
            var bytes = new List <byte>();
            var part1 = BitConverter.GetBytes(0x56781234abcdef00);
            var part2 = BitConverter.GetBytes(0xbcdefabcd0011224);

            bytes.AddRange(part2);
            bytes.AddRange(part1);
            var big = new Org.BouncyCastle.Math.BigInteger(bytes.ToArray());

            return(big);
            //var bytes = new List<byte>();
            //var part1 = BitConverter.GetBytes(0x56781234abcdef00);
            //var part2 = BitConverter.GetBytes(0xbcdefabcd0011224);
            //bytes.AddRange(BitConverter.GetBytes(0x56781234abcdef00));
            //bytes.AddRange(BitConverter.GetBytes(0xbcdefabcd0011224));
            //return new Org.BouncyCastle.Math.BigInteger(bytes.ToArray());
        }
        private void GenerateElGamal(Stream outSecret, Stream outPublic)
        {
            // Prepare a strong Secure Random with seed
            SecureRandom secureRandom = PgpEncryptionUtil.GetSecureRandom();

            IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA");
            DsaParametersGenerator            pGen   = new DsaParametersGenerator();

            pGen.Init((int)PublicKeyLength.BITS_1024, 80, new SecureRandom());  // DSA is 1024 even for long 2048+ ElGamal keys
            DsaParameters dsaParams        = pGen.GenerateParameters();
            DsaKeyGenerationParameters kgp = new DsaKeyGenerationParameters(secureRandom, dsaParams);

            dsaKpg.Init(kgp);

            //
            // this takes a while as the key generator has to Generate some DSA parameters
            // before it Generates the key.
            //
            AsymmetricCipherKeyPair           dsaKp  = dsaKpg.GenerateKeyPair();
            IAsymmetricCipherKeyPairGenerator elgKpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL");

            Group elgamalGroup = Precomputed.GetElGamalGroup((int)this.publicKeyLength);

            if (elgamalGroup == null)
            {
                throw new ArgumentException("ElGamal Group not found for key length: " + this.publicKeyLength);
            }

            Org.BouncyCastle.Math.BigInteger p = elgamalGroup.GetP();
            Org.BouncyCastle.Math.BigInteger g = elgamalGroup.GetG();

            secureRandom = PgpEncryptionUtil.GetSecureRandom();
            ElGamalParameters elParams           = new ElGamalParameters(p, g);
            ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters(secureRandom, elParams);

            elgKpg.Init(elKgp);

            //
            // this is quicker because we are using preGenerated parameters.
            //
            AsymmetricCipherKeyPair elgKp = elgKpg.GenerateKeyPair();

            DsaElGamalKeyGeneratorUtil.ExportKeyPair(outSecret, outPublic, dsaKp, elgKp, identity, passphrase, true);
        }
示例#45
0
    public string GetSign(byte[] msg)
    {
        //Org.BouncyCastle.Math.BigInteger d = new Org.BouncyCastle.Math.BigInteger(Convert.FromBase64String(privKey));
        byte[] prvB = StringToByteArray(prv);
        byte[] pubB = StringToByteArray(pub);
        //byte[] prvB = StringToByteArray(prvTmp);
        //byte[] pubB = StringToByteArray(pubTmp);
        Org.BouncyCastle.Math.BigInteger sk = new Org.BouncyCastle.Math.BigInteger(+1, prvB);
        Org.BouncyCastle.Math.EC.ECPoint q  = domain.G.Multiply(sk);

        byte[]     pubKeyX = q.Normalize().AffineXCoord.GetEncoded();
        byte[]     pubKeyY = q.Normalize().AffineYCoord.GetEncoded();
        BigInteger k       = GenerateRandom();

        //BigInteger k = new BigInteger(+1,StringToByteArray("015B931D9C7BF3A7A70E57868BF29712377E74355FC59032CD7547C80E179010"));
        //Debug.Log("kv:" + BitConverter.ToString(kv.ToByteArray()).Replace("-", ""));
        Debug.Log("K:" + BitConverter.ToString(k.ToByteArray()).Replace("-", ""));
        ECPoint Q = domain.G.Multiply(k);

        Org.BouncyCastle.Crypto.Digests.Sha256Digest digester = new Org.BouncyCastle.Crypto.Digests.Sha256Digest();
        byte[] h = new byte[digester.GetDigestSize()];

        digester.BlockUpdate(Q.GetEncoded(true), 0, Q.GetEncoded(true).Length);
        digester.BlockUpdate(pubB, 0, pubB.Length);
        digester.BlockUpdate(msg, 0, msg.Length);

        digester.DoFinal(h, 0);

        Org.BouncyCastle.Math.BigInteger r = new Org.BouncyCastle.Math.BigInteger(+1, h);

        BigInteger s = r.Multiply(sk);

        s = k.Subtract(s);
        s = s.Mod(domain.n);
        string rt = BitConverter.ToString(r.ToByteArray()).Replace("-", "");

        if (rt.Length > 32)
        {
            rt = rt.Remove(0, 2);
        }
        string st = BitConverter.ToString(s.ToByteArray()).Replace("-", "");

        return(rt + st);
    }
示例#46
0
        private static ECDsa LoadPrivateKey(byte[] key)
        {
            var privKeyInt = new Org.BouncyCastle.Math.BigInteger(+1, key);
            var parameters = SecNamedCurves.GetByName("secp256r1");
            var ecPoint    = parameters.G.Multiply(privKeyInt);
            var privKeyX   = ecPoint.Normalize().XCoord.ToBigInteger().ToByteArrayUnsigned();
            var privKeyY   = ecPoint.Normalize().YCoord.ToBigInteger().ToByteArrayUnsigned();

            return(ECDsa.Create(new ECParameters
            {
                Curve = ECCurve.NamedCurves.nistP256,
                D = privKeyInt.ToByteArrayUnsigned(),
                Q = new ECPoint
                {
                    X = privKeyX,
                    Y = privKeyY
                }
            }));
        }
示例#47
0
        public string GetPublicKey(byte[] privKey)
        {
            var privHex = BitConverter.ToString(privKey).Replace("-", "");

            privHex = privHex.Substring(104, (privHex.Length - 104));
            privKey = StringToByteArray(privHex);

            Org.BouncyCastle.Math.BigInteger d = new Org.BouncyCastle.Math.BigInteger(privKey);
            this.privateKeyParameters = new Org.BouncyCastle.Crypto.Parameters.ECPrivateKeyParameters(d, domain);
            Org.BouncyCastle.Math.EC.ECPoint q = domain.G.Multiply(d);
            this.pubKeyParameters = new Org.BouncyCastle.Crypto.Parameters.ECPublicKeyParameters(q, domain);

            //strip first byte
            var pubBytes         = this.pubKeyParameters.Q.GetEncoded();
            var pubHex           = BitConverter.ToString(pubBytes).Replace("-", "");
            var strippedPubBytes = StringToByteArray(pubHex.Substring(2, (pubHex.Length - 2)));

            return("MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE" + Convert.ToBase64String(strippedPubBytes));
        }
示例#48
0
        public MHKey()
        {
            generator gen = new generator(8);

            Org.BouncyCastle.Math.BigInteger w = gen.w;
            e = new List <Org.BouncyCastle.Math.BigInteger>();
            for (int i = 0; i < gen.a.Count; i++)
            {
                e.Add((w.Multiply(gen.a.ElementAt(i))).Mod(gen.n)); // w*a Mod n ..
            }

            Org.BouncyCastle.Math.BigInteger w1  = Org.BouncyCastle.Math.BigInteger.ValueOf(1);
            Org.BouncyCastle.Math.BigInteger one = Org.BouncyCastle.Math.BigInteger.ValueOf(2);
            while (one.IntValue != 1)
            {
                w1  = w1.Add(Org.BouncyCastle.Math.BigInteger.ValueOf(1)).Mod(gen.n);
                one = w.Multiply(w1).Mod(gen.n);
            }
            privateKey = new MHPrivateKey(gen.a, w.ModInverse(gen.n), gen.n);
        }
示例#49
0
        public generator(int k)
        {
            a = new List <Org.BouncyCastle.Math.BigInteger>();
            Random     rnd = new Random();
            BigInteger tmp;
            BigInteger sum;

            sum = BigInteger.ValueOf(0);
            for (int i = 0; i < k; i++)
            {
                tmp = BigInteger.ValueOf((long)(Math.Pow(2, k + i)));
                a.Add(tmp);
                sum = sum.Add(tmp);
            }
            n = sum.Add(BigInteger.ValueOf(1));
            w = BigInteger.ValueOf(467);
            while (this.getGCD(n, w).CompareTo(BigInteger.ValueOf(1)) != 0)
            {
                w.Add(BigInteger.ValueOf(1));
            }
        }
示例#50
0
        public static string ConvertPrivateToPublic(this string privateHex)
        {
            byte[] hex = ValidateAndGetHexPrivateKey(privateHex, 0x00);
            if (hex == null)
            {
                throw new Exception("Could not convert private key to public key. Bad private key.");
            }
            var ps = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");

            Org.BouncyCastle.Math.BigInteger Db = new Org.BouncyCastle.Math.BigInteger(1, hex.Skip(1).ToArray());
            ECPoint dd = ps.G.Multiply(Db);

            byte[] pubaddr = new byte[65];
            byte[] Y       = dd.Y.ToBigInteger().ToByteArray();
            Array.Copy(Y, 0, pubaddr, 64 - Y.Length + 1, Y.Length);
            byte[] X = dd.X.ToBigInteger().ToByteArray();
            Array.Copy(X, 0, pubaddr, 32 - X.Length + 1, X.Length);
            pubaddr[0] = 4;

            return(ByteArrayToString(pubaddr));
        }
示例#51
0
        static void Main(string[] args)
        {
            Console.WriteLine("Enter bits length: ");
            int bit_len = int.Parse(Console.ReadLine());
            RSA rsa     = new RSA(bit_len);

            Console.WriteLine("Enter string:");

            char[]        array = Console.ReadLine().ToCharArray();
            BigInteger [] enStr = new BigInteger[array.Length];

            for (int i = 0; i < array.Length; ++i)
            {
                enStr[i] = rsa.Encrypt(new BigInteger(Convert.ToString((int)array[i])));
            }

            Console.WriteLine("Encrypted string: ");
            for (int i = 0; i < array.Length; ++i)
            {
                Console.Write(enStr[i].ToString());
            }

            char[] decArray = new char[array.Length];

            Console.WriteLine(" ");
            for (int i = 0; i < array.Length; ++i)
            {
                String decStr = rsa.Decrypt(enStr[i]).ToString();
                Console.WriteLine(decStr);
                decArray[i] = (char)int.Parse(decStr);
            }

            Console.WriteLine("\nDecrypt string: ");
            for (int i = 0; i < decArray.Length; ++i)
            {
                Console.Write(decArray[i]);
            }
        }
示例#52
0
        //Following code from https://bitcointalk.org/index.php?topic=25141.0

        public static byte[] Base58ToByteArray(string base58)
        {
            Org.BouncyCastle.Math.BigInteger bi2 = new Org.BouncyCastle.Math.BigInteger("0");
            string b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

            bool IgnoreChecksum = false;

            foreach (char c in base58)
            {
                if (b58.IndexOf(c) != -1)
                {
                    bi2 = bi2.Multiply(new Org.BouncyCastle.Math.BigInteger("58"));
                    bi2 = bi2.Add(new Org.BouncyCastle.Math.BigInteger(b58.IndexOf(c).ToString()));
                }
                else if (c == '?')
                {
                    IgnoreChecksum = true;
                }
                else
                {
                    return(null);
                }
            }

            byte[] bb = bi2.ToByteArrayUnsigned();

            // interpret leading '1's as leading zero bytes
            foreach (char c in base58)
            {
                if (c != '1')
                {
                    break;
                }
                byte[] bbb = new byte[bb.Length + 1];
                Array.Copy(bb, 0, bbb, 1, bb.Length);
                bb = bbb;
            }

            if (bb.Length < 4)
            {
                return(null);
            }

            if (IgnoreChecksum == false)
            {
                SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider();
                byte[] checksum = sha256.ComputeHash(bb, 0, bb.Length - 4);
                checksum = sha256.ComputeHash(checksum);
                for (int i = 0; i < 4; i++)
                {
                    if (checksum[i] != bb[bb.Length - 4 + i])
                    {
                        return(null);
                    }
                }
            }

            byte[] rv = new byte[bb.Length - 4];
            Array.Copy(bb, 0, rv, 0, bb.Length - 4);
            return(rv);
        }
示例#53
0
 public void swap(int n, int m)
 {
     Org.BouncyCastle.Math.BigInteger tmp = (Org.BouncyCastle.Math.BigInteger)e.ElementAt(m);
     e.Insert(m, e.ElementAt(n));
     e.Insert(n, tmp);
 }
示例#54
0
        public System.Numerics.BigInteger[] Merge(Part[][] parts, int threshold)
        {
            Org.BouncyCastle.Math.BigInteger p1 = new Org.BouncyCastle.Math.BigInteger(p.ToString());
            Console.WriteLine("p1" + p1.ToString());
            int secretSize = parts[0].Length;

            Console.WriteLine("secretsize" + secretSize);
            System.Numerics.BigInteger[] results = new System.Numerics.BigInteger[secretSize];
            string[] secret = new string[secretSize];
            byte[]   ba;
            string   str;
            int      count = 0;

            // loop through each secret partition
            for (int i = 0; i < secretSize; i++)
            {
                Sum = System.Numerics.BigInteger.Zero;
                //doing lagrange interpolation
                for (int j = 0; j < threshold; j++)
                {
                    mult = System.Numerics.BigInteger.One;
                    for (int k = 0; k < threshold; k++)
                    {
                        if (j != k)
                        {
                            System.Numerics.BigInteger numerator   = parts[k][i].GetX();
                            System.Numerics.BigInteger denominator = System.Numerics.BigInteger.Subtract(numerator, parts[j][i].GetX());

                            // take mod of negative number
                            while (System.Numerics.BigInteger.Compare(denominator, System.Numerics.BigInteger.Zero) < 0)
                            {
                                denominator = System.Numerics.BigInteger.Add(denominator, p);
                            }
                            //convert to bouncycastle biginteger to calculate modInverse
                            Org.BouncyCastle.Math.BigInteger denominator1 = new Org.BouncyCastle.Math.BigInteger(denominator.ToString());

                            Org.BouncyCastle.Math.BigInteger invDenominator1 = denominator1.ModInverse(p1);

                            System.Numerics.BigInteger invDenominator = System.Numerics.BigInteger.Parse(invDenominator1.ToString());

                            mult = System.Numerics.BigInteger.Multiply(mult, System.Numerics.BigInteger.Multiply(numerator, invDenominator));

                            mult = System.Numerics.BigInteger.Remainder(mult, p);
                        }
                    }
                    mult = System.Numerics.BigInteger.Multiply(mult, parts[j][i].GetY());

                    mult = System.Numerics.BigInteger.Remainder(mult, p);

                    Sum = System.Numerics.BigInteger.Add(Sum, mult);

                    Sum = System.Numerics.BigInteger.Remainder(Sum, p);
                }

                results[i] = Sum;
            }
            foreach (System.Numerics.BigInteger r in results)
            {
                //Console.WriteLine(r);
                //System.Numerics.BigInteger.TryParse
                ba  = r.ToByteArray();
                str = Encoding.UTF8.GetString(ba);
                //Console.WriteLine(str);
                secret[count++] = str;
            }
            str = string.Join("", secret);
            str.Replace("\n", "");
            return(results);
        }
示例#55
0
 public ECDSASignature(Org.BouncyCastle.Math.BigInteger r, Org.BouncyCastle.Math.BigInteger s)
 {
     R = r;
     S = s;
 }
示例#56
0
 public BigInteger Decrypt(BigInteger c)
 {
     /* d = new BigInteger("6111579");*/
     return(c.ModPow(d, n));
 }
示例#57
0
 public static byte[] FromBigNum(Org.BouncyCastle.Math.BigInteger bi)
 {
     byte[] rgbT = bi.ToByteArrayUnsigned();
     return(rgbT);
 }
示例#58
0
        public static ECKey RecoverFromSignature(int recId, ECDSASignature sig, uint256 message, bool compressed)
        {
            if (recId < 0)
            {
                throw new ArgumentException("recId should be positive");
            }
            if (sig.R.SignValue < 0)
            {
                throw new ArgumentException("r should be positive");
            }
            if (sig.S.SignValue < 0)
            {
                throw new ArgumentException("s should be positive");
            }
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }


            var curve = ECKey.CreateCurve();

            // 1.0 For j from 0 to h   (h == recId here and the loop is outside this function)
            //   1.1 Let x = r + jn

            var n = curve.N;
            var i = Org.BouncyCastle.Math.BigInteger.ValueOf((long)recId / 2);
            var x = sig.R.Add(i.Multiply(n));

            //   1.2. Convert the integer x to an octet string X of length mlen using the conversion routine
            //        specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉.
            //   1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the
            //        conversion routine specified in Section 2.3.4. If this conversion routine outputs “invalid”, then
            //        do another iteration of Step 1.
            //
            // More concisely, what these points mean is to use X as a compressed public key.
            var prime = ((FpCurve)curve.Curve).Q;

            if (x.CompareTo(prime) >= 0)
            {
                return(null);
            }

            // Compressed keys require you to know an extra bit of data about the y-coord as there are two possibilities.
            // So it's encoded in the recId.
            ECPoint R = DecompressKey(x, (recId & 1) == 1);

            //   1.4. If nR != point at infinity, then do another iteration of Step 1 (callers responsibility).

            if (!R.Multiply(n).IsInfinity)
            {
                return(null);
            }

            //   1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification.
            var e = new Org.BouncyCastle.Math.BigInteger(1, message.ToBytes());
            //   1.6. For k from 1 to 2 do the following.   (loop is outside this function via iterating recId)
            //   1.6.1. Compute a candidate public key as:
            //               Q = mi(r) * (sR - eG)
            //
            // Where mi(x) is the modular multiplicative inverse. We transform this into the following:
            //               Q = (mi(r) * s ** R) + (mi(r) * -e ** G)
            // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). In the above equation
            // ** is point multiplication and + is point addition (the EC group operator).
            //
            // We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive
            // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8.

            var eInv     = Org.BouncyCastle.Math.BigInteger.Zero.Subtract(e).Mod(n);
            var rInv     = sig.R.ModInverse(n);
            var srInv    = rInv.Multiply(sig.S).Mod(n);
            var eInvrInv = rInv.Multiply(eInv).Mod(n);
            var q        = (FpPoint)ECAlgorithms.SumOfTwoMultiplies(curve.G, eInvrInv, R, srInv);

            if (compressed)
            {
                q = new FpPoint(curve.Curve, q.X, q.Y, true);
            }
            return(new ECKey(q.GetEncoded(), false));
        }