Current section
Files
Jump to
Current section
Files
priv/dstu/src/math/ec/ECFieldElement.cs
using System;
namespace UA.Cryptography.EC
{
public abstract class ECFieldElement
{
public abstract BigInteger ToBigInteger();
public abstract string FieldName { get; }
public abstract int FieldSize { get; }
public abstract ECFieldElement Add(ECFieldElement b);
public abstract ECFieldElement Subtract(ECFieldElement b);
public abstract ECFieldElement Multiply(ECFieldElement b);
public abstract ECFieldElement Divide(ECFieldElement b);
public abstract ECFieldElement Negate();
public abstract ECFieldElement Square();
public abstract ECFieldElement Invert();
public abstract ECFieldElement Sqrt();
public override bool Equals(
object obj)
{
if (obj == this)
return true;
ECFieldElement other = obj as ECFieldElement;
if (other == null)
return false;
return Equals(other);
}
protected bool Equals(
ECFieldElement other)
{
return ToBigInteger().Equals(other.ToBigInteger());
}
public override int GetHashCode()
{
return ToBigInteger().GetHashCode();
}
public override string ToString()
{
return this.ToBigInteger().ToString(2);
}
}
public class F2mFieldElement
: ECFieldElement
{
public const int Gnb = 1;
public const int Tpb = 2;
public const int Ppb = 3;
private int representation;
private int m;
private int k1;
private int k2;
private int k3;
private IntArray x;
private readonly int t;
public F2mFieldElement(
int m,
int k1,
int k2,
int k3,
BigInteger x)
{
// t = m / 32 rounded up to the next integer
this.t = (m + 31) >> 5;
this.x = new IntArray(x, t);
if ((k2 == 0) && (k3 == 0))
{
this.representation = Tpb;
}
else
{
if (k2 >= k3)
throw new ArgumentException("k2 must be smaller than k3");
if (k2 <= 0)
throw new ArgumentException("k2 must be larger than 0");
this.representation = Ppb;
}
if (x.SignValue < 0)
throw new ArgumentException("x value cannot be negative");
this.m = m;
this.k1 = k1;
this.k2 = k2;
this.k3 = k3;
}
public F2mFieldElement(
int m,
int k,
BigInteger x)
: this(m, k, 0, 0, x)
{
// Set k1 to k, and set k2 and k3 to 0
}
private F2mFieldElement(int m, int k1, int k2, int k3, IntArray x)
{
t = (m + 31) >> 5;
this.x = x;
this.m = m;
this.k1 = k1;
this.k2 = k2;
this.k3 = k3;
if ((k2 == 0) && (k3 == 0))
{
this.representation = Tpb;
}
else
{
this.representation = Ppb;
}
}
public override BigInteger ToBigInteger()
{
return x.ToBigInteger();
}
public override string FieldName
{
get { return "F2m"; }
}
public override int FieldSize
{
get { return m; }
}
public static void CheckFieldElements(
ECFieldElement a,
ECFieldElement b)
{
if (!(a is F2mFieldElement) || !(b is F2mFieldElement))
{
throw new ArgumentException("Field elements are not "
+ "both instances of F2mFieldElement");
}
F2mFieldElement aF2m = (F2mFieldElement)a;
F2mFieldElement bF2m = (F2mFieldElement)b;
if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1)
|| (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3))
{
throw new ArgumentException("Field elements are not "
+ "elements of the same field F2m");
}
if (aF2m.representation != bF2m.representation)
{
// Should never occur
throw new ArgumentException(
"One of the field "
+ "elements are not elements has incorrect representation");
}
}
public override ECFieldElement Add(
ECFieldElement b)
{
IntArray iarrClone = (IntArray) this.x.Clone();
F2mFieldElement bF2m = (F2mFieldElement) b;
iarrClone.AddShifted(bF2m.x, 0);
return new F2mFieldElement(m, k1, k2, k3, iarrClone);
}
public override ECFieldElement Subtract(
ECFieldElement b)
{
return Add(b);
}
public override ECFieldElement Multiply(
ECFieldElement b)
{
F2mFieldElement bF2m = (F2mFieldElement) b;
IntArray mult = x.Multiply(bF2m.x, m);
mult.Reduce(m, new int[]{k1, k2, k3});
return new F2mFieldElement(m, k1, k2, k3, mult);
}
public override ECFieldElement Divide(
ECFieldElement b)
{
ECFieldElement bInv = b.Invert();
return Multiply(bInv);
}
public override ECFieldElement Negate()
{
return this;
}
public override ECFieldElement Square()
{
IntArray squared = x.Square(m);
squared.Reduce(m, new int[]{k1, k2, k3});
return new F2mFieldElement(m, k1, k2, k3, squared);
}
public override ECFieldElement Invert()
{
IntArray uz = (IntArray)this.x.Clone();
IntArray vz = new IntArray(t);
vz.SetBit(m);
vz.SetBit(0);
vz.SetBit(this.k1);
if (this.representation == Ppb)
{
vz.SetBit(this.k2);
vz.SetBit(this.k3);
}
IntArray g1z = new IntArray(t);
g1z.SetBit(0);
IntArray g2z = new IntArray(t);
while (uz.GetUsedLength() > 0)
{
int j = uz.BitLength - vz.BitLength;
if (j < 0)
{
IntArray uzCopy = uz;
uz = vz;
vz = uzCopy;
IntArray g1zCopy = g1z;
g1z = g2z;
g2z = g1zCopy;
j = -j;
}
int jInt = j >> 5;
int jBit = j & 0x1F;
IntArray vzShift = vz.ShiftLeft(jBit);
uz.AddShifted(vzShift, jInt);
IntArray g2zShift = g2z.ShiftLeft(jBit);
g1z.AddShifted(g2zShift, jInt);
}
return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, g2z);
}
public override ECFieldElement Sqrt()
{
throw new ArithmeticException("Not implemented");
}
public int Representation
{
get { return this.representation; }
}
public int M
{
get { return this.m; }
}
public int K1
{
get { return this.k1; }
}
public int K2
{
get { return this.k2; }
}
public int K3
{
get { return this.k3; }
}
public override bool Equals(
object obj)
{
if (obj == this)
return true;
F2mFieldElement other = obj as F2mFieldElement;
if (other == null)
return false;
return Equals(other);
}
protected bool Equals(
F2mFieldElement other)
{
return m == other.m
&& k1 == other.k1
&& k2 == other.k2
&& k3 == other.k3
&& representation == other.representation
&& base.Equals(other);
}
public override int GetHashCode()
{
return m.GetHashCode()
^ k1.GetHashCode()
^ k2.GetHashCode()
^ k3.GetHashCode()
^ representation.GetHashCode()
^ base.GetHashCode();
}
}
}