Example #1
0
        public byte[] Encrypt(byte[] data, int offset, int length)
        {
            using(MemoryStream buffer = new MemoryStream(255))
            using(BinaryWriter writer = new BinaryWriter(buffer)) {
                using(SHA1 sha1 = new SHA1Managed()) {
                    byte[] hashsum = sha1.ComputeHash(data, offset, length);
                    writer.Write(hashsum);
                }

                buffer.Write(data, offset, length);
                if(length < 235) {
                    byte[] padding = new byte[235 - length];
                    new Random().NextBytes(padding);
                    buffer.Write(padding, 0, padding.Length);
                }

                byte[] ciphertext = new BigInteger(1, buffer.ToArray()).ModPow(e, m).ToByteArrayUnsigned();

                if(ciphertext.Length == 256) {
                    return ciphertext;
                } else {
                    byte[] paddedCiphertext = new byte[256];
                    int padding = 256 - ciphertext.Length;
                    for(int i = 0; i < padding; i++) {
                        paddedCiphertext[i] = 0;
                    }
                    ciphertext.CopyTo(paddedCiphertext, padding);
                    return paddedCiphertext;
                }
            }
        }
Example #2
0
        public byte[] ToBytes(byte[] nonce, byte[] serverNonce, List<byte[]> fingerprints, BigInteger pq)
        {
            new Random().NextBytes(newNonce);

            var pqPair = Factorizator.Factorize(pq);

            byte[] reqDhParamsBytes;

            using (MemoryStream pqInnerData = new MemoryStream(255))
            {
                using (BinaryWriter pqInnerDataWriter = new BinaryWriter(pqInnerData))
                {
                    pqInnerDataWriter.Write(0x83c95aec); // pq_inner_data
                    Serializers.Bytes.write(pqInnerDataWriter, pq.ToByteArrayUnsigned());
                    Serializers.Bytes.write(pqInnerDataWriter, pqPair.Min.ToByteArrayUnsigned());
                    Serializers.Bytes.write(pqInnerDataWriter, pqPair.Max.ToByteArrayUnsigned());
                    pqInnerDataWriter.Write(nonce);
                    pqInnerDataWriter.Write(serverNonce);
                    pqInnerDataWriter.Write(newNonce);

                    byte[] ciphertext = null;
                    byte[] targetFingerprint = null;
                    foreach (byte[] fingerprint in fingerprints)
                    {
                        ciphertext = RSA.Encrypt(BitConverter.ToString(fingerprint).Replace("-", string.Empty),
                                                 pqInnerData.GetBuffer(), 0, (int)pqInnerData.Position);
                        if (ciphertext != null)
                        {
                            targetFingerprint = fingerprint;
                            break;
                        }
                    }

                    if (ciphertext == null)
                    {
                        throw new InvalidOperationException(
                            String.Format("not found valid key for fingerprints: {0}", String.Join(", ", fingerprints)));
                    }

                    using (MemoryStream reqDHParams = new MemoryStream(1024))
                    {
                        using (BinaryWriter reqDHParamsWriter = new BinaryWriter(reqDHParams))
                        {
                            reqDHParamsWriter.Write(0xd712e4be); // req_dh_params
                            reqDHParamsWriter.Write(nonce);
                            reqDHParamsWriter.Write(serverNonce);
                            Serializers.Bytes.write(reqDHParamsWriter, pqPair.Min.ToByteArrayUnsigned());
                            Serializers.Bytes.write(reqDHParamsWriter, pqPair.Max.ToByteArrayUnsigned());
                            reqDHParamsWriter.Write(targetFingerprint);
                            Serializers.Bytes.write(reqDHParamsWriter, ciphertext);

                            reqDhParamsBytes = reqDHParams.ToArray();
                        }
                    }
                }
                return reqDhParamsBytes;
            }
        }
Example #3
0
 public AuthKey(BigInteger gab) {
     key = gab.ToByteArrayUnsigned();
     using(SHA1 hash = new SHA1Managed()) {
         using(MemoryStream hashStream = new MemoryStream(hash.ComputeHash(key), false)) {
             using(BinaryReader hashReader = new BinaryReader(hashStream)) {
                 auxHash = hashReader.ReadUInt64();
                 hashReader.ReadBytes(4);
                 keyId = hashReader.ReadUInt64();
             }
         }
     }
 }
Example #4
0
 public static FactorizedPair Factorize(BigInteger pq)
 {
     if(pq.BitLength < 64) {
         long pqlong = pq.LongValue;
         long divisor = findSmallMultiplierLopatin(pqlong);
         return new FactorizedPair(BigInteger.ValueOf(divisor), BigInteger.ValueOf(pqlong/divisor));
     } else {
         // TODO: port pollard factorization
         throw new InvalidOperationException("pq too long; TODO: port the pollard algo");
        // logger.error("pq too long; TODO: port the pollard algo");
        // return null;
     }
 }
Example #5
0
		public Step1_Response FromBytes(byte[] bytes)
		{
			var fingerprints = new List<byte[]>();

			using (var memoryStream = new MemoryStream(bytes, false))
			{
				using (var binaryReader = new BinaryReader(memoryStream))
				{
					const int responseConstructorNumber = 0x05162463;
					var responseCode = binaryReader.ReadInt32();
					if (responseCode != responseConstructorNumber)
					{
						throw new InvalidOperationException($"invalid response code: {responseCode}");
					}

					var nonceFromServer = binaryReader.ReadBytes(16);
					
					if (!nonceFromServer.SequenceEqual(nonce))
					{
						throw new InvalidOperationException("invalid nonce from server");
					}
					
					var serverNonce = binaryReader.ReadBytes(16);

					byte[] pqbytes = Serializers.Bytes.read(binaryReader);
					var pq = new BigInteger(1, pqbytes);

					var vectorId = binaryReader.ReadInt32();
					const int vectorConstructorNumber = 0x1cb5c415;
					if (vectorId != vectorConstructorNumber)
					{
						throw new InvalidOperationException($"Invalid vector constructor number {vectorId}");
					}

					var fingerprintCount = binaryReader.ReadInt32();
					for (var i = 0; i < fingerprintCount; i++)
					{
						byte[] fingerprint = binaryReader.ReadBytes(8);
						fingerprints.Add(fingerprint);
					}

					return new Step1_Response
					{
						Fingerprints = fingerprints,
						Nonce = nonce,
						Pq = pq,
						ServerNonce = serverNonce
					};
				}
			}
		}
Example #6
0
        public BigInteger ModPow(
            BigInteger exponent,
            BigInteger m) {
            if (m.sign < 1)
                throw new ArithmeticException("Modulus must be positive");

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

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

            if (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.magnitude[m.magnitude.Length - 1] & 1) == 1);
            long mQ = 0;
            if (useMonty) {
                mQ = m.GetMQuote();

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

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

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

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

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

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

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

            //
            // from LSW to MSW
            //
            for (int i = 0; i < exponent.magnitude.Length; i++) {
                int v = exponent.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.magnitude, mQ);
                    }
                    else {
                        Square(yAccum, yVal);
                        Remainder(yAccum, 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.magnitude, mQ);
                        }
                        else {
                            Multiply(yAccum, yVal, zVal);
                            Remainder(yAccum, 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.magnitude, mQ);
                    }
                    else {
                        Square(yAccum, yVal);
                        Remainder(yAccum, 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.magnitude, mQ);
            }

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

            return exponent.sign > 0
                ? result
                : result.ModInverse(m);
        }
Example #7
0
 public RSAServerKey(string fingerprint, BigInteger m, BigInteger e)
 {
     this.fingerprint = fingerprint;
     this.m = m;
     this.e = e;
 }
Example #8
0
 public FactorizedPair(long p, long q) {
     this.p = BigInteger.ValueOf(p);
     this.q = BigInteger.ValueOf(q);
 }
Example #9
0
 public int CompareTo(
     BigInteger value) {
     return sign < value.sign ? -1
         : sign > value.sign ? 1
         : sign == 0 ? 0
         : sign * CompareNoLeadingZeroes(0, magnitude, 0, value.magnitude);
 }
Example #10
0
        public BigInteger And(
            BigInteger value) {
            if (this.sign == 0 || value.sign == 0) {
                return Zero;
            }

            int[] aMag = this.sign > 0
                ? this.magnitude
                : Add(One).magnitude;

            int[] bMag = value.sign > 0
                ? value.magnitude
                : value.Add(One).magnitude;

            bool resultNeg = sign < 0 && value.sign < 0;
            int resultLength = System.Math.Max(aMag.Length, bMag.Length);
            int[] resultMag = new int[resultLength];

            int aStart = resultMag.Length - aMag.Length;
            int bStart = resultMag.Length - bMag.Length;

            for (int i = 0; i < resultMag.Length; ++i) {
                int aWord = i >= aStart ? aMag[i - aStart] : 0;
                int bWord = i >= bStart ? bMag[i - bStart] : 0;

                if (this.sign < 0) {
                    aWord = ~aWord;
                }

                if (value.sign < 0) {
                    bWord = ~bWord;
                }

                resultMag[i] = aWord & bWord;

                if (resultNeg) {
                    resultMag[i] = ~resultMag[i];
                }
            }

            BigInteger result = new BigInteger(1, resultMag, true);

            // TODO Optimise this case
            if (resultNeg) {
                result = result.Not();
            }

            return result;
        }
Example #11
0
        private static BigInteger createUValueOf(
            ulong value) {
            int msw = (int)(value >> 32);
            int lsw = (int)value;

            if (msw != 0)
                return new BigInteger(1, new int[] { msw, lsw }, false);

            if (lsw != 0) {
                BigInteger n = new BigInteger(1, new int[] { lsw }, false);
                // Check for a power of two
                if ((lsw & -lsw) == lsw) {
                    n.nBits = 1;
                }
                return n;
            }

            return Zero;
        }
Example #12
0
        public BigInteger ShiftLeft(
            int n) {
            if (sign == 0 || magnitude.Length == 0)
                return Zero;

            if (n == 0)
                return this;

            if (n < 0)
                return ShiftRight(-n);

            BigInteger result = new BigInteger(sign, ShiftLeft(magnitude, n), true);

            if (this.nBits != -1) {
                result.nBits = sign > 0
                    ? this.nBits
                    : this.nBits + n;
            }

            if (this.nBitLength != -1) {
                result.nBitLength = this.nBitLength + n;
            }

            return result;
        }
Example #13
0
        public BigInteger Gcd(
            BigInteger value) {
            if (value.sign == 0)
                return Abs();

            if (sign == 0)
                return value.Abs();

            BigInteger r;
            BigInteger u = this;
            BigInteger v = value;

            while (v.sign != 0) {
                r = u.Mod(v);
                u = v;
                v = r;
            }

            return u;
        }
Example #14
0
        public BigInteger[] DivideAndRemainder(
            BigInteger val) {
            if (val.sign == 0)
                throw new ArithmeticException("Division by zero error");

            BigInteger[] biggies = new BigInteger[2];

            if (sign == 0) {
                biggies[0] = Zero;
                biggies[1] = Zero;
            }
            else if (val.QuickPow2Check()) // val is power of two
			{
                int e = val.Abs().BitLength - 1;
                BigInteger quotient = this.Abs().ShiftRight(e);
                int[] remainder = this.LastNBits(e);

                biggies[0] = val.sign == this.sign ? quotient : quotient.Negate();
                biggies[1] = new BigInteger(this.sign, remainder, true);
            }
            else {
                int[] remainder = (int[])this.magnitude.Clone();
                int[] quotient = Divide(remainder, val.magnitude);

                biggies[0] = new BigInteger(this.sign * val.sign, quotient, true);
                biggies[1] = new BigInteger(this.sign, remainder, true);
            }

            return biggies;
        }
        public byte[] ToBytes(byte[] nonce, byte[] serverNonce, byte[] newNonce, byte[] encryptedAnswer)
        {
            this.newNonce = newNonce;
            AESKeyData key = AES.GenerateKeyDataFromNonces(serverNonce, newNonce);
            byte[] plaintextAnswer = AES.DecryptAES(key, encryptedAnswer);

            // logger.debug("plaintext answer: {0}", BitConverter.ToString(plaintextAnswer));

            int g;
            BigInteger dhPrime;
            BigInteger ga;

            using (MemoryStream dhInnerData = new MemoryStream(plaintextAnswer))
            {
                using (BinaryReader dhInnerDataReader = new BinaryReader(dhInnerData))
                {
                    byte[] hashsum = dhInnerDataReader.ReadBytes(20);
                    uint code = dhInnerDataReader.ReadUInt32();
                    if (code != 0xb5890dba)
                    {
                        throw new InvalidOperationException($"invalid dh_inner_data code: {code}");
                    }

                    // logger.debug("valid code");

                    byte[] nonceFromServer1 = dhInnerDataReader.ReadBytes(16);
                    if (!nonceFromServer1.SequenceEqual(nonce))
                    {
                        throw new InvalidOperationException("invalid nonce in encrypted answer");
                    }

                    // logger.debug("valid nonce");

                    byte[] serverNonceFromServer1 = dhInnerDataReader.ReadBytes(16);
                    if (!serverNonceFromServer1.SequenceEqual(serverNonce))
                    {
                        throw new InvalidOperationException("invalid server nonce in encrypted answer");
                    }

                    // logger.debug("valid server nonce");

                    g = dhInnerDataReader.ReadInt32();
                    dhPrime = new BigInteger(1, Serializers.Bytes.read(dhInnerDataReader));
                    ga = new BigInteger(1, Serializers.Bytes.read(dhInnerDataReader));

                    int serverTime = dhInnerDataReader.ReadInt32();
                    timeOffset = serverTime - (int)(Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds) / 1000);

                    // logger.debug("g: {0}, dhprime: {1}, ga: {2}", g, dhPrime, ga);
                }
            }

            BigInteger b = new BigInteger(2048, new Random());
            BigInteger gb = BigInteger.ValueOf(g).ModPow(b, dhPrime);
            _gab = ga.ModPow(b, dhPrime);

            // logger.debug("gab: {0}", gab);

            // prepare client dh inner data
            byte[] clientDHInnerDataBytes;
            using (MemoryStream clientDhInnerData = new MemoryStream())
            {
                using (BinaryWriter clientDhInnerDataWriter = new BinaryWriter(clientDhInnerData))
                {
                    clientDhInnerDataWriter.Write(0x6643b654); // client_dh_inner_data
                    clientDhInnerDataWriter.Write(nonce);
                    clientDhInnerDataWriter.Write(serverNonce);
                    clientDhInnerDataWriter.Write((long)0); // TODO: retry_id
                    Serializers.Bytes.write(clientDhInnerDataWriter, gb.ToByteArrayUnsigned());

                    using (MemoryStream clientDhInnerDataWithHash = new MemoryStream())
                    {
                        using (BinaryWriter clientDhInnerDataWithHashWriter = new BinaryWriter(clientDhInnerDataWithHash))
                        {
                            using (SHA1 sha1 = new SHA1Managed())
                            {
                                clientDhInnerDataWithHashWriter.Write(sha1.ComputeHash(clientDhInnerData.GetBuffer(), 0, (int)clientDhInnerData.Position));
                                clientDhInnerDataWithHashWriter.Write(clientDhInnerData.GetBuffer(), 0, (int)clientDhInnerData.Position);
                                clientDHInnerDataBytes = clientDhInnerDataWithHash.ToArray();
                            }
                        }
                    }
                }
            }

            // logger.debug("client dh inner data papared len {0}: {1}", clientDHInnerDataBytes.Length, BitConverter.ToString(clientDHInnerDataBytes).Replace("-", ""));

            // encryption
            byte[] clientDhInnerDataEncryptedBytes = AES.EncryptAES(key, clientDHInnerDataBytes);

            // logger.debug("inner data encrypted {0}: {1}", clientDhInnerDataEncryptedBytes.Length, BitConverter.ToString(clientDhInnerDataEncryptedBytes).Replace("-", ""));

            // prepare set_client_dh_params
            byte[] setclientDhParamsBytes;
            using (MemoryStream setClientDhParams = new MemoryStream())
            {
                using (BinaryWriter setClientDhParamsWriter = new BinaryWriter(setClientDhParams))
                {
                    setClientDhParamsWriter.Write(0xf5045f1f);
                    setClientDhParamsWriter.Write(nonce);
                    setClientDhParamsWriter.Write(serverNonce);
                    Serializers.Bytes.write(setClientDhParamsWriter, clientDhInnerDataEncryptedBytes);

                    setclientDhParamsBytes = setClientDhParams.ToArray();
                }
            }

            // logger.debug("set client dh params prepared: {0}", BitConverter.ToString(setclientDhParamsBytes));

            return setclientDhParamsBytes;
        }
Example #16
0
        public BigInteger Multiply(
            BigInteger val) {
            if (sign == 0 || val.sign == 0)
                return Zero;

            if (val.QuickPow2Check()) // val is power of two
			{
                BigInteger result = this.ShiftLeft(val.Abs().BitLength - 1);
                return val.sign > 0 ? result : result.Negate();
            }

            if (this.QuickPow2Check()) // this is power of two
			{
                BigInteger result = val.ShiftLeft(this.Abs().BitLength - 1);
                return this.sign > 0 ? result : result.Negate();
            }

            int resLength = (this.BitLength + val.BitLength) / BitsPerInt + 1;
            int[] res = new int[resLength];

            if (val == this) {
                Square(res, this.magnitude);
            }
            else {
                Multiply(res, this.magnitude, val.magnitude);
            }

            return new BigInteger(sign * val.sign, res, true);
        }
Example #17
0
        public BigInteger Remainder(
            BigInteger n) {
            if (n.sign == 0)
                throw new ArithmeticException("Division by zero error");

            if (this.sign == 0)
                return Zero;

            // For small values, use fast remainder method
            if (n.magnitude.Length == 1) {
                int val = n.magnitude[0];

                if (val > 0) {
                    if (val == 1)
                        return Zero;

                    // TODO Make this func work on uint, and handle val == 1?
                    int rem = Remainder(val);

                    return rem == 0
                        ? Zero
                        : new BigInteger(sign, new int[] { rem }, false);
                }
            }

            if (CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude) < 0)
                return this;

            int[] result;
            if (n.QuickPow2Check())  // n is power of two
			{
                // TODO Move before small values branch above?
                result = LastNBits(n.Abs().BitLength - 1);
            }
            else {
                result = (int[])this.magnitude.Clone();
                result = Remainder(result, n.magnitude);
            }

            return new BigInteger(sign, result, true);
        }
Example #18
0
        internal bool RabinMillerTest(
            int certainty,
            Random random) {
            Debug.Assert(certainty > 0);
            Debug.Assert(BitLength > 2);
            Debug.Assert(TestBit(0));

            // let n = 1 + d . 2^s
            BigInteger n = this;
            BigInteger nMinusOne = n.Subtract(One);
            int s = nMinusOne.GetLowestSetBit();
            BigInteger r = nMinusOne.ShiftRight(s);

            Debug.Assert(s >= 1);

            do {
                // TODO Make a method for random BigIntegers in range 0 < x < n)
                // - Method can be optimized by only replacing examined bits at each trial
                BigInteger a;
                do {
                    a = new BigInteger(n.BitLength, random);
                }
                while (a.CompareTo(One) <= 0 || a.CompareTo(nMinusOne) >= 0);

                BigInteger y = a.ModPow(r, n);

                if (!y.Equals(One)) {
                    int j = 0;
                    while (!y.Equals(nMinusOne)) {
                        if (++j == s)
                            return false;

                        y = y.ModPow(Two, n);

                        if (y.Equals(One))
                            return false;
                    }
                }

                certainty -= 2; // composites pass for only 1/4 possible 'a'
            }
            while (certainty > 0);

            return true;
        }
Example #19
0
        public BigInteger Subtract(
            BigInteger n) {
            if (n.sign == 0)
                return this;

            if (this.sign == 0)
                return n.Negate();

            if (this.sign != n.sign)
                return Add(n.Negate());

            int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude);
            if (compare == 0)
                return Zero;

            BigInteger bigun, lilun;
            if (compare < 0) {
                bigun = n;
                lilun = this;
            }
            else {
                bigun = this;
                lilun = n;
            }

            return new BigInteger(this.sign * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true);
        }
Example #20
0
 public BigInteger Max(
     BigInteger value) {
     return CompareTo(value) > 0 ? this : value;
 }
Example #21
0
        public BigInteger Add(
            BigInteger value) {
            if (this.sign == 0)
                return value;

            if (this.sign != value.sign) {
                if (value.sign == 0)
                    return this;

                if (value.sign < 0)
                    return Subtract(value.Negate());

                return value.Subtract(Negate());
            }

            return AddToMagnitude(value.magnitude);
        }
Example #22
0
 public BigInteger Min(
     BigInteger value) {
     return CompareTo(value) < 0 ? this : value;
 }
Example #23
0
 public BigInteger AndNot(
     BigInteger val) {
     return And(val.Not());
 }
Example #24
0
        public BigInteger Mod(
            BigInteger m) {
            if (m.sign < 1)
                throw new ArithmeticException("Modulus must be positive");

            BigInteger biggie = Remainder(m);

            return (biggie.sign >= 0 ? biggie : biggie.Add(m));
        }
Example #25
0
        public BigInteger Divide(
            BigInteger val) {
            if (val.sign == 0)
                throw new ArithmeticException("Division by zero error");

            if (sign == 0)
                return Zero;

            if (val.QuickPow2Check()) // val is power of two
			{
                BigInteger result = this.Abs().ShiftRight(val.Abs().BitLength - 1);
                return val.sign == this.sign ? result : result.Negate();
            }

            int[] mag = (int[])this.magnitude.Clone();

            return new BigInteger(this.sign * val.sign, Divide(mag, val.magnitude), true);
        }
Example #26
0
        public BigInteger ModInverse(
            BigInteger m) {
            if (m.sign < 1)
                throw new ArithmeticException("Modulus must be positive");

            // TODO Too slow at the moment
            //			// "Fast Key Exchange with Elliptic Curve Systems" R.Schoeppel
            //			if (m.TestBit(0))
            //			{
            //				//The Almost Inverse Algorithm
            //				int k = 0;
            //				BigInteger B = One, C = Zero, F = this, G = m, tmp;
            //
            //				for (;;)
            //				{
            //					// While F is even, do F=F/u, C=C*u, k=k+1.
            //					int zeroes = F.GetLowestSetBit();
            //					if (zeroes > 0)
            //					{
            //						F = F.ShiftRight(zeroes);
            //						C = C.ShiftLeft(zeroes);
            //						k += zeroes;
            //					}
            //
            //					// If F = 1, then return B,k.
            //					if (F.Equals(One))
            //					{
            //						BigInteger half = m.Add(One).ShiftRight(1);
            //						BigInteger halfK = half.ModPow(BigInteger.ValueOf(k), m);
            //						return B.Multiply(halfK).Mod(m);
            //					}
            //
            //					if (F.CompareTo(G) < 0)
            //					{
            //						tmp = G; G = F; F = tmp;
            //						tmp = B; B = C; C = tmp;
            //					}
            //
            //					F = F.Add(G);
            //					B = B.Add(C);
            //				}
            //			}

            BigInteger x = new BigInteger();
            BigInteger gcd = ExtEuclid(this.Mod(m), m, x, null);

            if (!gcd.Equals(One))
                throw new ArithmeticException("Numbers not relatively prime.");

            if (x.sign < 0) {
                x.sign = 1;
                //x = m.Subtract(x);
                x.magnitude = doSubBigLil(m.magnitude, x.magnitude);
            }

            return x;
        }
Example #27
0
 public FactorizedPair(BigInteger p, BigInteger q) {
     this.p = p;
     this.q = q;
 }
Example #28
0
        /**
         * Calculate the numbers u1, u2, and u3 such that:
         *
         * u1 * a + u2 * b = u3
         *
         * where u3 is the greatest common divider of a and b.
         * a and b using the extended Euclid algorithm (refer p. 323
         * of The Art of Computer Programming vol 2, 2nd ed).
         * This also seems to have the side effect of calculating
         * some form of multiplicative inverse.
         *
         * @param a    First number to calculate gcd for
         * @param b    Second number to calculate gcd for
         * @param u1Out      the return object for the u1 value
         * @param u2Out      the return object for the u2 value
         * @return     The greatest common divisor of a and b
         */
        private static BigInteger ExtEuclid(
            BigInteger a,
            BigInteger b,
            BigInteger u1Out,
            BigInteger u2Out) {
            BigInteger u1 = One;
            BigInteger u3 = a;
            BigInteger v1 = Zero;
            BigInteger v3 = b;

            while (v3.sign > 0) {
                BigInteger[] q = u3.DivideAndRemainder(v3);

                BigInteger tmp = v1.Multiply(q[0]);
                BigInteger tn = u1.Subtract(tmp);
                u1 = v1;
                v1 = tn;

                u3 = v3;
                v3 = q[1];
            }

            if (u1Out != null) {
                u1Out.sign = u1.sign;
                u1Out.magnitude = u1.magnitude;
            }

            if (u2Out != null) {
                BigInteger tmp = u1.Multiply(a);
                tmp = u3.Subtract(tmp);
                BigInteger res = tmp.Divide(b);
                u2Out.sign = res.sign;
                u2Out.magnitude = res.magnitude;
            }

            return u3;
        }