TLSharp/TLSharp.Core/MTProto/Crypto/Factorizator.cs

105 lines
3 KiB
C#
Raw Normal View History

2015-09-28 04:01:17 +02:00
using System;
2016-04-18 12:50:57 +02:00
namespace TLSharp.Core.MTProto.Crypto
{
public class FactorizedPair
{
2015-09-28 04:01:17 +02:00
private readonly BigInteger p;
private readonly BigInteger q;
2016-04-18 12:50:57 +02:00
public FactorizedPair(BigInteger p, BigInteger q)
{
2015-09-28 04:01:17 +02:00
this.p = p;
this.q = q;
}
2016-04-18 12:50:57 +02:00
public FactorizedPair(long p, long q)
{
2015-09-28 04:01:17 +02:00
this.p = BigInteger.ValueOf(p);
this.q = BigInteger.ValueOf(q);
}
2017-04-13 08:38:01 +02:00
public BigInteger Min => p.Min(q);
2015-09-28 04:01:17 +02:00
2017-04-13 08:38:01 +02:00
public BigInteger Max => p.Max(q);
2015-09-28 04:01:17 +02:00
2016-04-18 12:50:57 +02:00
public override string ToString()
{
2015-09-28 04:01:17 +02:00
return string.Format("P: {0}, Q: {1}", p, q);
}
}
2017-04-13 08:38:01 +02:00
2016-04-18 12:50:57 +02:00
public class Factorizator
{
2015-09-28 04:01:17 +02:00
public static Random random = new Random();
2017-04-13 08:38:01 +02:00
2016-04-18 12:50:57 +02:00
public static long findSmallMultiplierLopatin(long what)
{
2015-09-28 04:01:17 +02:00
long g = 0;
2017-04-13 08:38:01 +02:00
for (var i = 0; i < 3; i++)
2016-04-18 12:50:57 +02:00
{
2017-04-13 08:38:01 +02:00
var q = (random.Next(128) & 15) + 17;
2015-09-28 04:01:17 +02:00
long x = random.Next(1000000000) + 1, y = x;
2017-04-13 08:38:01 +02:00
var lim = 1 << (i + 18);
for (var j = 1; j < lim; j++)
2016-04-18 12:50:57 +02:00
{
2015-09-28 04:01:17 +02:00
long a = x, b = x, c = q;
2016-04-18 12:50:57 +02:00
while (b != 0)
{
if ((b & 1) != 0)
{
2015-09-28 04:01:17 +02:00
c += a;
2016-04-18 12:50:57 +02:00
if (c >= what)
2015-09-28 04:01:17 +02:00
c -= what;
}
a += a;
2016-04-18 12:50:57 +02:00
if (a >= what)
2015-09-28 04:01:17 +02:00
a -= what;
b >>= 1;
}
x = c;
2017-04-13 08:38:01 +02:00
var z = x < y ? y - x : x - y;
2015-09-28 04:01:17 +02:00
g = GCD(z, what);
2016-04-18 12:50:57 +02:00
if (g != 1)
2015-09-28 04:01:17 +02:00
break;
2016-04-18 12:50:57 +02:00
if ((j & (j - 1)) == 0)
2015-09-28 04:01:17 +02:00
y = x;
}
2016-04-18 12:50:57 +02:00
if (g > 1)
2015-09-28 04:01:17 +02:00
break;
}
2017-04-13 08:38:01 +02:00
var p = what / g;
2015-09-28 04:01:17 +02:00
return Math.Min(p, g);
}
2016-04-18 12:50:57 +02:00
public static long GCD(long a, long b)
{
while (a != 0 && b != 0)
{
while ((b & 1) == 0)
2015-09-28 04:01:17 +02:00
b >>= 1;
2016-04-18 12:50:57 +02:00
while ((a & 1) == 0)
2015-09-28 04:01:17 +02:00
a >>= 1;
2016-04-18 12:50:57 +02:00
if (a > b)
2015-09-28 04:01:17 +02:00
a -= b;
2017-04-13 08:38:01 +02:00
else b -= a;
2015-09-28 04:01:17 +02:00
}
return b == 0 ? a : b;
}
2016-04-18 12:50:57 +02:00
public static FactorizedPair Factorize(BigInteger pq)
{
if (pq.BitLength < 64)
{
2017-04-13 08:38:01 +02:00
var pqlong = pq.LongValue;
var divisor = findSmallMultiplierLopatin(pqlong);
2016-04-18 12:50:57 +02:00
return new FactorizedPair(BigInteger.ValueOf(divisor), BigInteger.ValueOf(pqlong / divisor));
}
2017-04-13 08:38:01 +02:00
// 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;
2015-09-28 04:01:17 +02:00
}
}
2017-04-13 08:38:01 +02:00
}