Sub(Digits a, Digits b, Digits c, Digits mod, int n) { Debug.Assert(n > 0, "internal error"); Digit alead = a[n - 1], blead = b[n - 1], mlead = mod[n - 1]; int itest; if (alead == blead) { itest = Digits.Compare(a, b, n - 1); } else { itest = alead < blead ? -1 : +1; } if (itest < 0) { if (blead >= mlead) { ValidateData(b, mod, n); } int carry = Digits.AddSub(a, mod, b, c, n); Debug.Assert(carry == 0, "internal error"); } else { if (alead >= mlead) { Debug.Assert(false, "untested code"); ValidateData(a, mod, n); } uint borrow = Digits.Sub(a, b, c, n); Debug.Assert(borrow == 0, "internal error"); } }
internal static void Neg(Digits a, Digits b, Digits mod, int n) { Digit allZero = 0; for (int i = 0; i != n; i++) { allZero |= a[i]; b[i] = a[i]; } if (allZero != 0) { if (Digits.Sub(mod, b, b, n) != 0) { throw new ArgumentException(); } } }
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; } }
internal Modulus(Digits mod, int digitN, bool fromRight) { if (digitN == 0 || mod[digitN - 1] == 0) { throw new ArgumentException(); } _mod = mod; _digitN = digitN; _fromRight = fromRight; _one = new Digits(digitN); _multiplier1 = new Digits(digitN); _multiplier2 = new Digits(digitN); // this.mod.Set(this.mod, _digitN); _leftRecip = new Reciprocal(); Digits.DivPrecondition(mod, digitN, _leftRecip); Digit mod0inv = 0; if ((mod[0] & 1) != 0) { mod0inv = Digit.TwoAdicInverse(mod[0]); } _rightRecip = mod0inv; int digitN2 = (digitN + 1) / 2; Digits temp = new Digits(digitN + digitN2); if (!fromRight) { _algorithm = new MulAlgorithm(_MulFromLeft); int dividendN = digitN + digitN2; _scaleBitN = 0; for (int i = 0; i != dividendN; i++) { temp[i] = Digit.MaxValue; } temp[dividendN - 1] = Digit.MaxValue >> _leftRecip._shiftBitN; Digits q = new Digits(digitN2 + 1); Digits r = new Digits(digitN); Digits.Div(temp, dividendN, mod, digitN, _leftRecip, q, r); Debug.Assert(q[digitN2] == 1, "internal error"); Digits.Add(r, 1U, r, digitN); Digits.Sub(mod, r, r, digitN); } else { _algorithm = new MulAlgorithm(_MulFromRight); _scaleBitN = Digit.BitN * digitN; if (mod0inv == 0) { throw new ArgumentException(); } _multiplier2[0] = mod0inv; temp[digitN] = Digits.Mul(mod, mod0inv, temp, digitN); Debug.Assert(temp[0] == 1, "internal error"); for (int i = 1; i != digitN2; i++) { Digit mul = unchecked (0 - mod0inv * temp[i]); _multiplier2[i] = mul; temp[i + digitN] = Digits.Accumulate(mod, mul, temp + i, digitN); Debug.Assert(temp[i] == 0, "internal error"); } _multiplier1._Set(temp + digitN2, digitN); } _ToModular(new Digits(new Digit[] { 1 }), 1, _one); }
public Key(int bitN, Random generator) { _modBitN = bitN; // The public exponent is 2^16 + 1 _eBitN = 17; _eBytes = new byte[] { 1, 0, 1 }; int p1BitN = (bitN + 1) / 2 , p1ByteN = (p1BitN + 7) / 8 , p1DigitN = (p1BitN + (Digit.BitN - 1)) / Digit.BitN , p2BitN = bitN / 2 , p2ByteN = (p2BitN + 7) / 8 , p2DigitN = (p2BitN + (Digit.BitN - 1)) / Digit.BitN , longerDigitN = p1DigitN > p2DigitN ? p1DigitN : p2DigitN; Digits d1 = new Digits(p1DigitN), d2 = new Digits(p2DigitN); _modDigits = new Digits(_modDigitN); _eDigits = new Digits(1); Digits gcd = new Digits(longerDigitN) , temp = new Digits(longerDigitN); Digits.BytesToDigits(_eBytes, 0, _eDigits, _eBitN); int[] pBitN = new int[] { p1BitN, p2BitN }; int nPrimeFound = 0; Digits p1 = null, p2 = null; while (nPrimeFound != 2) { int pNowBitN = pBitN[nPrimeFound] , pNowDigitN = (pNowBitN + (Digit.BitN - 1)) / Digit.BitN; Digits pNow = Prime.NewPrime(pNowBitN, generator); if (nPrimeFound == 0) { p1 = pNow; } else { p2 = pNow; } Digits.Sub(pNow, 1, temp, pNowDigitN); int lgcd; Digits.ExtendedGcd(_eDigits , _eDigitN , temp , pNowDigitN , nPrimeFound == 0 ? d1 : d2 , null , gcd , out lgcd); if (Digits.Compare(gcd, 1, lgcd) != 0) { Debug.Assert(false, "untested code"); continue; } if ( nPrimeFound == 1 && Digits.Compare(p1, p1DigitN, p2, p2DigitN) == 0 ) { Debug.Assert(false, "untested code"); continue; } nPrimeFound++; } Digits.Mul(p1, p1DigitN, p2, p2DigitN, _modDigits); int modBitN = Digits.SigBitN(_modDigits, _modDigitN); Debug.Assert(modBitN == p1BitN + p2BitN && modBitN == _modBitN , "internal error"); _primeBitN = new int[2] { p1BitN, p2BitN }; _modBytes = new byte[_modByteN]; _primeBytes = new byte[2][] { new byte[p1ByteN], new byte[p2ByteN] }; _dBytes = new byte[2][] { new byte[p1ByteN], new byte[p2ByteN] }; Digits.DigitsToBytes(_modDigits, _modBytes, 0, _modBitN); for (int ip = 0; ip != 2; ip++) { Digits.DigitsToBytes( ip == 0 ? p1 : p2, _primeBytes[ip], 0, pBitN[ip]); Digits.DigitsToBytes( ip == 0 ? d1 : d2, _dBytes[ip], 0, pBitN[ip]); } int moduliCreated = 0; Digits.BytesToDigits(_eBytes, 0, _eDigits, _eBitN); _modulus = new Modulus(_modDigits, _modDigitN, true); _privateModulus = new Modulus[2]; _dDigits = new Digits[2]; _chineseDigits = new Digits[2]; for (int ip = 0; ip != 2; ip++) { Digits temp2 = new Digits(_modDigitN); _dDigits[ip] = new Digits(p1DigitN); _chineseDigits[ip] = new Digits(p1DigitN); Digits.BytesToDigits( _primeBytes[ip], 0, temp2, _primeBitN[ip]); _privateModulus[ip] = new Modulus(temp2 , (_primeBitN[ip] + (Digit.BitN - 1)) / Digit.BitN , true); moduliCreated++; Digits.BytesToDigits( _dBytes[ip], 0, _dDigits[ip], _primeBitN[ip]); } int lgcd2 = 0; Digits gcd2 = new Digits(_modDigitN); Digits.ExtendedGcd(_privateModulus[0]._mod , p1DigitN , _privateModulus[1]._mod , p2DigitN , _chineseDigits[1] , _chineseDigits[0] , gcd2 , out lgcd2); if (Digits.Compare(gcd2, 1, lgcd2) != 0) { throw new ArgumentException(); } }