/**
         * given a message from a given party and the corresponding public key
         * calculate the next message in the agreement sequence. In this case
         * this will represent the shared secret.
         */
        public BigInteger CalculateAgreement(
            DHPublicKeyParameters	pub,
            BigInteger				message)
        {
            if (pub == null)
                throw new ArgumentNullException("pub");
            if (message == null)
                throw new ArgumentNullException("message");

            if (!pub.Parameters.Equals(dhParams))
            {
                throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
            }

            BigInteger p = dhParams.P;

            return message.ModPow(key.X, p).Multiply(pub.Y.ModPow(privateValue, p)).Mod(p);
        }
        /**
        * Process a single block using the basic ElGamal algorithm.
        *
        * @param in the input array.
        * @param inOff the offset into the input buffer where the data starts.
        * @param length the length of the data to be processed.
        * @return the result of the ElGamal process.
        * @exception DataLengthException the input block is too large.
        */
        public byte[] ProcessBlock(
            byte[]	input,
            int		inOff,
            int		length)
        {
            if (key == null)
                throw new InvalidOperationException("ElGamal engine not initialised");

            int maxLength = forEncryption
                ?	(bitSize - 1 + 7) / 8
                :	GetInputBlockSize();

            if (length > maxLength)
                throw new DataLengthException("input too large for ElGamal cipher.\n");

            BigInteger p = key.Parameters.P;

            byte[] output;
            if (key is ElGamalPrivateKeyParameters) // decryption
            {
                int halfLength = length / 2;
                BigInteger gamma = new BigInteger(1, input, inOff, halfLength);
                BigInteger phi = new BigInteger(1, input, inOff + halfLength, halfLength);

                ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters) key;

                // a shortcut, which generally relies on p being prime amongst other things.
                // if a problem with this shows up, check the p and g values!
                BigInteger m = gamma.ModPow(p.Subtract(BigInteger.One).Subtract(priv.X), p).Multiply(phi).Mod(p);

                output = m.ToByteArrayUnsigned();
            }
            else // encryption
            {
                BigInteger tmp = new BigInteger(1, input, inOff, length);

                if (tmp.BitLength >= p.BitLength)
                    throw new DataLengthException("input too large for ElGamal cipher.\n");

                ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters) key;

                BigInteger pSub2 = p.Subtract(BigInteger.Two);

                // TODO In theory, a series of 'k', 'g.ModPow(k, p)' and 'y.ModPow(k, p)' can be pre-calculated
                BigInteger k;
                do
                {
                    k = new BigInteger(p.BitLength, random);
                }
                while (k.SignValue == 0 || k.CompareTo(pSub2) > 0);

                BigInteger g = key.Parameters.G;
                BigInteger gamma = g.ModPow(k, p);
                BigInteger phi = tmp.Multiply(pub.Y.ModPow(k, p)).Mod(p);

                output = new byte[this.GetOutputBlockSize()];

                // TODO Add methods to allow writing BigInteger to existing byte array?
                byte[] out1 = gamma.ToByteArrayUnsigned();
                byte[] out2 = phi.ToByteArrayUnsigned();
                out1.CopyTo(output, output.Length / 2 - out1.Length);
                out2.CopyTo(output, output.Length - out2.Length);
            }

            return output;
        }
        /**
         * Procedure C
         * procedure generates the a value from the given p,q,
         * returning the a value.
         */
        private BigInteger procedure_C(BigInteger p, BigInteger q)
        {
            BigInteger pSub1 = p.Subtract(BigInteger.One);
            BigInteger pSub1Divq = pSub1.Divide(q);

            for(;;)
            {
                BigInteger d = new BigInteger(p.BitLength, init_random);

                // 1 < d < p-1
                if (d.CompareTo(BigInteger.One) > 0 && d.CompareTo(pSub1) < 0)
                {
                    BigInteger a = d.ModPow(pSub1Divq, p);

                    if (a.CompareTo(BigInteger.One) != 0)
                    {
                        return a;
                    }
                }
            }
        }
        public BigInteger ProcessBlock(
            BigInteger input)
        {
            if (key is RsaPrivateCrtKeyParameters)
            {
                //
                // we have the extra factors, use the Chinese Remainder Theorem - the author
                // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for
                // advice regarding the expression of this.
                //
                RsaPrivateCrtKeyParameters crtKey = (RsaPrivateCrtKeyParameters)key;

                BigInteger p = crtKey.P;;
                BigInteger q = crtKey.Q;
                BigInteger dP = crtKey.DP;
                BigInteger dQ = crtKey.DQ;
                BigInteger qInv = crtKey.QInv;

                BigInteger mP, mQ, h, m;

                // mP = ((input Mod p) ^ dP)) Mod p
                mP = (input.Remainder(p)).ModPow(dP, p);

                // mQ = ((input Mod q) ^ dQ)) Mod q
                mQ = (input.Remainder(q)).ModPow(dQ, q);

                // h = qInv * (mP - mQ) Mod p
                h = mP.Subtract(mQ);
                h = h.Multiply(qInv);
                h = h.Mod(p);               // Mod (in Java) returns the positive residual

                // m = h * q + mQ
                m = h.Multiply(q);
                m = m.Add(mQ);

                return m;
            }

            return input.ModPow(key.Exponent, key.Modulus);
        }
 private static BigInteger CalculatePublicKey(BigInteger p, BigInteger g, BigInteger x)
 {
     return g.ModPow(x, p);
 }
        /**
         * Set the private key.
         *
         * @param p   key parameter: field modulus
         * @param q   key parameter: subgroup order
         * @param g   key parameter: generator
         * @param x   private key
         */
        public void setPrivateKey(BigInteger p, BigInteger q,
            BigInteger g, BigInteger x)
        {
            /*
             * Perform some basic sanity checks.  We do not
             * check primality of p or q because that would
             * be too expensive.
             *
             * We reject keys where q is longer than 999 bits,
             * because it would complicate signature encoding.
             * Normal DSA keys do not have a q longer than 256
             * bits anyway.
             */
            if(p == null || q == null || g == null || x == null
                    || p.SignValue <= 0 || q.SignValue <= 0
                    || g.SignValue <= 0 || x.SignValue <= 0
                    || x.CompareTo(q) >= 0 || q.CompareTo(p) >= 0
                    || q.BitLength > 999
                    || g.CompareTo(p) >= 0 || g.BitLength == 1
                    || g.ModPow(q, p).BitLength != 1)
            {
                throw new InvalidOperationException(
                        "invalid DSA private key");
            }
            this.p = p;
            this.q = q;
            this.g = g;
            this.x = x;
            qlen = q.BitLength;
            if(q.SignValue <= 0 || qlen < 8)
            {
                throw new InvalidOperationException(
                        "bad group order: " + q);

            }
            rolen = (qlen + 7) >> 3;
            rlen = rolen * 8;

            /*
             * Convert the private exponent (x) into a sequence
             * of octets.
             */
            bx = int2octets(x);
        }