Lidgren.Network.NetBigInteger.ModPow C# (CSharp) Method

ModPow() public method

public ModPow ( NetBigInteger exponent, NetBigInteger m ) : NetBigInteger
exponent NetBigInteger
m NetBigInteger
return NetBigInteger
        public NetBigInteger ModPow(
			NetBigInteger exponent,
			NetBigInteger m)
        {
            if (m.m_sign < 1)
                throw new ArithmeticException("Modulus must be positive");

            if (m.Equals(One))
                return Zero;

            if (exponent.m_sign == 0)
                return One;

            if (m_sign == 0)
                return Zero;

            int[] zVal = null;
            int[] yAccum = null;
            int[] yVal;

            // Montgomery exponentiation is only possible if the modulus is odd,
            // but AFAIK, this is always the case for crypto algo's
            bool useMonty = ((m.m_magnitude[m.m_magnitude.Length - 1] & 1) == 1);
            long mQ = 0;
            if (useMonty)
            {
                mQ = m.GetMQuote();

                // tmp = this * R mod m
                NetBigInteger tmp = ShiftLeft(32 * m.m_magnitude.Length).Mod(m);
                zVal = tmp.m_magnitude;

                useMonty = (zVal.Length <= m.m_magnitude.Length);

                if (useMonty)
                {
                    yAccum = new int[m.m_magnitude.Length + 1];
                    if (zVal.Length < m.m_magnitude.Length)
                    {
                        int[] longZ = new int[m.m_magnitude.Length];
                        zVal.CopyTo(longZ, longZ.Length - zVal.Length);
                        zVal = longZ;
                    }
                }
            }

            if (!useMonty)
            {
                if (m_magnitude.Length <= m.m_magnitude.Length)
                {
                    //zAccum = new int[m.magnitude.Length * 2];
                    zVal = new int[m.m_magnitude.Length];
                    m_magnitude.CopyTo(zVal, zVal.Length - m_magnitude.Length);
                }
                else
                {
                    //
                    // in normal practice we'll never see ..
                    //
                    NetBigInteger tmp = Remainder(m);

                    //zAccum = new int[m.magnitude.Length * 2];
                    zVal = new int[m.m_magnitude.Length];
                    tmp.m_magnitude.CopyTo(zVal, zVal.Length - tmp.m_magnitude.Length);
                }

                yAccum = new int[m.m_magnitude.Length * 2];
            }

            yVal = new int[m.m_magnitude.Length];

            //
            // from LSW to MSW
            //
            for (int i = 0; i < exponent.m_magnitude.Length; i++)
            {
                int v = exponent.m_magnitude[i];
                int bits = 0;

                if (i == 0)
                {
                    while (v > 0)
                    {
                        v <<= 1;
                        bits++;
                    }

                    //
                    // first time in initialise y
                    //
                    zVal.CopyTo(yVal, 0);

                    v <<= 1;
                    bits++;
                }

                while (v != 0)
                {
                    if (useMonty)
                    {
                        // Montgomery square algo doesn't exist, and a normal
                        // square followed by a Montgomery reduction proved to
                        // be almost as heavy as a Montgomery mulitply.
                        MultiplyMonty(yAccum, yVal, yVal, m.m_magnitude, mQ);
                    }
                    else
                    {
                        Square(yAccum, yVal);
                        Remainder(yAccum, m.m_magnitude);
                        Array.Copy(yAccum, yAccum.Length - yVal.Length, yVal, 0, yVal.Length);
                        ZeroOut(yAccum);
                    }
                    bits++;

                    if (v < 0)
                    {
                        if (useMonty)
                        {
                            MultiplyMonty(yAccum, yVal, zVal, m.m_magnitude, mQ);
                        }
                        else
                        {
                            Multiply(yAccum, yVal, zVal);
                            Remainder(yAccum, m.m_magnitude);
                            Array.Copy(yAccum, yAccum.Length - yVal.Length, yVal, 0,
                                yVal.Length);
                            ZeroOut(yAccum);
                        }
                    }

                    v <<= 1;
                }

                while (bits < 32)
                {
                    if (useMonty)
                    {
                        MultiplyMonty(yAccum, yVal, yVal, m.m_magnitude, mQ);
                    }
                    else
                    {
                        Square(yAccum, yVal);
                        Remainder(yAccum, m.m_magnitude);
                        Array.Copy(yAccum, yAccum.Length - yVal.Length, yVal, 0, yVal.Length);
                        ZeroOut(yAccum);
                    }
                    bits++;
                }
            }

            if (useMonty)
            {
                // Return y * R^(-1) mod m by doing y * 1 * R^(-1) mod m
                ZeroOut(zVal);
                zVal[zVal.Length - 1] = 1;
                MultiplyMonty(yAccum, yVal, zVal, m.m_magnitude, mQ);
            }

            NetBigInteger result = new NetBigInteger(1, yVal, true);

            return exponent.m_sign > 0
                ? result
                : result.ModInverse(m);
        }

Usage Example

Exemplo n.º 1
0
		/// <summary>
		/// Computes the server session value
		/// </summary>
		public static byte[] ComputeServerSessionValue(byte[] clientPublicEphemeral, byte[] verifier, byte[] udata, byte[] serverPrivateEphemeral)
		{
			// S = (Av^u) ^ b (mod N)
			var A = new NetBigInteger(NetUtility.ToHexString(clientPublicEphemeral), 16);
			var v = new NetBigInteger(NetUtility.ToHexString(verifier), 16);
			var u = new NetBigInteger(NetUtility.ToHexString(udata), 16);
			var b = new NetBigInteger(NetUtility.ToHexString(serverPrivateEphemeral), 16);

			NetBigInteger retval = v.ModPow(u, N).Multiply(A).Mod(N).ModPow(b, N).Mod(N);

			return retval.ToByteArrayUnsigned();
		}