Example #1
0
 internal void _Mul(Digits a, Digits b, Digits c)
 {
     Modular.ValidateData(a, _mod, _digitN);
     if (a != b)
     {
         Modular.ValidateData(b, _mod, _digitN);
     }
     _algorithm(a, b, c);
 }
Example #2
0
        void _MulFromRight(Digits a, Digits b, Digits c)
        {
            Digit minv = _rightRecip
            , minva0 = unchecked (minv * a[0])
            , mul1 = b[0]
            , mul2 = unchecked (minva0 * mul1)
            , carry1 = Digit2.Hi((UInt64)mul1 * a[0])
            , carry2 = Digit2.Hi((UInt64)mul2 * _mod[0]);
            UInt64 prod1, prod2;

            Debug.Assert(unchecked (mul1 * a[0]) == unchecked (mul2 * _mod[0])
                         , "internal error");
            Digits temp1 = new Digits(_digitN), temp2 = new Digits(_digitN);

            for (int i = 1; i != _digitN; i++)
            {
                prod1        = (UInt64)mul1 * a[i] + carry1;
                prod2        = (UInt64)mul2 * _mod[i] + carry2;
                temp1[i - 1] = Digit2.Lo(prod1);
                temp2[i - 1] = Digit2.Lo(prod2);
                carry1       = Digit2.Hi(prod1);
                carry2       = Digit2.Hi(prod2);
            }
            temp1[_digitN - 1] = carry1;
            temp2[_digitN - 1] = carry2;
            for (int j = 1; j != _digitN; j++)
            {
                mul1  = b[j];
                mul2  = unchecked (minva0 * mul1 + minv * (temp1[0] - temp2[0]));
                prod1 = (UInt64)mul1 * a[0] + temp1[0];
                prod2 = (UInt64)mul2 * _mod[0] + temp2[0];
                Debug.Assert(Digit2.Lo(prod1) == Digit2.Lo(prod2)
                             , "internal error");
                carry1 = Digit2.Hi(prod1);
                carry2 = Digit2.Hi(prod2);
                for (int i = 1; i != _digitN; i++)
                {
                    prod1        = (UInt64)mul1 * a[i] + temp1[i] + carry1;
                    prod2        = (UInt64)mul2 * _mod[i] + temp2[i] + carry2;
                    temp1[i - 1] = Digit2.Lo(prod1);
                    temp2[i - 1] = Digit2.Lo(prod2);
                    carry1       = Digit2.Hi(prod1);
                    carry2       = Digit2.Hi(prod2);
                }
                temp1[_digitN - 1] = carry1;
                temp2[_digitN - 1] = carry2;
            }
            Modular.Sub(temp1, temp2, c, _mod, _digitN);
        }
Example #3
0
            void _EncryptBlock(Block input, Block output)
            {
                if (input == null || output == null)
                {
                    throw new ArgumentNullException();
                }
                Digits digits = new Digits(_modDigitN);

                Digits.BytesToDigits(
                    input._Bytes, input._ByteI, digits, input._BitN);
                Modular.ValidateData(digits, _modulus._mod, _modulus._digitN);
                _modulus._ToModular(digits, input._DigitN, digits);
                _modulus._Exp(digits, _eDigits, _eDigitN, digits);
                _modulus._FromModular(digits, digits);
                Digits.DigitsToBytes(
                    digits, output._Bytes, output._ByteI, output._BitN);
            }
Example #4
0
            void _DecryptBlock(Block input, Block output)
            {
                if (input == null || output == null)
                {
                    throw new ArgumentNullException();
                }
                if (
                    _privateModulus[0]._digitN
                    + _privateModulus[1]._digitN
                    - _modDigitN
                    > 1
                    )
                {
                    throw new ArgumentException();
                }
                Digits[] dmsg = new Digits[] {
                    new Digits(_modDigitN + 1)
                    , new Digits(_modDigitN + 1)
                };
                int longerDigitN
                    = _privateModulus[0]._digitN > _privateModulus[1]._digitN
                  ? _privateModulus[0]._digitN
                  : _privateModulus[1]._digitN;
                Digits res = new Digits(longerDigitN);

                Digits.BytesToDigits(
                    input._Bytes, input._ByteI, dmsg[1], input._BitN);
                Modular.ValidateData(dmsg[1], _modDigits, _modDigitN);
                for (int ip = 0; ip != 2; ip++)
                {
                    _privateModulus[ip]._ToModular(dmsg[1], _modDigitN, res);
                    _privateModulus[ip]
                    ._Exp(res, _dDigits[ip], _privateModulus[ip]._digitN, res);
                    _privateModulus[ip]._Mul(res, _chineseDigits[ip], res);
                    Digits.Mul(res
                               , _privateModulus[ip]._digitN
                               , _privateModulus[1 - ip]._mod
                               , _privateModulus[1 - ip]._digitN
                               , dmsg[ip]);
                }
                Modular.Add(dmsg[0], dmsg[1], dmsg[0], _modDigits, _modDigitN);
                Digits.DigitsToBytes(
                    dmsg[0], output._Bytes, output._ByteI, output._BitN);
            }
Example #5
0
 void _Shift(Digits a, int n, Digits b)
 {
     if (a != b)
     {
         b._Set(a, _digitN);
     }
     Modular.ValidateData(a, _mod, _digitN);
     if (n < 0 && (_mod[0] & 1) == 0)
     {
         throw new ArgumentException();
     }
     while (n > 0)
     {
         int   shiftNow = n > Digit.BitN ? Digit.BitN : n;
         Digit carryOut = Digits.ShiftLost(b, shiftNow, b, _digitN)
         , qest         = _leftRecip
                          .EstQuotient(carryOut
                                       , b[_digitN - 1]
                                       , _digitN >= 2 ? b[_digitN - 2] : 0);
         carryOut -= Digits.Decumulate(_mod, qest, b, _digitN);
         if (carryOut != 0 || Digits.Compare(b, _mod, _digitN) >= 0)
         {
             carryOut -= Digits.Sub(b, _mod, b, _digitN);
         }
         Debug.Assert(carryOut == 0, "internal error");
         n -= shiftNow;
     }
     while (n < 0)
     {
         int   shiftNow = -n > Digit.BitN ? Digit.BitN : -n;
         Digit mul      = unchecked (0 - _rightRecip * b[0])
                          & Digit.MaxValue >> Digit.BitN - shiftNow
         , carry       = Digits.Accumulate(_mod, mul, b, _digitN)
         , lowBitNLost = Digits.ShiftLost(b, -shiftNow, b, _digitN);
         b[_digitN - 1] |= carry << Digit.BitN - shiftNow;
         Debug.Assert(lowBitNLost == 0, "internal error");
         n += shiftNow;
     }
 }
Example #6
0
 internal void _FromModular(Digits a, Digits b)
 {
     Modular.ValidateData(a, _mod, _digitN);
     _Shift(a, -_scaleBitN, b);
 }
Example #7
0
        _Exp(Digits @base, Digits exp, int expDigitN, Digits answer)
        {
            int expBitNUsed = Digits.SigBitN(exp, expDigitN);

            ushort[] widthCutoffs = new ushort[] { 6, 24, 80, 240, 672 };
            Digits   basepower    = answer;
            int      bucketWidth  = 1;

            while (
                bucketWidth < 5 && widthCutoffs[bucketWidth - 1] < expBitNUsed
                )
            {
                bucketWidth++;
            }
            Modular.ValidateData(@base, _mod, _digitN);
            UInt32    bucketMask = (1U << bucketWidth) - 1;
            UInt32    maxBucket  = bucketMask;
            Digits    bucketData = new Digits((int)(_digitN * maxBucket));
            Temps2000 temps      = new Temps2000();

            temps._modulus   = this;
            temps._bucket[0] = null;
            Modular.Add(_one, _one, bucketData, _mod, _digitN);
            bool base2 = Digits.Compare(@base, bucketData, _digitN) == 0;

            if (base2 && expBitNUsed != 0)
            {
                int shiftMax
                    = Digit.BitN * _digitN > 1024 ? 1024 : Digit.BitN * _digitN;
                int    highExponBitN     = 0;
                bool   bighBitNProcessed = false;
                Digits temp = bucketData;
                for (int i = expBitNUsed; i-- != 0;)
                {
                    Digit expBit = Digits.GetBit(exp, i);
                    if (bighBitNProcessed)
                    {
                        _Mul(temp, temp, temp);
                        if (expBit != 0)
                        {
                            Modular.Add(temp, temp, temp, _mod, _digitN);
                        }
                    }
                    else
                    {
                        highExponBitN = (int)(2 * highExponBitN + expBit);
                        if (i == 0 || 2 * highExponBitN >= shiftMax)
                        {
                            bighBitNProcessed = true;
                            _Shift(_one, highExponBitN, temp);
                        }
                    }
                }
                temps._bucket[1] = temp;
                Debug.Assert(bighBitNProcessed, "internal error");
            }
            else
            {
                UInt32 ibucket;
                for (ibucket = 1; ibucket <= maxBucket; ibucket++)
                {
                    Digits bloc = bucketData
                                  + (int)(_digitN
                                          * (ibucket
                                             - 1
                                             + ((ibucket & 1) == 0 ? maxBucket : 0))
                                          / 2);
                    temps._bucket[ibucket]     = bloc;
                    temps._bucketBusy[ibucket] = false;
                    bloc._Set(_one, _digitN);
                }
                basepower._Set(@base, _digitN);
                Digit carried   = 0;
                int   ndoubling = 0;
                for (int i = 0; i != expBitNUsed; i++)
                {
                    Digit bitNow = Digits.GetBit(exp, i);
                    Debug.Assert(carried >> bucketWidth + 2 == 0
                                 , "internal error");
                    if (bitNow != 0)
                    {
                        while (ndoubling >= bucketWidth + 1)
                        {
                            if ((carried & 1) != 0)
                            {
                                ibucket  = carried & bucketMask;
                                carried -= ibucket;
                                temps._modulus
                                ._BucketMul(ibucket, basepower, temps);
                            }
                            temps._modulus._BasePowerSquaring(basepower);
                            carried /= 2;
                            ndoubling--;
                        }
                        carried |= 1U << ndoubling;
                    }
                    ndoubling++;
                }
                while (carried != 0)
                {
                    bool squareNow = false;
                    if (carried <= maxBucket)
                    {
                        ibucket = carried;
                    }
                    else if ((carried & 1) == 0)
                    {
                        squareNow = true;
                    }
                    else if (carried <= 3 * maxBucket)
                    {
                        ibucket = maxBucket;
                    }
                    else
                    {
                        Debug.Assert(false, "untested code");
                        ibucket = carried & bucketMask;
                    }
                    if (squareNow)
                    {
                        carried /= 2;
                        temps._modulus._BasePowerSquaring(basepower);
                    }
                    else
                    {
                        carried -= ibucket;
                        temps._modulus._BucketMul(ibucket, basepower, temps);
                    }
                }
                for (ibucket = maxBucket; ibucket >= 2; ibucket--)
                {
                    if (temps._bucketBusy[ibucket])
                    {
                        bool   found = false;
                        UInt32 jbucket, jbucketMax, kbucket;
                        Digits bloci;
                        if ((ibucket & 1) == 0)
                        {
                            jbucketMax = ibucket / 2;
                        }
                        else
                        {
                            jbucketMax = 1;
                        }
                        for (
                            jbucket = ibucket >> 1;
                            jbucket != ibucket && !found;
                            jbucket++
                            )
                        {
                            if (temps._bucketBusy[jbucket])
                            {
                                jbucketMax = jbucket;
                                found      = temps._bucketBusy[ibucket - jbucket];
                            }
                        }
                        jbucket = jbucketMax;
                        kbucket = ibucket - jbucket;
                        bloci   = temps._bucket[ibucket];
                        temps._modulus._BucketMul(jbucket, bloci, temps);
                        temps._modulus._BucketMul(kbucket, bloci, temps);
                    }
                }
            }
            answer._Set(temps._bucket[1], _digitN);
        }
Example #8
0
        internal static Digits NewPrime(int pBitN, Random generator)
        {
            if (pBitN < Digit.BitN)
            {
                throw new ArgumentException();
            }
            int    pDigitN = (pBitN + (Digit.BitN - 1)) / Digit.BitN;
            Digits p       = new Digits(pDigitN);

            while (true)
            {
                for (
                    int iteration = 0;
                    iteration < _IterationsAllowed;
                    iteration++
                    )
                {
                    Digits.Random(p, pDigitN, generator);
                    p[pDigitN - 1] >>= Digit.BitN * pDigitN - pBitN;
                    p[0]            |= 1;
                    Digits.SetBit(p, pBitN - 1, 1);
                    Digits.SetBit(p, pBitN - 2, 1);
                    if (DivisibleBySomeLowPrime(p, pDigitN))
                    {
                        continue;
                    }
                    Modulus modulus = new Modulus(p, pDigitN, true);
                    Digits  minus1  = new Digits(pDigitN);
                    Modular
                    .Neg(modulus._one, minus1, modulus._mod, modulus._digitN);
                    Digits exp = new Digits(pDigitN);
                    Digits.Shift(p, -1, exp, pDigitN);
                    Digits @base = new Digits(pDigitN);
                    for (int i = 1; i <= _RabinTestN; i++)
                    {
                        if (i == 1)
                        {
                            Modular.Add(modulus._one
                                        , modulus._one
                                        , @base
                                        , modulus._mod
                                        , modulus._digitN);
                        }
                        else
                        {
                            Modular.NonZeroRandom(
                                p, @base, pDigitN, generator);
                        }
                        Digits result = new Digits(pDigitN);
                        modulus._Exp(@base, exp, pDigitN, result);
                        if (Digits.Compare(result, minus1, pDigitN) == 0)
                        {
                            return(p);
                        }
                        if (
                            Digits.Compare(result, modulus._one, pDigitN) != 0
                            )
                        {
                            break;
                        }
                    }
                }
                Debug.Assert(false, "too many iterations");
            }
        }