ln.crypto.ec/ln.crypto.ec/Euclid.cs

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;
}
}
}
}