Initial Commit
This commit is contained in:
566
iTechSharp/srcbc/math/ec/ECPoint.cs
Normal file
566
iTechSharp/srcbc/math/ec/ECPoint.cs
Normal file
@@ -0,0 +1,566 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
|
||||
using Org.BouncyCastle.Math.EC.Multiplier;
|
||||
|
||||
namespace Org.BouncyCastle.Math.EC
|
||||
{
|
||||
/**
|
||||
* base class for points on elliptic curves.
|
||||
*/
|
||||
public abstract class ECPoint
|
||||
{
|
||||
internal readonly ECCurve curve;
|
||||
internal readonly ECFieldElement x, y;
|
||||
internal readonly bool withCompression;
|
||||
internal ECMultiplier multiplier = null;
|
||||
internal PreCompInfo preCompInfo = null;
|
||||
|
||||
protected internal ECPoint(
|
||||
ECCurve curve,
|
||||
ECFieldElement x,
|
||||
ECFieldElement y,
|
||||
bool withCompression)
|
||||
{
|
||||
if (curve == null)
|
||||
throw new ArgumentNullException("curve");
|
||||
|
||||
this.curve = curve;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.withCompression = withCompression;
|
||||
}
|
||||
|
||||
public ECCurve Curve
|
||||
{
|
||||
get { return curve; }
|
||||
}
|
||||
|
||||
public ECFieldElement X
|
||||
{
|
||||
get { return x; }
|
||||
}
|
||||
|
||||
public ECFieldElement Y
|
||||
{
|
||||
get { return y; }
|
||||
}
|
||||
|
||||
public bool IsInfinity
|
||||
{
|
||||
get { return x == null && y == null; }
|
||||
}
|
||||
|
||||
public bool IsCompressed
|
||||
{
|
||||
get { return withCompression; }
|
||||
}
|
||||
|
||||
public override bool Equals(
|
||||
object obj)
|
||||
{
|
||||
if (obj == this)
|
||||
return true;
|
||||
|
||||
ECPoint o = obj as ECPoint;
|
||||
|
||||
if (o == null)
|
||||
return false;
|
||||
|
||||
if (this.IsInfinity)
|
||||
return o.IsInfinity;
|
||||
|
||||
return x.Equals(o.x) && y.Equals(o.y);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (this.IsInfinity)
|
||||
return 0;
|
||||
|
||||
return x.GetHashCode() ^ y.GetHashCode();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Mainly for testing. Explicitly set the <code>ECMultiplier</code>.
|
||||
// * @param multiplier The <code>ECMultiplier</code> to be used to multiply
|
||||
// * this <code>ECPoint</code>.
|
||||
// */
|
||||
// internal void SetECMultiplier(
|
||||
// ECMultiplier multiplier)
|
||||
// {
|
||||
// this.multiplier = multiplier;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s
|
||||
* to save the precomputation for this <code>ECPoint</code> to store the
|
||||
* precomputation result for use by subsequent multiplication.
|
||||
* @param preCompInfo The values precomputed by the
|
||||
* <code>ECMultiplier</code>.
|
||||
*/
|
||||
internal void SetPreCompInfo(
|
||||
PreCompInfo preCompInfo)
|
||||
{
|
||||
this.preCompInfo = preCompInfo;
|
||||
}
|
||||
|
||||
public abstract byte[] GetEncoded();
|
||||
|
||||
public abstract ECPoint Add(ECPoint b);
|
||||
public abstract ECPoint Subtract(ECPoint b);
|
||||
public abstract ECPoint Negate();
|
||||
public abstract ECPoint Twice();
|
||||
public abstract ECPoint Multiply(BigInteger b);
|
||||
|
||||
/**
|
||||
* Sets the appropriate <code>ECMultiplier</code>, unless already set.
|
||||
*/
|
||||
internal virtual void AssertECMultiplier()
|
||||
{
|
||||
if (this.multiplier == null)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (this.multiplier == null)
|
||||
{
|
||||
this.multiplier = new FpNafMultiplier();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ECPointBase
|
||||
: ECPoint
|
||||
{
|
||||
protected internal ECPointBase(
|
||||
ECCurve curve,
|
||||
ECFieldElement x,
|
||||
ECFieldElement y,
|
||||
bool withCompression)
|
||||
: base(curve, x, y, withCompression)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal abstract bool YTilde { get; }
|
||||
|
||||
/**
|
||||
* return the field element encoded with point compression. (S 4.3.6)
|
||||
*/
|
||||
public override byte[] GetEncoded()
|
||||
{
|
||||
if (this.IsInfinity)
|
||||
return new byte[1];
|
||||
|
||||
// Note: some of the tests rely on calculating byte length from the field element
|
||||
// (since the test cases use mismatching fields for curve/elements)
|
||||
int byteLength = X9IntegerConverter.GetByteLength(x);
|
||||
byte[] X = X9IntegerConverter.IntegerToBytes(this.X.ToBigInteger(), byteLength);
|
||||
byte[] PO;
|
||||
|
||||
if (withCompression)
|
||||
{
|
||||
PO = new byte[1 + X.Length];
|
||||
|
||||
PO[0] = (byte)(YTilde ? 0x03 : 0x02);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] Y = X9IntegerConverter.IntegerToBytes(this.Y.ToBigInteger(), byteLength);
|
||||
PO = new byte[1 + X.Length + Y.Length];
|
||||
|
||||
PO[0] = 0x04;
|
||||
|
||||
Y.CopyTo(PO, 1 + X.Length);
|
||||
}
|
||||
|
||||
X.CopyTo(PO, 1);
|
||||
|
||||
return PO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies this <code>ECPoint</code> by the given number.
|
||||
* @param k The multiplicator.
|
||||
* @return <code>k * this</code>.
|
||||
*/
|
||||
public override ECPoint Multiply(
|
||||
BigInteger k)
|
||||
{
|
||||
if (this.IsInfinity)
|
||||
return this;
|
||||
|
||||
if (k.SignValue == 0)
|
||||
return this.curve.Infinity;
|
||||
|
||||
AssertECMultiplier();
|
||||
return this.multiplier.Multiply(this, k, preCompInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Elliptic curve points over Fp
|
||||
*/
|
||||
public class FpPoint
|
||||
: ECPointBase
|
||||
{
|
||||
/**
|
||||
* Create a point which encodes with point compression.
|
||||
*
|
||||
* @param curve the curve to use
|
||||
* @param x affine x co-ordinate
|
||||
* @param y affine y co-ordinate
|
||||
*/
|
||||
public FpPoint(
|
||||
ECCurve curve,
|
||||
ECFieldElement x,
|
||||
ECFieldElement y)
|
||||
: this(curve, x, y, false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a point that encodes with or without point compresion.
|
||||
*
|
||||
* @param curve the curve to use
|
||||
* @param x affine x co-ordinate
|
||||
* @param y affine y co-ordinate
|
||||
* @param withCompression if true encode with point compression
|
||||
*/
|
||||
public FpPoint(
|
||||
ECCurve curve,
|
||||
ECFieldElement x,
|
||||
ECFieldElement y,
|
||||
bool withCompression)
|
||||
: base(curve, x, y, withCompression)
|
||||
{
|
||||
if ((x != null && y == null) || (x == null && y != null))
|
||||
throw new ArgumentException("Exactly one of the field elements is null");
|
||||
}
|
||||
|
||||
protected internal override bool YTilde
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Y.ToBigInteger().TestBit(0);
|
||||
}
|
||||
}
|
||||
|
||||
// B.3 pg 62
|
||||
public override ECPoint Add(
|
||||
ECPoint b)
|
||||
{
|
||||
if (this.IsInfinity)
|
||||
return b;
|
||||
|
||||
if (b.IsInfinity)
|
||||
return this;
|
||||
|
||||
// Check if b = this or b = -this
|
||||
if (this.x.Equals(b.x))
|
||||
{
|
||||
if (this.y.Equals(b.y))
|
||||
{
|
||||
// this = b, i.e. this must be doubled
|
||||
return this.Twice();
|
||||
}
|
||||
|
||||
Debug.Assert(this.y.Equals(b.y.Negate()));
|
||||
|
||||
// this = -b, i.e. the result is the point at infinity
|
||||
return this.curve.Infinity;
|
||||
}
|
||||
|
||||
ECFieldElement gamma = b.y.Subtract(this.y).Divide(b.x.Subtract(this.x));
|
||||
|
||||
ECFieldElement x3 = gamma.Square().Subtract(this.x).Subtract(b.x);
|
||||
ECFieldElement y3 = gamma.Multiply(this.x.Subtract(x3)).Subtract(this.y);
|
||||
|
||||
return new FpPoint(curve, x3, y3);
|
||||
}
|
||||
|
||||
// B.3 pg 62
|
||||
public override ECPoint Twice()
|
||||
{
|
||||
// Twice identity element (point at infinity) is identity
|
||||
if (this.IsInfinity)
|
||||
return this;
|
||||
|
||||
// if y1 == 0, then (x1, y1) == (x1, -y1)
|
||||
// and hence this = -this and thus 2(x1, y1) == infinity
|
||||
if (this.y.ToBigInteger().SignValue == 0)
|
||||
return this.curve.Infinity;
|
||||
|
||||
ECFieldElement TWO = this.curve.FromBigInteger(BigInteger.Two);
|
||||
ECFieldElement THREE = this.curve.FromBigInteger(BigInteger.Three);
|
||||
ECFieldElement gamma = this.x.Square().Multiply(THREE).Add(curve.a).Divide(y.Multiply(TWO));
|
||||
|
||||
ECFieldElement x3 = gamma.Square().Subtract(this.x.Multiply(TWO));
|
||||
ECFieldElement y3 = gamma.Multiply(this.x.Subtract(x3)).Subtract(this.y);
|
||||
|
||||
return new FpPoint(curve, x3, y3, this.withCompression);
|
||||
}
|
||||
|
||||
// D.3.2 pg 102 (see Note:)
|
||||
public override ECPoint Subtract(
|
||||
ECPoint b)
|
||||
{
|
||||
if (b.IsInfinity)
|
||||
return this;
|
||||
|
||||
// Add -b
|
||||
return Add(b.Negate());
|
||||
}
|
||||
|
||||
public override ECPoint Negate()
|
||||
{
|
||||
return new FpPoint(this.curve, this.x, this.y.Negate(), this.withCompression);
|
||||
}
|
||||
|
||||
// TODO Uncomment this to enable WNAF Fp point multiplication
|
||||
// /**
|
||||
// * Sets the default <code>ECMultiplier</code>, unless already set.
|
||||
// */
|
||||
// internal override void AssertECMultiplier()
|
||||
// {
|
||||
// if (this.multiplier == null)
|
||||
// {
|
||||
// lock (this)
|
||||
// {
|
||||
// if (this.multiplier == null)
|
||||
// {
|
||||
// this.multiplier = new WNafMultiplier();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Elliptic curve points over F2m
|
||||
*/
|
||||
public class F2mPoint
|
||||
: ECPointBase
|
||||
{
|
||||
/**
|
||||
* @param curve base curve
|
||||
* @param x x point
|
||||
* @param y y point
|
||||
*/
|
||||
public F2mPoint(
|
||||
ECCurve curve,
|
||||
ECFieldElement x,
|
||||
ECFieldElement y)
|
||||
: this(curve, x, y, false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param curve base curve
|
||||
* @param x x point
|
||||
* @param y y point
|
||||
* @param withCompression true if encode with point compression.
|
||||
*/
|
||||
public F2mPoint(
|
||||
ECCurve curve,
|
||||
ECFieldElement x,
|
||||
ECFieldElement y,
|
||||
bool withCompression)
|
||||
: base(curve, x, y, withCompression)
|
||||
{
|
||||
if ((x != null && y == null) || (x == null && y != null))
|
||||
{
|
||||
throw new ArgumentException("Exactly one of the field elements is null");
|
||||
}
|
||||
|
||||
if (x != null)
|
||||
{
|
||||
// Check if x and y are elements of the same field
|
||||
F2mFieldElement.CheckFieldElements(this.x, this.y);
|
||||
|
||||
// Check if x and a are elements of the same field
|
||||
F2mFieldElement.CheckFieldElements(this.x, this.curve.A);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for point at infinity
|
||||
*/
|
||||
[Obsolete("Use ECCurve.Infinity property")]
|
||||
public F2mPoint(
|
||||
ECCurve curve)
|
||||
: this(curve, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override bool YTilde
|
||||
{
|
||||
get
|
||||
{
|
||||
// X9.62 4.2.2 and 4.3.6:
|
||||
// if x = 0 then ypTilde := 0, else ypTilde is the rightmost
|
||||
// bit of y * x^(-1)
|
||||
return this.X.ToBigInteger().SignValue != 0
|
||||
&& this.Y.Multiply(this.X.Invert()).ToBigInteger().TestBit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check, if two <code>ECPoint</code>s can be added or subtracted.
|
||||
* @param a The first <code>ECPoint</code> to check.
|
||||
* @param b The second <code>ECPoint</code> to check.
|
||||
* @throws IllegalArgumentException if <code>a</code> and <code>b</code>
|
||||
* cannot be added.
|
||||
*/
|
||||
private static void CheckPoints(
|
||||
ECPoint a,
|
||||
ECPoint b)
|
||||
{
|
||||
// Check, if points are on the same curve
|
||||
if (!a.curve.Equals(b.curve))
|
||||
throw new ArgumentException("Only points on the same curve can be added or subtracted");
|
||||
|
||||
// F2mFieldElement.CheckFieldElements(a.x, b.x);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint)
|
||||
*/
|
||||
public override ECPoint Add(ECPoint b)
|
||||
{
|
||||
CheckPoints(this, b);
|
||||
return AddSimple((F2mPoint) b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds another <code>ECPoints.F2m</code> to <code>this</code> without
|
||||
* checking if both points are on the same curve. Used by multiplication
|
||||
* algorithms, because there all points are a multiple of the same point
|
||||
* and hence the checks can be omitted.
|
||||
* @param b The other <code>ECPoints.F2m</code> to add to
|
||||
* <code>this</code>.
|
||||
* @return <code>this + b</code>
|
||||
*/
|
||||
internal F2mPoint AddSimple(F2mPoint b)
|
||||
{
|
||||
if (this.IsInfinity)
|
||||
return b;
|
||||
|
||||
if (b.IsInfinity)
|
||||
return this;
|
||||
|
||||
F2mFieldElement x2 = (F2mFieldElement) b.X;
|
||||
F2mFieldElement y2 = (F2mFieldElement) b.Y;
|
||||
|
||||
// Check if b == this or b == -this
|
||||
if (this.x.Equals(x2))
|
||||
{
|
||||
// this == b, i.e. this must be doubled
|
||||
if (this.y.Equals(y2))
|
||||
return (F2mPoint) this.Twice();
|
||||
|
||||
// this = -other, i.e. the result is the point at infinity
|
||||
return (F2mPoint) this.curve.Infinity;
|
||||
}
|
||||
|
||||
ECFieldElement xSum = this.x.Add(x2);
|
||||
|
||||
F2mFieldElement lambda
|
||||
= (F2mFieldElement)(this.y.Add(y2)).Divide(xSum);
|
||||
|
||||
F2mFieldElement x3
|
||||
= (F2mFieldElement)lambda.Square().Add(lambda).Add(xSum).Add(this.curve.A);
|
||||
|
||||
F2mFieldElement y3
|
||||
= (F2mFieldElement)lambda.Multiply(this.x.Add(x3)).Add(x3).Add(this.y);
|
||||
|
||||
return new F2mPoint(curve, x3, y3, withCompression);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint)
|
||||
*/
|
||||
public override ECPoint Subtract(
|
||||
ECPoint b)
|
||||
{
|
||||
CheckPoints(this, b);
|
||||
return SubtractSimple((F2mPoint) b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
|
||||
* without checking if both points are on the same curve. Used by
|
||||
* multiplication algorithms, because there all points are a multiple
|
||||
* of the same point and hence the checks can be omitted.
|
||||
* @param b The other <code>ECPoints.F2m</code> to subtract from
|
||||
* <code>this</code>.
|
||||
* @return <code>this - b</code>
|
||||
*/
|
||||
internal F2mPoint SubtractSimple(
|
||||
F2mPoint b)
|
||||
{
|
||||
if (b.IsInfinity)
|
||||
return this;
|
||||
|
||||
// Add -b
|
||||
return AddSimple((F2mPoint) b.Negate());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see Org.BouncyCastle.Math.EC.ECPoint#twice()
|
||||
*/
|
||||
public override ECPoint Twice()
|
||||
{
|
||||
// Twice identity element (point at infinity) is identity
|
||||
if (this.IsInfinity)
|
||||
return this;
|
||||
|
||||
// if x1 == 0, then (x1, y1) == (x1, x1 + y1)
|
||||
// and hence this = -this and thus 2(x1, y1) == infinity
|
||||
if (this.x.ToBigInteger().SignValue == 0)
|
||||
return this.curve.Infinity;
|
||||
|
||||
F2mFieldElement lambda = (F2mFieldElement) this.x.Add(this.y.Divide(this.x));
|
||||
F2mFieldElement x2 = (F2mFieldElement)lambda.Square().Add(lambda).Add(this.curve.A);
|
||||
ECFieldElement ONE = this.curve.FromBigInteger(BigInteger.One);
|
||||
F2mFieldElement y2 = (F2mFieldElement)this.x.Square().Add(
|
||||
x2.Multiply(lambda.Add(ONE)));
|
||||
|
||||
return new F2mPoint(this.curve, x2, y2, withCompression);
|
||||
}
|
||||
|
||||
public override ECPoint Negate()
|
||||
{
|
||||
return new F2mPoint(curve, this.x, this.x.Add(this.y), withCompression);
|
||||
}
|
||||
|
||||
// TODO Uncomment this to enable WNAF/WTNAF F2m point multiplication
|
||||
// /**
|
||||
// * Sets the appropriate <code>ECMultiplier</code>, unless already set.
|
||||
// */
|
||||
// internal override void AssertECMultiplier()
|
||||
// {
|
||||
// if (this.multiplier == null)
|
||||
// {
|
||||
// lock (this)
|
||||
// {
|
||||
// if (this.multiplier == null)
|
||||
// {
|
||||
// if (((F2mCurve) this.curve).IsKoblitz)
|
||||
// {
|
||||
// this.multiplier = new WTauNafMultiplier();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// this.multiplier = new WNafMultiplier();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user