73 lines
1.7 KiB
C#
73 lines
1.7 KiB
C#
using System;
|
|
using System.Numerics;
|
|
|
|
namespace ln.crypto.ec
|
|
{
|
|
public static class Euclid
|
|
{
|
|
|
|
public static Tuple<BigInteger,BigInteger,BigInteger> extended(BigInteger a, BigInteger b)
|
|
{
|
|
if (b.IsZero){
|
|
if (a != BigInteger.One){
|
|
throw new ArgumentException("Euclid found GCD>1!");
|
|
}
|
|
return new Tuple<BigInteger,BigInteger,BigInteger>(a, BigInteger.One, BigInteger.Zero);
|
|
}
|
|
Tuple<BigInteger,BigInteger,BigInteger> r = extended(b, a % b);
|
|
return new Tuple<BigInteger,BigInteger,BigInteger>(r.Item1,r.Item3,r.Item2 - ((a / b) * r.Item3) );
|
|
}
|
|
|
|
/**
|
|
* Implementation of inverse() like found at
|
|
* https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm (14 Oct 2017)
|
|
**/
|
|
public static BigInteger inverse(BigInteger a,BigInteger m){
|
|
BigInteger one, zero;
|
|
|
|
rt act, next, future;
|
|
|
|
one = BigInteger.One;
|
|
zero = BigInteger.Zero;
|
|
|
|
act = new rt(m, zero);
|
|
next = new rt(a, one);
|
|
|
|
while (!next.r.IsZero)
|
|
{
|
|
BigInteger q = act.r / next.r;
|
|
future = new rt(
|
|
act.r - (q * next.r),
|
|
act.t - (q * next.t)
|
|
);
|
|
|
|
//Console.WriteLine("EUCLID: q = {0}",q);
|
|
//Console.WriteLine("EUCLID: act: r = {0} / t = {1}",act.r,act.t);
|
|
//Console.WriteLine("EUCLID: next: r = {0} / t = {1}",next.r,next.t);
|
|
//Console.WriteLine("EUCLID: future: r = {0} / t = {1}",future.r,future.t);
|
|
|
|
act = next;
|
|
next = future;
|
|
}
|
|
|
|
if (act.r > one){
|
|
throw new NotSupportedException();
|
|
}
|
|
if (act.t < 0){
|
|
act.t += m;
|
|
}
|
|
|
|
return act.t;
|
|
}
|
|
|
|
private struct rt {
|
|
public BigInteger r, t;
|
|
|
|
public rt(BigInteger r,BigInteger t){
|
|
this.r = r;
|
|
this.t = t;
|
|
}
|
|
}
|
|
|
|
}
|
|
} |