private bool _MakeTest(OmgNum testBase) { OmgNum numDec = (new OmgNum(m_tested)).Dec(); OmgNum tested = OmgOp.Pow(testBase, m_initialTested, m_tested); OmgNum iterationsLeft = new OmgNum(m_powerOfTwo); try { if (OmgOp.Equal(tested, OmgNum.GetConst(1)) || OmgOp.Equal(tested, numDec)) { return(true); } while (!iterationsLeft.IsZero()) { iterationsLeft.Dec(); var nwTested = OmgOp.Multiply(tested, tested, m_tested); tested.Release(); tested = nwTested; if (OmgOp.Equal(tested, numDec)) { return(true); } } return(false); } finally { numDec.Release(); tested.Release(); iterationsLeft.Release(); } }
internal RawNum ExtendedGcd(RawNum left, RawNum right, out OmgNum x, out OmgNum y) { if (left.IsZero()) { x = 0.ToOmgNum(); y = 1.ToOmgNum(); RawNum gcd = OmgPool.GetRawZero(); gcd.CopyFrom(right); return(gcd); } var divModRes = OmgOp.DivMod(right.OmgWrapper(), left.OmgWrapper()); RawNum gcdRes = ExtendedGcd(divModRes.mod.Raw, left, out OmgNum x2, out OmgNum y2); divModRes.mod.Release(); OmgNum multRes = OmgOp.Multiply(divModRes.div, x2); divModRes.div.Release(); x = OmgOp.Subtract(y2, multRes); y2.Release(); multRes.Release(); y = x2; return(gcdRes); }
public OmgNum EulerFunction(OmgNum num) { var factorization = Factorize(num); var one = 1.ToOmgNum(); OmgNum result = 1.ToOmgNum(); foreach (var factor in factorization) { OmgNum phiP = null; if (factor.Value.IsOne()) { phiP = OmgOp.Subtract(factor.Key, one); } else { var pTonMinusOne = OmgOp.Pow(factor.Key, OmgOp.Subtract(factor.Value, one)); phiP = OmgOp.Multiply(pTonMinusOne, OmgOp.Subtract(factor.Key, one)); pTonMinusOne.Release(); } var nwRes = OmgOp.Multiply(result, phiP); result.Release(); phiP.Release(); result = nwRes; } return(result); }
private void _FactorPowerOfTwo(OmgNum num) { m_powerOfTwo?.Release(); m_initialTested?.Release(); var n = OmgOp.Subtract(num, OmgNum.GetConst(1)); m_powerOfTwo = 0.ToOmgNum(); (OmgNum div, OmgNum mod)divMod = OmgOp.DivMod(n, OmgNum.GetConst(2)); while (divMod.mod.IsZero()) { n.Release(); divMod.mod.Release(); n = divMod.div; m_powerOfTwo.Inc(); divMod = OmgOp.DivMod(n, OmgNum.GetConst(2)); } divMod.div.Release(); divMod.mod.Release(); m_initialTested = n; }
private OmgNum _FindPow(ref OmgNum num, OmgNum factor) { OmgNum pow = 0.ToOmgNum(); while (true) { var divMod = OmgOp.DivMod(num, factor); if (!divMod.mod.IsZero()) { break; } pow.Inc(); divMod.mod.Release(); num.Release(); num = divMod.div; } if (pow.IsZero()) { throw new Exception(); } return(pow); }
public OmgNum FindFactor(OmgNum n, int maxIterations = -1) { m_iterations = 0; m_current = n; OmgNum x = OmgOp.Random(1.ToOmgNum(), OmgOp.Subtract(n, 2.ToOmgNum())); OmgNum y = 1.ToOmgNum(); OmgNum i = 0.ToOmgNum(); OmgNum stage = 2.ToOmgNum(); OmgNum sub = OmgOp.Subtract(x, y).MakeAbs(); OmgNum gcd = OmgOp.Gcd(n, sub); sub.Release(); while (gcd.IsOne()) { if (maxIterations >= 0 && m_iterations++ > maxIterations) { return(null); } if (OmgOp.Equal(i, stage)) { y.Release(); y = new OmgNum(x); stage.MultByTwo(); } OmgNum xSquare = OmgOp.Multiply(x, x).Inc(); x.Release(); x = OmgOp.Mod(xSquare, n); xSquare.Release(); i.Inc(); sub = OmgOp.Subtract(x, y).MakeAbs(); gcd.Release(); gcd = OmgOp.Gcd(n, sub); sub.Release(); } return(gcd); }
private OmgNum _Carmichael(OmgNum phiP, OmgNum phiQ) { OmgNum pq = OmgOp.Multiply(phiP, phiQ); OmgNum pqGCD = OmgOp.Gcd(phiP, phiQ); OmgNum lcm = OmgOp.Div(pq, pqGCD); pq.Release(); pqGCD.Release(); return(lcm); }
public void SetTestedNumber(OmgNum num) { m_tested?.Release(); m_tested = num; m_shurelyNotAPrime = OmgOp.Less(num, OmgNum.GetConst(2)); m_shurelyNotAPrime = m_shurelyNotAPrime || !m_smallPrimeTester.IsPrime(m_tested); if (!m_shurelyNotAPrime && OmgOp.Greater(num, OmgNum.GetConst(1))) { _FactorPowerOfTwo(num); } }
private OmgNum _SelectExponent(OmgNum carmN) { OmgNum candidate = ((1 << 16) + 1).ToOmgNum(); OmgNum gcd = OmgOp.Gcd(candidate, carmN); while (!gcd.IsOne()) { gcd = OmgOp.Gcd(candidate.Inc(), carmN); } gcd.Release(); return(candidate); }
public SignaureKey GenerateSignature(int keyByteLength) { int componentLength = keyByteLength * 8 / 2; OmgNum p = m_primeSource.GeneratePrime(componentLength); OmgNum q = m_primeSource.GeneratePrime(componentLength); OmgNum n = OmgOp.Multiply(p, q); OmgNum carmN = _Carmichael(p.Dec(), q.Dec()); OmgNum e = _SelectRandomExponent(carmN, out OmgNum d); p.Release(); p.Release(); return(new SignaureKey { cert = new SignCertificate { N = n.Copy(), D = d }, secret = new SignSecret() { N = n, E = e } }); }
private bool _TestFailed(OmgNum num) { m_primeTester.SetTestedNumber(num.Copy()); for (int i = 0; i < m_testsPerNumber; i++) { OmgNum testBase = OmgOp.Random(OmgNum.GetConst(2), num); bool isPrime = m_primeTester.IsPrimeToBase(testBase); testBase.Release(); if (!isPrime) { return(true); } } return(false); }
private OmgNum _MakeFastPow(OmgNum left, RawNum right, OmgNum mod) { if (right.IsZero()) { var res = OmgPool.GetRawZero(); res.Digits.Add(1); return(new OmgNum(res)); } var rightCopy = OmgPool.GetRawZero(); rightCopy.CopyFrom(right); bool even = (rightCopy.Digits[0] & 1) == 0; if (even) { rightCopy.DivByTwo(); var p = _MakeFastPow(left, rightCopy, mod); OmgNum powSquare = OmgOp.Multiply(p, p); OmgNum powSquareModded = OmgOp.Mod(powSquare, mod); powSquare.Release(); p.Release(); OmgPool.ReleaseNumber(rightCopy); return(powSquareModded); } else { _SubOne(rightCopy); var p = _MakeFastPow(left, rightCopy, mod); OmgNum powPlusOne = OmgOp.Multiply(p, left); OmgNum powPlusOneModded = OmgOp.Mod(powPlusOne, mod); powPlusOne.Release(); p.Release(); OmgPool.ReleaseNumber(rightCopy); return(powPlusOneModded); } }
public static IEnumerable <OmgNum> Decode(IEnumerable <OmgNum> code, PrivKey key) { foreach (var num in code) { OmgNum m1 = OmgOp.Pow(num, key.dP, key.P); OmgNum m2 = OmgOp.Pow(num, key.dQ, key.Q); OmgNum mdif = OmgOp.Subtract(m1, m2); OmgNum h = OmgOp.Multiply(key.qInv, mdif, key.P); OmgNum hq = OmgOp.Multiply(h, key.Q); OmgNum m = OmgOp.Add(m2, hq); m1.Release(); m2.Release(); mdif.Release(); h.Release(); hq.Release(); yield return(m); } }
public OmgNum GeneratePrime(int bitLength) { if (bitLength < 0) { return(null); } if (bitLength == 0) { return(0.ToOmgNum()); } OmgNum randNum = OmgOp.Random(bitLength); while (_TestFailed(randNum)) { randNum.Release(); randNum = OmgOp.Random(bitLength); } return(randNum); }
internal RawNum MultiplyKaratsuba(RawNum left, RawNum right) { if (left.IsZero() || right.IsZero()) { return(OmgPool.GetRawZero()); } int n = Math.Min(left.Size, right.Size); (RawNum head, RawNum tail)leftSep = _SeparateHead(left, n); (RawNum head, RawNum tail)rightSep = _SeparateHead(right, n); RawNum headsProd = Multiply(leftSep.head, rightSep.head); RawNum tailsProd = Multiply(leftSep.tail, rightSep.tail); RawNum headTail = Multiply(leftSep.head, rightSep.tail); RawNum tailHead = Multiply(leftSep.tail, rightSep.head); OmgNum midSum = OmgOp.Add(new OmgNum(headTail), new OmgNum(tailHead)); m_multRaw = OmgPool.GetRawZero(); m_multRaw.CopyFrom(tailsProd); midSum.Raw.Digits.InsertRange(0, Enumerable.Repeat <uint>(0, n)); headsProd.Digits.InsertRange(0, Enumerable.Repeat <uint>(0, 2 * n)); OmgNum res = OmgOp.Add(new OmgNum(tailsProd), midSum); OmgNum finalRes = OmgOp.Add(new OmgNum(headsProd), res); midSum.Release(); res.Release(); OmgPool.ReleaseNumber(headTail); OmgPool.ReleaseNumber(tailHead); return(finalRes.Raw); }