Initial Commit

This commit is contained in:
2023-06-21 12:46:23 -04:00
commit c70248a520
1352 changed files with 336780 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
using System;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Math.EC
{
public class ECAlgorithms
{
public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a,
ECPoint Q, BigInteger b)
{
ECCurve c = P.Curve;
if (!c.Equals(Q.Curve))
throw new ArgumentException("P and Q must be on same curve");
// TODO Put back in once WTNAF F2m point multiplication is enabled
// // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
// if (c is F2mCurve)
// {
// F2mCurve f2mCurve = (F2mCurve) c;
// if (f2mCurve.IsKoblitz)
// {
// return P.Multiply(a).Add(Q.Multiply(b));
// }
// }
return ImplShamirsTrick(P, a, Q, b);
}
/*
* "Shamir's Trick", originally due to E. G. Straus
* (Addition chains of vectors. American Mathematical Monthly,
* 71(7):806<30>808, Aug./Sept. 1964)
*
* Input: The points P, Q, scalar k = (km?, ... , k1, k0)
* and scalar l = (lm?, ... , l1, l0).
* Output: R = k * P + l * Q.
* 1: Z <- P + Q
* 2: R <- O
* 3: for i from m-1 down to 0 do
* 4: R <- R + R {point doubling}
* 5: if (ki = 1) and (li = 0) then R <- R + P end if
* 6: if (ki = 0) and (li = 1) then R <- R + Q end if
* 7: if (ki = 1) and (li = 1) then R <- R + Z end if
* 8: end for
* 9: return R
*/
public static ECPoint ShamirsTrick(
ECPoint P,
BigInteger k,
ECPoint Q,
BigInteger l)
{
if (!P.Curve.Equals(Q.Curve))
throw new ArgumentException("P and Q must be on same curve");
return ImplShamirsTrick(P, k, Q, l);
}
private static ECPoint ImplShamirsTrick(ECPoint P, BigInteger k,
ECPoint Q, BigInteger l)
{
int m = System.Math.Max(k.BitLength, l.BitLength);
ECPoint Z = P.Add(Q);
ECPoint R = P.Curve.Infinity;
for (int i = m - 1; i >= 0; --i)
{
R = R.Twice();
if (k.TestBit(i))
{
if (l.TestBit(i))
{
R = R.Add(Z);
}
else
{
R = R.Add(P);
}
}
else
{
if (l.TestBit(i))
{
R = R.Add(Q);
}
}
}
return R;
}
}
}

View File

@@ -0,0 +1,661 @@
using System;
using System.Collections;
using Org.BouncyCastle.Math.EC.Abc;
namespace Org.BouncyCastle.Math.EC
{
/// <remarks>Base class for an elliptic curve.</remarks>
public abstract class ECCurve
{
internal ECFieldElement a, b;
public abstract int FieldSize { get; }
public abstract ECFieldElement FromBigInteger(BigInteger x);
public abstract ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression);
public abstract ECPoint DecodePoint(byte[] encoded);
public abstract ECPoint Infinity { get; }
public ECFieldElement A
{
get { return a; }
}
public ECFieldElement B
{
get { return b; }
}
public override bool Equals(
object obj)
{
if (obj == this)
return true;
ECCurve other = obj as ECCurve;
if (other == null)
return false;
return Equals(other);
}
protected bool Equals(
ECCurve other)
{
return a.Equals(other.a) && b.Equals(other.b);
}
public override int GetHashCode()
{
return a.GetHashCode() ^ b.GetHashCode();
}
}
public abstract class ECCurveBase : ECCurve
{
protected internal ECCurveBase()
{
}
protected internal abstract ECPoint DecompressPoint(int yTilde, BigInteger X1);
/**
* Decode a point on this curve from its ASN.1 encoding. The different
* encodings are taken account of, including point compression for
* <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
* @return The decoded point.
*/
public override ECPoint DecodePoint(
byte[] encoded)
{
ECPoint p = null;
int expectedLength = (FieldSize + 7) / 8;
switch (encoded[0])
{
case 0x00: // infinity
{
if (encoded.Length != 1)
throw new ArgumentException("Incorrect length for infinity encoding", "encoded");
p = Infinity;
break;
}
case 0x02: // compressed
case 0x03: // compressed
{
if (encoded.Length != (expectedLength + 1))
throw new ArgumentException("Incorrect length for compressed encoding", "encoded");
int yTilde = encoded[0] & 1;
BigInteger X1 = new BigInteger(1, encoded, 1, encoded.Length - 1);
p = DecompressPoint(yTilde, X1);
break;
}
case 0x04: // uncompressed
case 0x06: // hybrid
case 0x07: // hybrid
{
if (encoded.Length != (2 * expectedLength + 1))
throw new ArgumentException("Incorrect length for uncompressed/hybrid encoding", "encoded");
BigInteger X1 = new BigInteger(1, encoded, 1, expectedLength);
BigInteger Y1 = new BigInteger(1, encoded, 1 + expectedLength, expectedLength);
p = CreatePoint(X1, Y1, false);
break;
}
default:
throw new FormatException("Invalid point encoding " + encoded[0]);
}
return p;
}
}
/**
* Elliptic curve over Fp
*/
public class FpCurve : ECCurveBase
{
private readonly BigInteger q;
private readonly FpPoint infinity;
public FpCurve(BigInteger q, BigInteger a, BigInteger b)
{
this.q = q;
this.a = FromBigInteger(a);
this.b = FromBigInteger(b);
this.infinity = new FpPoint(this, null, null);
}
public BigInteger Q
{
get { return q; }
}
public override ECPoint Infinity
{
get { return infinity; }
}
public override int FieldSize
{
get { return q.BitLength; }
}
public override ECFieldElement FromBigInteger(BigInteger x)
{
return new FpFieldElement(this.q, x);
}
public override ECPoint CreatePoint(
BigInteger X1,
BigInteger Y1,
bool withCompression)
{
// TODO Validation of X1, Y1?
return new FpPoint(
this,
FromBigInteger(X1),
FromBigInteger(Y1),
withCompression);
}
protected internal override ECPoint DecompressPoint(
int yTilde,
BigInteger X1)
{
ECFieldElement x = FromBigInteger(X1);
ECFieldElement alpha = x.Multiply(x.Square().Add(a)).Add(b);
ECFieldElement beta = alpha.Sqrt();
//
// if we can't find a sqrt we haven't got a point on the
// curve - run!
//
if (beta == null)
throw new ArithmeticException("Invalid point compression");
BigInteger betaValue = beta.ToBigInteger();
int bit0 = betaValue.TestBit(0) ? 1 : 0;
if (bit0 != yTilde)
{
// Use the other root
beta = FromBigInteger(q.Subtract(betaValue));
}
return new FpPoint(this, x, beta, true);
}
public override bool Equals(
object obj)
{
if (obj == this)
return true;
FpCurve other = obj as FpCurve;
if (other == null)
return false;
return Equals(other);
}
protected bool Equals(
FpCurve other)
{
return base.Equals(other) && q.Equals(other.q);
}
public override int GetHashCode()
{
return base.GetHashCode() ^ q.GetHashCode();
}
}
/**
* Elliptic curves over F2m. The Weierstrass equation is given by
* <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
*/
public class F2mCurve : ECCurveBase
{
/**
* The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
*/
private readonly int m;
/**
* TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
* x<sup>k</sup> + 1</code> represents the reduction polynomial
* <code>f(z)</code>.<br/>
* PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.<br/>
*/
private readonly int k1;
/**
* TPB: Always set to <code>0</code><br/>
* PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.<br/>
*/
private readonly int k2;
/**
* TPB: Always set to <code>0</code><br/>
* PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.<br/>
*/
private readonly int k3;
/**
* The order of the base point of the curve.
*/
private readonly BigInteger n;
/**
* The cofactor of the curve.
*/
private readonly BigInteger h;
/**
* The point at infinity on this curve.
*/
private readonly F2mPoint infinity;
/**
* The parameter <code>&#956;</code> of the elliptic curve if this is
* a Koblitz curve.
*/
private sbyte mu = 0;
/**
* The auxiliary values <code>s<sub>0</sub></code> and
* <code>s<sub>1</sub></code> used for partial modular reduction for
* Koblitz curves.
*/
private BigInteger[] si = null;
/**
* Constructor for Trinomial Polynomial Basis (TPB).
* @param m The exponent <code>m</code> of
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param k The integer <code>k</code> where <code>x<sup>m</sup> +
* x<sup>k</sup> + 1</code> represents the reduction
* polynomial <code>f(z)</code>.
* @param a The coefficient <code>a</code> in the Weierstrass equation
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param b The coefficient <code>b</code> in the Weierstrass equation
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
*/
public F2mCurve(
int m,
int k,
BigInteger a,
BigInteger b)
: this(m, k, 0, 0, a, b, null, null)
{
}
/**
* Constructor for Trinomial Polynomial Basis (TPB).
* @param m The exponent <code>m</code> of
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param k The integer <code>k</code> where <code>x<sup>m</sup> +
* x<sup>k</sup> + 1</code> represents the reduction
* polynomial <code>f(z)</code>.
* @param a The coefficient <code>a</code> in the Weierstrass equation
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param b The coefficient <code>b</code> in the Weierstrass equation
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param n The order of the main subgroup of the elliptic curve.
* @param h The cofactor of the elliptic curve, i.e.
* <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
*/
public F2mCurve(
int m,
int k,
BigInteger a,
BigInteger b,
BigInteger n,
BigInteger h)
: this(m, k, 0, 0, a, b, n, h)
{
}
/**
* Constructor for Pentanomial Polynomial Basis (PPB).
* @param m The exponent <code>m</code> of
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.
* @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.
* @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.
* @param a The coefficient <code>a</code> in the Weierstrass equation
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param b The coefficient <code>b</code> in the Weierstrass equation
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
*/
public F2mCurve(
int m,
int k1,
int k2,
int k3,
BigInteger a,
BigInteger b)
: this(m, k1, k2, k3, a, b, null, null)
{
}
/**
* Constructor for Pentanomial Polynomial Basis (PPB).
* @param m The exponent <code>m</code> of
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.
* @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.
* @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.
* @param a The coefficient <code>a</code> in the Weierstrass equation
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param b The coefficient <code>b</code> in the Weierstrass equation
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
* @param n The order of the main subgroup of the elliptic curve.
* @param h The cofactor of the elliptic curve, i.e.
* <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
*/
public F2mCurve(
int m,
int k1,
int k2,
int k3,
BigInteger a,
BigInteger b,
BigInteger n,
BigInteger h)
{
this.m = m;
this.k1 = k1;
this.k2 = k2;
this.k3 = k3;
this.n = n;
this.h = h;
this.infinity = new F2mPoint(this, null, null);
if (k1 == 0)
throw new ArgumentException("k1 must be > 0");
if (k2 == 0)
{
if (k3 != 0)
throw new ArgumentException("k3 must be 0 if k2 == 0");
}
else
{
if (k2 <= k1)
throw new ArgumentException("k2 must be > k1");
if (k3 <= k2)
throw new ArgumentException("k3 must be > k2");
}
this.a = FromBigInteger(a);
this.b = FromBigInteger(b);
}
public override ECPoint Infinity
{
get { return infinity; }
}
public override int FieldSize
{
get { return m; }
}
public override ECFieldElement FromBigInteger(BigInteger x)
{
return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, x);
}
/**
* Returns true if this is a Koblitz curve (ABC curve).
* @return true if this is a Koblitz curve (ABC curve), false otherwise
*/
public bool IsKoblitz
{
get
{
return n != null && h != null
&& (a.ToBigInteger().Equals(BigInteger.Zero)
|| a.ToBigInteger().Equals(BigInteger.One))
&& b.ToBigInteger().Equals(BigInteger.One);
}
}
/**
* Returns the parameter <code>&#956;</code> of the elliptic curve.
* @return <code>&#956;</code> of the elliptic curve.
* @throws ArgumentException if the given ECCurve is not a
* Koblitz curve.
*/
internal sbyte GetMu()
{
if (mu == 0)
{
lock (this)
{
if (mu == 0)
{
mu = Tnaf.GetMu(this);
}
}
}
return mu;
}
/**
* @return the auxiliary values <code>s<sub>0</sub></code> and
* <code>s<sub>1</sub></code> used for partial modular reduction for
* Koblitz curves.
*/
internal BigInteger[] GetSi()
{
if (si == null)
{
lock (this)
{
if (si == null)
{
si = Tnaf.GetSi(this);
}
}
}
return si;
}
public override ECPoint CreatePoint(
BigInteger X1,
BigInteger Y1,
bool withCompression)
{
// TODO Validation of X1, Y1?
return new F2mPoint(
this,
FromBigInteger(X1),
FromBigInteger(Y1),
withCompression);
}
protected internal override ECPoint DecompressPoint(
int yTilde,
BigInteger X1)
{
ECFieldElement xp = FromBigInteger(X1);
ECFieldElement yp = null;
if (xp.ToBigInteger().SignValue == 0)
{
yp = (F2mFieldElement)b;
for (int i = 0; i < m - 1; i++)
{
yp = yp.Square();
}
}
else
{
ECFieldElement beta = xp.Add(a).Add(
b.Multiply(xp.Square().Invert()));
ECFieldElement z = solveQuadradicEquation(beta);
if (z == null)
throw new ArithmeticException("Invalid point compression");
int zBit = z.ToBigInteger().TestBit(0) ? 1 : 0;
if (zBit != yTilde)
{
z = z.Add(FromBigInteger(BigInteger.One));
}
yp = xp.Multiply(z);
}
return new F2mPoint(this, xp, yp, true);
}
/**
* Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
* D.1.6) The other solution is <code>z + 1</code>.
*
* @param beta
* The value to solve the qradratic equation for.
* @return the solution for <code>z<sup>2</sup> + z = beta</code> or
* <code>null</code> if no solution exists.
*/
private ECFieldElement solveQuadradicEquation(ECFieldElement beta)
{
if (beta.ToBigInteger().SignValue == 0)
{
return FromBigInteger(BigInteger.Zero);
}
ECFieldElement z = null;
ECFieldElement gamma = FromBigInteger(BigInteger.Zero);
while (gamma.ToBigInteger().SignValue == 0)
{
ECFieldElement t = FromBigInteger(new BigInteger(m, new Random()));
z = FromBigInteger(BigInteger.Zero);
ECFieldElement w = beta;
for (int i = 1; i <= m - 1; i++)
{
ECFieldElement w2 = w.Square();
z = z.Square().Add(w2.Multiply(t));
w = w2.Add(beta);
}
if (w.ToBigInteger().SignValue != 0)
{
return null;
}
gamma = z.Square().Add(z);
}
return z;
}
public override bool Equals(
object obj)
{
if (obj == this)
return true;
F2mCurve other = obj as F2mCurve;
if (other == null)
return false;
return Equals(other);
}
protected bool Equals(
F2mCurve other)
{
return m == other.m
&& k1 == other.k1
&& k2 == other.k2
&& k3 == other.k3
&& base.Equals(other);
}
public override int GetHashCode()
{
return base.GetHashCode() ^ m ^ k1 ^ k2 ^ k3;
}
public int M
{
get { return m; }
}
/**
* Return true if curve uses a Trinomial basis.
*
* @return true if curve Trinomial, false otherwise.
*/
public bool IsTrinomial()
{
return k2 == 0 && k3 == 0;
}
public int K1
{
get { return k1; }
}
public int K2
{
get { return k2; }
}
public int K3
{
get { return k3; }
}
public BigInteger N
{
get { return n; }
}
public BigInteger H
{
get { return h; }
}
}
}

File diff suppressed because it is too large Load Diff

View 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();
// }
// }
// }
// }
// }
}
}

View File

@@ -0,0 +1,486 @@
using System;
using System.Text;
namespace Org.BouncyCastle.Math.EC
{
internal class IntArray
: ICloneable
{
// TODO make m fixed for the IntArray, and hence compute T once and for all
// TODO Use uint's internally?
private int[] m_ints;
public IntArray(int intLen)
{
m_ints = new int[intLen];
}
private IntArray(int[] ints)
{
m_ints = ints;
}
public IntArray(BigInteger bigInt)
: this(bigInt, 0)
{
}
public IntArray(BigInteger bigInt, int minIntLen)
{
if (bigInt.SignValue == -1)
throw new ArgumentException("Only positive Integers allowed", "bigint");
if (bigInt.SignValue == 0)
{
m_ints = new int[] { 0 };
return;
}
byte[] barr = bigInt.ToByteArrayUnsigned();
int barrLen = barr.Length;
int intLen = (barrLen + 3) / 4;
m_ints = new int[System.Math.Max(intLen, minIntLen)];
int rem = barrLen % 4;
int barrI = 0;
if (0 < rem)
{
int temp = (int) barr[barrI++];
while (barrI < rem)
{
temp = temp << 8 | (int) barr[barrI++];
}
m_ints[--intLen] = temp;
}
while (intLen > 0)
{
int temp = (int) barr[barrI++];
for (int i = 1; i < 4; i++)
{
temp = temp << 8 | (int) barr[barrI++];
}
m_ints[--intLen] = temp;
}
}
public int GetUsedLength()
{
int highestIntPos = m_ints.Length;
if (highestIntPos < 1)
return 0;
// Check if first element will act as sentinel
if (m_ints[0] != 0)
{
while (m_ints[--highestIntPos] == 0)
{
}
return highestIntPos + 1;
}
do
{
if (m_ints[--highestIntPos] != 0)
{
return highestIntPos + 1;
}
}
while (highestIntPos > 0);
return 0;
}
public int BitLength
{
get
{
// JDK 1.5: see Integer.numberOfLeadingZeros()
int intLen = GetUsedLength();
if (intLen == 0)
return 0;
int last = intLen - 1;
uint highest = (uint) m_ints[last];
int bits = (last << 5) + 1;
// A couple of binary search steps
if (highest > 0x0000ffff)
{
if (highest > 0x00ffffff)
{
bits += 24;
highest >>= 24;
}
else
{
bits += 16;
highest >>= 16;
}
}
else if (highest > 0x000000ff)
{
bits += 8;
highest >>= 8;
}
while (highest > 1)
{
++bits;
highest >>= 1;
}
return bits;
}
}
private int[] resizedInts(int newLen)
{
int[] newInts = new int[newLen];
int oldLen = m_ints.Length;
int copyLen = oldLen < newLen ? oldLen : newLen;
Array.Copy(m_ints, 0, newInts, 0, copyLen);
return newInts;
}
public BigInteger ToBigInteger()
{
int usedLen = GetUsedLength();
if (usedLen == 0)
{
return BigInteger.Zero;
}
int highestInt = m_ints[usedLen - 1];
byte[] temp = new byte[4];
int barrI = 0;
bool trailingZeroBytesDone = false;
for (int j = 3; j >= 0; j--)
{
byte thisByte = (byte)((int)((uint) highestInt >> (8 * j)));
if (trailingZeroBytesDone || (thisByte != 0))
{
trailingZeroBytesDone = true;
temp[barrI++] = thisByte;
}
}
int barrLen = 4 * (usedLen - 1) + barrI;
byte[] barr = new byte[barrLen];
for (int j = 0; j < barrI; j++)
{
barr[j] = temp[j];
}
// Highest value int is done now
for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
{
for (int j = 3; j >= 0; j--)
{
barr[barrI++] = (byte)((int)((uint)m_ints[iarrJ] >> (8 * j)));
}
}
return new BigInteger(1, barr);
}
public void ShiftLeft()
{
int usedLen = GetUsedLength();
if (usedLen == 0)
{
return;
}
if (m_ints[usedLen - 1] < 0)
{
// highest bit of highest used byte is set, so shifting left will
// make the IntArray one byte longer
usedLen++;
if (usedLen > m_ints.Length)
{
// make the m_ints one byte longer, because we need one more
// byte which is not available in m_ints
m_ints = resizedInts(m_ints.Length + 1);
}
}
bool carry = false;
for (int i = 0; i < usedLen; i++)
{
// nextCarry is true if highest bit is set
bool nextCarry = m_ints[i] < 0;
m_ints[i] <<= 1;
if (carry)
{
// set lowest bit
m_ints[i] |= 1;
}
carry = nextCarry;
}
}
public IntArray ShiftLeft(int n)
{
int usedLen = GetUsedLength();
if (usedLen == 0)
{
return this;
}
if (n == 0)
{
return this;
}
if (n > 31)
{
throw new ArgumentException("shiftLeft() for max 31 bits "
+ ", " + n + "bit shift is not possible", "n");
}
int[] newInts = new int[usedLen + 1];
int nm32 = 32 - n;
newInts[0] = m_ints[0] << n;
for (int i = 1; i < usedLen; i++)
{
newInts[i] = (m_ints[i] << n) | (int)((uint)m_ints[i - 1] >> nm32);
}
newInts[usedLen] = (int)((uint)m_ints[usedLen - 1] >> nm32);
return new IntArray(newInts);
}
public void AddShifted(IntArray other, int shift)
{
int usedLenOther = other.GetUsedLength();
int newMinUsedLen = usedLenOther + shift;
if (newMinUsedLen > m_ints.Length)
{
m_ints = resizedInts(newMinUsedLen);
//Console.WriteLine("Resize required");
}
for (int i = 0; i < usedLenOther; i++)
{
m_ints[i + shift] ^= other.m_ints[i];
}
}
public int Length
{
get { return m_ints.Length; }
}
public bool TestBit(int n)
{
// theInt = n / 32
int theInt = n >> 5;
// theBit = n % 32
int theBit = n & 0x1F;
int tester = 1 << theBit;
return ((m_ints[theInt] & tester) != 0);
}
public void FlipBit(int n)
{
// theInt = n / 32
int theInt = n >> 5;
// theBit = n % 32
int theBit = n & 0x1F;
int flipper = 1 << theBit;
m_ints[theInt] ^= flipper;
}
public void SetBit(int n)
{
// theInt = n / 32
int theInt = n >> 5;
// theBit = n % 32
int theBit = n & 0x1F;
int setter = 1 << theBit;
m_ints[theInt] |= setter;
}
public IntArray Multiply(IntArray other, int m)
{
// Lenght of c is 2m bits rounded up to the next int (32 bit)
int t = (m + 31) >> 5;
if (m_ints.Length < t)
{
m_ints = resizedInts(t);
}
IntArray b = new IntArray(other.resizedInts(other.Length + 1));
IntArray c = new IntArray((m + m + 31) >> 5);
// IntArray c = new IntArray(t + t);
int testBit = 1;
for (int k = 0; k < 32; k++)
{
for (int j = 0; j < t; j++)
{
if ((m_ints[j] & testBit) != 0)
{
// The kth bit of m_ints[j] is set
c.AddShifted(b, j);
}
}
testBit <<= 1;
b.ShiftLeft();
}
return c;
}
// public IntArray multiplyLeftToRight(IntArray other, int m) {
// // Lenght of c is 2m bits rounded up to the next int (32 bit)
// int t = (m + 31) / 32;
// if (m_ints.Length < t) {
// m_ints = resizedInts(t);
// }
//
// IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
// IntArray c = new IntArray((m + m + 31) / 32);
// // IntArray c = new IntArray(t + t);
// int testBit = 1 << 31;
// for (int k = 31; k >= 0; k--) {
// for (int j = 0; j < t; j++) {
// if ((m_ints[j] & testBit) != 0) {
// // The kth bit of m_ints[j] is set
// c.addShifted(b, j);
// }
// }
// testBit >>>= 1;
// if (k > 0) {
// c.shiftLeft();
// }
// }
// return c;
// }
// TODO note, redPol.Length must be 3 for TPB and 5 for PPB
public void Reduce(int m, int[] redPol)
{
for (int i = m + m - 2; i >= m; i--)
{
if (TestBit(i))
{
int bit = i - m;
FlipBit(bit);
FlipBit(i);
int l = redPol.Length;
while (--l >= 0)
{
FlipBit(redPol[l] + bit);
}
}
}
m_ints = resizedInts((m + 31) >> 5);
}
public IntArray Square(int m)
{
// TODO make the table static readonly
int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40,
0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 };
int t = (m + 31) >> 5;
if (m_ints.Length < t)
{
m_ints = resizedInts(t);
}
IntArray c = new IntArray(t + t);
// TODO twice the same code, put in separate private method
for (int i = 0; i < t; i++)
{
int v0 = 0;
for (int j = 0; j < 4; j++)
{
v0 = (int)((uint) v0 >> 8);
int u = (int)((uint)m_ints[i] >> (j * 4)) & 0xF;
int w = table[u] << 24;
v0 |= w;
}
c.m_ints[i + i] = v0;
v0 = 0;
int upper = (int)((uint) m_ints[i] >> 16);
for (int j = 0; j < 4; j++)
{
v0 = (int)((uint) v0 >> 8);
int u = (int)((uint)upper >> (j * 4)) & 0xF;
int w = table[u] << 24;
v0 |= w;
}
c.m_ints[i + i + 1] = v0;
}
return c;
}
public override bool Equals(object o)
{
if (!(o is IntArray))
{
return false;
}
IntArray other = (IntArray) o;
int usedLen = GetUsedLength();
if (other.GetUsedLength() != usedLen)
{
return false;
}
for (int i = 0; i < usedLen; i++)
{
if (m_ints[i] != other.m_ints[i])
{
return false;
}
}
return true;
}
public override int GetHashCode()
{
int i = GetUsedLength();
int hc = i;
while (--i >= 0)
{
hc *= 17;
hc ^= m_ints[i];
}
return hc;
}
public object Clone()
{
return new IntArray((int[]) m_ints.Clone());
}
public override string ToString()
{
int usedLen = GetUsedLength();
if (usedLen == 0)
{
return "0";
}
StringBuilder sb = new StringBuilder(Convert.ToString(m_ints[usedLen - 1], 2));
for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
{
string hexString = Convert.ToString(m_ints[iarrJ], 2);
// Add leading zeroes, except for highest significant int
for (int i = hexString.Length; i < 8; i++)
{
hexString = "0" + hexString;
}
sb.Append(hexString);
}
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,241 @@
using System;
using System.Text;
namespace Org.BouncyCastle.Math.EC.Abc
{
/**
* Class representing a simple version of a big decimal. A
* <code>SimpleBigDecimal</code> is basically a
* {@link java.math.BigInteger BigInteger} with a few digits on the right of
* the decimal point. The number of (binary) digits on the right of the decimal
* point is called the <code>scale</code> of the <code>SimpleBigDecimal</code>.
* Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted
* automatically, but must be set manually. All <code>SimpleBigDecimal</code>s
* taking part in the same arithmetic operation must have equal scale. The
* result of a multiplication of two <code>SimpleBigDecimal</code>s returns a
* <code>SimpleBigDecimal</code> with double scale.
*/
internal class SimpleBigDecimal
// : Number
{
// private static final long serialVersionUID = 1L;
private readonly BigInteger bigInt;
private readonly int scale;
/**
* Returns a <code>SimpleBigDecimal</code> representing the same numerical
* value as <code>value</code>.
* @param value The value of the <code>SimpleBigDecimal</code> to be
* created.
* @param scale The scale of the <code>SimpleBigDecimal</code> to be
* created.
* @return The such created <code>SimpleBigDecimal</code>.
*/
public static SimpleBigDecimal GetInstance(BigInteger val, int scale)
{
return new SimpleBigDecimal(val.ShiftLeft(scale), scale);
}
/**
* Constructor for <code>SimpleBigDecimal</code>. The value of the
* constructed <code>SimpleBigDecimal</code> Equals <code>bigInt /
* 2<sup>scale</sup></code>.
* @param bigInt The <code>bigInt</code> value parameter.
* @param scale The scale of the constructed <code>SimpleBigDecimal</code>.
*/
public SimpleBigDecimal(BigInteger bigInt, int scale)
{
if (scale < 0)
throw new ArgumentException("scale may not be negative");
this.bigInt = bigInt;
this.scale = scale;
}
private SimpleBigDecimal(SimpleBigDecimal limBigDec)
{
bigInt = limBigDec.bigInt;
scale = limBigDec.scale;
}
private void CheckScale(SimpleBigDecimal b)
{
if (scale != b.scale)
throw new ArgumentException("Only SimpleBigDecimal of same scale allowed in arithmetic operations");
}
public SimpleBigDecimal AdjustScale(int newScale)
{
if (newScale < 0)
throw new ArgumentException("scale may not be negative");
if (newScale == scale)
return this;
return new SimpleBigDecimal(bigInt.ShiftLeft(newScale - scale), newScale);
}
public SimpleBigDecimal Add(SimpleBigDecimal b)
{
CheckScale(b);
return new SimpleBigDecimal(bigInt.Add(b.bigInt), scale);
}
public SimpleBigDecimal Add(BigInteger b)
{
return new SimpleBigDecimal(bigInt.Add(b.ShiftLeft(scale)), scale);
}
public SimpleBigDecimal Negate()
{
return new SimpleBigDecimal(bigInt.Negate(), scale);
}
public SimpleBigDecimal Subtract(SimpleBigDecimal b)
{
return Add(b.Negate());
}
public SimpleBigDecimal Subtract(BigInteger b)
{
return new SimpleBigDecimal(bigInt.Subtract(b.ShiftLeft(scale)), scale);
}
public SimpleBigDecimal Multiply(SimpleBigDecimal b)
{
CheckScale(b);
return new SimpleBigDecimal(bigInt.Multiply(b.bigInt), scale + scale);
}
public SimpleBigDecimal Multiply(BigInteger b)
{
return new SimpleBigDecimal(bigInt.Multiply(b), scale);
}
public SimpleBigDecimal Divide(SimpleBigDecimal b)
{
CheckScale(b);
BigInteger dividend = bigInt.ShiftLeft(scale);
return new SimpleBigDecimal(dividend.Divide(b.bigInt), scale);
}
public SimpleBigDecimal Divide(BigInteger b)
{
return new SimpleBigDecimal(bigInt.Divide(b), scale);
}
public SimpleBigDecimal ShiftLeft(int n)
{
return new SimpleBigDecimal(bigInt.ShiftLeft(n), scale);
}
public int CompareTo(SimpleBigDecimal val)
{
CheckScale(val);
return bigInt.CompareTo(val.bigInt);
}
public int CompareTo(BigInteger val)
{
return bigInt.CompareTo(val.ShiftLeft(scale));
}
public BigInteger Floor()
{
return bigInt.ShiftRight(scale);
}
public BigInteger Round()
{
SimpleBigDecimal oneHalf = new SimpleBigDecimal(BigInteger.One, 1);
return Add(oneHalf.AdjustScale(scale)).Floor();
}
public int IntValue
{
get { return Floor().IntValue; }
}
public long LongValue
{
get { return Floor().LongValue; }
}
// public double doubleValue()
// {
// return new Double(ToString()).doubleValue();
// }
//
// public float floatValue()
// {
// return new Float(ToString()).floatValue();
// }
public int Scale
{
get { return scale; }
}
public override string ToString()
{
if (scale == 0)
return bigInt.ToString();
BigInteger floorBigInt = Floor();
BigInteger fract = bigInt.Subtract(floorBigInt.ShiftLeft(scale));
if (bigInt.SignValue < 0)
{
fract = BigInteger.One.ShiftLeft(scale).Subtract(fract);
}
if ((floorBigInt.SignValue == -1) && (!(fract.Equals(BigInteger.Zero))))
{
floorBigInt = floorBigInt.Add(BigInteger.One);
}
string leftOfPoint = floorBigInt.ToString();
char[] fractCharArr = new char[scale];
string fractStr = fract.ToString(2);
int fractLen = fractStr.Length;
int zeroes = scale - fractLen;
for (int i = 0; i < zeroes; i++)
{
fractCharArr[i] = '0';
}
for (int j = 0; j < fractLen; j++)
{
fractCharArr[zeroes + j] = fractStr[j];
}
string rightOfPoint = new string(fractCharArr);
StringBuilder sb = new StringBuilder(leftOfPoint);
sb.Append(".");
sb.Append(rightOfPoint);
return sb.ToString();
}
public override bool Equals(
object obj)
{
if (this == obj)
return true;
SimpleBigDecimal other = obj as SimpleBigDecimal;
if (other == null)
return false;
return bigInt.Equals(other.bigInt)
&& scale == other.scale;
}
public override int GetHashCode()
{
return bigInt.GetHashCode() ^ scale;
}
}
}

View File

@@ -0,0 +1,834 @@
using System;
namespace Org.BouncyCastle.Math.EC.Abc
{
/**
* Class holding methods for point multiplication based on the window
* &#964;-adic nonadjacent form (WTNAF). The algorithms are based on the
* paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
* by Jerome A. Solinas. The paper first appeared in the Proceedings of
* Crypto 1997.
*/
internal class Tnaf
{
private static readonly BigInteger MinusOne = BigInteger.One.Negate();
private static readonly BigInteger MinusTwo = BigInteger.Two.Negate();
private static readonly BigInteger MinusThree = BigInteger.Three.Negate();
private static readonly BigInteger Four = BigInteger.ValueOf(4);
/**
* The window width of WTNAF. The standard value of 4 is slightly less
* than optimal for running time, but keeps space requirements for
* precomputation low. For typical curves, a value of 5 or 6 results in
* a better running time. When changing this value, the
* <code>&#945;<sub>u</sub></code>'s must be computed differently, see
* e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
* Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
* p. 121-122
*/
public const sbyte Width = 4;
/**
* 2<sup>4</sup>
*/
public const sbyte Pow2Width = 16;
/**
* The <code>&#945;<sub>u</sub></code>'s for <code>a=0</code> as an array
* of <code>ZTauElement</code>s.
*/
public static readonly ZTauElement[] Alpha0 =
{
null,
new ZTauElement(BigInteger.One, BigInteger.Zero), null,
new ZTauElement(MinusThree, MinusOne), null,
new ZTauElement(MinusOne, MinusOne), null,
new ZTauElement(BigInteger.One, MinusOne), null
};
/**
* The <code>&#945;<sub>u</sub></code>'s for <code>a=0</code> as an array
* of TNAFs.
*/
public static readonly sbyte[][] Alpha0Tnaf =
{
null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, 1}
};
/**
* The <code>&#945;<sub>u</sub></code>'s for <code>a=1</code> as an array
* of <code>ZTauElement</code>s.
*/
public static readonly ZTauElement[] Alpha1 =
{
null,
new ZTauElement(BigInteger.One, BigInteger.Zero), null,
new ZTauElement(MinusThree, BigInteger.One), null,
new ZTauElement(MinusOne, BigInteger.One), null,
new ZTauElement(BigInteger.One, BigInteger.One), null
};
/**
* The <code>&#945;<sub>u</sub></code>'s for <code>a=1</code> as an array
* of TNAFs.
*/
public static readonly sbyte[][] Alpha1Tnaf =
{
null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, -1}
};
/**
* Computes the norm of an element <code>&#955;</code> of
* <code><b>Z</b>[&#964;]</code>.
* @param mu The parameter <code>&#956;</code> of the elliptic curve.
* @param lambda The element <code>&#955;</code> of
* <code><b>Z</b>[&#964;]</code>.
* @return The norm of <code>&#955;</code>.
*/
public static BigInteger Norm(sbyte mu, ZTauElement lambda)
{
BigInteger norm;
// s1 = u^2
BigInteger s1 = lambda.u.Multiply(lambda.u);
// s2 = u * v
BigInteger s2 = lambda.u.Multiply(lambda.v);
// s3 = 2 * v^2
BigInteger s3 = lambda.v.Multiply(lambda.v).ShiftLeft(1);
if (mu == 1)
{
norm = s1.Add(s2).Add(s3);
}
else if (mu == -1)
{
norm = s1.Subtract(s2).Add(s3);
}
else
{
throw new ArgumentException("mu must be 1 or -1");
}
return norm;
}
/**
* Computes the norm of an element <code>&#955;</code> of
* <code><b>R</b>[&#964;]</code>, where <code>&#955; = u + v&#964;</code>
* and <code>u</code> and <code>u</code> are real numbers (elements of
* <code><b>R</b></code>).
* @param mu The parameter <code>&#956;</code> of the elliptic curve.
* @param u The real part of the element <code>&#955;</code> of
* <code><b>R</b>[&#964;]</code>.
* @param v The <code>&#964;</code>-adic part of the element
* <code>&#955;</code> of <code><b>R</b>[&#964;]</code>.
* @return The norm of <code>&#955;</code>.
*/
public static SimpleBigDecimal Norm(sbyte mu, SimpleBigDecimal u, SimpleBigDecimal v)
{
SimpleBigDecimal norm;
// s1 = u^2
SimpleBigDecimal s1 = u.Multiply(u);
// s2 = u * v
SimpleBigDecimal s2 = u.Multiply(v);
// s3 = 2 * v^2
SimpleBigDecimal s3 = v.Multiply(v).ShiftLeft(1);
if (mu == 1)
{
norm = s1.Add(s2).Add(s3);
}
else if (mu == -1)
{
norm = s1.Subtract(s2).Add(s3);
}
else
{
throw new ArgumentException("mu must be 1 or -1");
}
return norm;
}
/**
* Rounds an element <code>&#955;</code> of <code><b>R</b>[&#964;]</code>
* to an element of <code><b>Z</b>[&#964;]</code>, such that their difference
* has minimal norm. <code>&#955;</code> is given as
* <code>&#955; = &#955;<sub>0</sub> + &#955;<sub>1</sub>&#964;</code>.
* @param lambda0 The component <code>&#955;<sub>0</sub></code>.
* @param lambda1 The component <code>&#955;<sub>1</sub></code>.
* @param mu The parameter <code>&#956;</code> of the elliptic curve. Must
* equal 1 or -1.
* @return The rounded element of <code><b>Z</b>[&#964;]</code>.
* @throws ArgumentException if <code>lambda0</code> and
* <code>lambda1</code> do not have same scale.
*/
public static ZTauElement Round(SimpleBigDecimal lambda0,
SimpleBigDecimal lambda1, sbyte mu)
{
int scale = lambda0.Scale;
if (lambda1.Scale != scale)
throw new ArgumentException("lambda0 and lambda1 do not have same scale");
if (!((mu == 1) || (mu == -1)))
throw new ArgumentException("mu must be 1 or -1");
BigInteger f0 = lambda0.Round();
BigInteger f1 = lambda1.Round();
SimpleBigDecimal eta0 = lambda0.Subtract(f0);
SimpleBigDecimal eta1 = lambda1.Subtract(f1);
// eta = 2*eta0 + mu*eta1
SimpleBigDecimal eta = eta0.Add(eta0);
if (mu == 1)
{
eta = eta.Add(eta1);
}
else
{
// mu == -1
eta = eta.Subtract(eta1);
}
// check1 = eta0 - 3*mu*eta1
// check2 = eta0 + 4*mu*eta1
SimpleBigDecimal threeEta1 = eta1.Add(eta1).Add(eta1);
SimpleBigDecimal fourEta1 = threeEta1.Add(eta1);
SimpleBigDecimal check1;
SimpleBigDecimal check2;
if (mu == 1)
{
check1 = eta0.Subtract(threeEta1);
check2 = eta0.Add(fourEta1);
}
else
{
// mu == -1
check1 = eta0.Add(threeEta1);
check2 = eta0.Subtract(fourEta1);
}
sbyte h0 = 0;
sbyte h1 = 0;
// if eta >= 1
if (eta.CompareTo(BigInteger.One) >= 0)
{
if (check1.CompareTo(MinusOne) < 0)
{
h1 = mu;
}
else
{
h0 = 1;
}
}
else
{
// eta < 1
if (check2.CompareTo(BigInteger.Two) >= 0)
{
h1 = mu;
}
}
// if eta < -1
if (eta.CompareTo(MinusOne) < 0)
{
if (check1.CompareTo(BigInteger.One) >= 0)
{
h1 = (sbyte)-mu;
}
else
{
h0 = -1;
}
}
else
{
// eta >= -1
if (check2.CompareTo(MinusTwo) < 0)
{
h1 = (sbyte)-mu;
}
}
BigInteger q0 = f0.Add(BigInteger.ValueOf(h0));
BigInteger q1 = f1.Add(BigInteger.ValueOf(h1));
return new ZTauElement(q0, q1);
}
/**
* Approximate division by <code>n</code>. For an integer
* <code>k</code>, the value <code>&#955; = s k / n</code> is
* computed to <code>c</code> bits of accuracy.
* @param k The parameter <code>k</code>.
* @param s The curve parameter <code>s<sub>0</sub></code> or
* <code>s<sub>1</sub></code>.
* @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
* @param a The parameter <code>a</code> of the elliptic curve.
* @param m The bit length of the finite field
* <code><b>F</b><sub>m</sub></code>.
* @param c The number of bits of accuracy, i.e. the scale of the returned
* <code>SimpleBigDecimal</code>.
* @return The value <code>&#955; = s k / n</code> computed to
* <code>c</code> bits of accuracy.
*/
public static SimpleBigDecimal ApproximateDivisionByN(BigInteger k,
BigInteger s, BigInteger vm, sbyte a, int m, int c)
{
int _k = (m + 5)/2 + c;
BigInteger ns = k.ShiftRight(m - _k - 2 + a);
BigInteger gs = s.Multiply(ns);
BigInteger hs = gs.ShiftRight(m);
BigInteger js = vm.Multiply(hs);
BigInteger gsPlusJs = gs.Add(js);
BigInteger ls = gsPlusJs.ShiftRight(_k-c);
if (gsPlusJs.TestBit(_k-c-1))
{
// round up
ls = ls.Add(BigInteger.One);
}
return new SimpleBigDecimal(ls, c);
}
/**
* Computes the <code>&#964;</code>-adic NAF (non-adjacent form) of an
* element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>.
* @param mu The parameter <code>&#956;</code> of the elliptic curve.
* @param lambda The element <code>&#955;</code> of
* <code><b>Z</b>[&#964;]</code>.
* @return The <code>&#964;</code>-adic NAF of <code>&#955;</code>.
*/
public static sbyte[] TauAdicNaf(sbyte mu, ZTauElement lambda)
{
if (!((mu == 1) || (mu == -1)))
throw new ArgumentException("mu must be 1 or -1");
BigInteger norm = Norm(mu, lambda);
// Ceiling of log2 of the norm
int log2Norm = norm.BitLength;
// If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;
// The array holding the TNAF
sbyte[] u = new sbyte[maxLength];
int i = 0;
// The actual length of the TNAF
int length = 0;
BigInteger r0 = lambda.u;
BigInteger r1 = lambda.v;
while(!((r0.Equals(BigInteger.Zero)) && (r1.Equals(BigInteger.Zero))))
{
// If r0 is odd
if (r0.TestBit(0))
{
u[i] = (sbyte) BigInteger.Two.Subtract((r0.Subtract(r1.ShiftLeft(1))).Mod(Four)).IntValue;
// r0 = r0 - u[i]
if (u[i] == 1)
{
r0 = r0.ClearBit(0);
}
else
{
// u[i] == -1
r0 = r0.Add(BigInteger.One);
}
length = i;
}
else
{
u[i] = 0;
}
BigInteger t = r0;
BigInteger s = r0.ShiftRight(1);
if (mu == 1)
{
r0 = r1.Add(s);
}
else
{
// mu == -1
r0 = r1.Subtract(s);
}
r1 = t.ShiftRight(1).Negate();
i++;
}
length++;
// Reduce the TNAF array to its actual length
sbyte[] tnaf = new sbyte[length];
Array.Copy(u, 0, tnaf, 0, length);
return tnaf;
}
/**
* Applies the operation <code>&#964;()</code> to an
* <code>F2mPoint</code>.
* @param p The F2mPoint to which <code>&#964;()</code> is applied.
* @return <code>&#964;(p)</code>
*/
public static F2mPoint Tau(F2mPoint p)
{
if (p.IsInfinity)
return p;
ECFieldElement x = p.X;
ECFieldElement y = p.Y;
return new F2mPoint(p.Curve, x.Square(), y.Square(), p.IsCompressed);
}
/**
* Returns the parameter <code>&#956;</code> of the elliptic curve.
* @param curve The elliptic curve from which to obtain <code>&#956;</code>.
* The curve must be a Koblitz curve, i.e. <code>a</code> Equals
* <code>0</code> or <code>1</code> and <code>b</code> Equals
* <code>1</code>.
* @return <code>&#956;</code> of the elliptic curve.
* @throws ArgumentException if the given ECCurve is not a Koblitz
* curve.
*/
public static sbyte GetMu(F2mCurve curve)
{
BigInteger a = curve.A.ToBigInteger();
sbyte mu;
if (a.SignValue == 0)
{
mu = -1;
}
else if (a.Equals(BigInteger.One))
{
mu = 1;
}
else
{
throw new ArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible");
}
return mu;
}
/**
* Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
* <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
* <code>V<sub>k</sub></code>.
* @param mu The parameter <code>&#956;</code> of the elliptic curve.
* @param k The index of the second element of the Lucas Sequence to be
* returned.
* @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
* <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
* <code>U<sub>k</sub></code>.
* @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
* and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
* and <code>V<sub>k</sub></code>.
*/
public static BigInteger[] GetLucas(sbyte mu, int k, bool doV)
{
if (!(mu == 1 || mu == -1))
throw new ArgumentException("mu must be 1 or -1");
BigInteger u0;
BigInteger u1;
BigInteger u2;
if (doV)
{
u0 = BigInteger.Two;
u1 = BigInteger.ValueOf(mu);
}
else
{
u0 = BigInteger.Zero;
u1 = BigInteger.One;
}
for (int i = 1; i < k; i++)
{
// u2 = mu*u1 - 2*u0;
BigInteger s = null;
if (mu == 1)
{
s = u1;
}
else
{
// mu == -1
s = u1.Negate();
}
u2 = s.Subtract(u0.ShiftLeft(1));
u0 = u1;
u1 = u2;
// System.out.println(i + ": " + u2);
// System.out.println();
}
BigInteger[] retVal = {u0, u1};
return retVal;
}
/**
* Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
* 4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
* <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code>
* @param mu The parameter <code>&#956;</code> of the elliptic curve.
* @param w The window width of the WTNAF.
* @return the auxiliary value <code>t<sub>w</sub></code>
*/
public static BigInteger GetTw(sbyte mu, int w)
{
if (w == 4)
{
if (mu == 1)
{
return BigInteger.ValueOf(6);
}
else
{
// mu == -1
return BigInteger.ValueOf(10);
}
}
else
{
// For w <> 4, the values must be computed
BigInteger[] us = GetLucas(mu, w, false);
BigInteger twoToW = BigInteger.Zero.SetBit(w);
BigInteger u1invert = us[1].ModInverse(twoToW);
BigInteger tw;
tw = BigInteger.Two.Multiply(us[0]).Multiply(u1invert).Mod(twoToW);
//System.out.println("mu = " + mu);
//System.out.println("tw = " + tw);
return tw;
}
}
/**
* Computes the auxiliary values <code>s<sub>0</sub></code> and
* <code>s<sub>1</sub></code> used for partial modular reduction.
* @param curve The elliptic curve for which to compute
* <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
* @throws ArgumentException if <code>curve</code> is not a
* Koblitz curve (Anomalous Binary Curve, ABC).
*/
public static BigInteger[] GetSi(F2mCurve curve)
{
if (!curve.IsKoblitz)
throw new ArgumentException("si is defined for Koblitz curves only");
int m = curve.M;
int a = curve.A.ToBigInteger().IntValue;
sbyte mu = curve.GetMu();
int h = curve.H.IntValue;
int index = m + 3 - a;
BigInteger[] ui = GetLucas(mu, index, false);
BigInteger dividend0;
BigInteger dividend1;
if (mu == 1)
{
dividend0 = BigInteger.One.Subtract(ui[1]);
dividend1 = BigInteger.One.Subtract(ui[0]);
}
else if (mu == -1)
{
dividend0 = BigInteger.One.Add(ui[1]);
dividend1 = BigInteger.One.Add(ui[0]);
}
else
{
throw new ArgumentException("mu must be 1 or -1");
}
BigInteger[] si = new BigInteger[2];
if (h == 2)
{
si[0] = dividend0.ShiftRight(1);
si[1] = dividend1.ShiftRight(1).Negate();
}
else if (h == 4)
{
si[0] = dividend0.ShiftRight(2);
si[1] = dividend1.ShiftRight(2).Negate();
}
else
{
throw new ArgumentException("h (Cofactor) must be 2 or 4");
}
return si;
}
/**
* Partial modular reduction modulo
* <code>(&#964;<sup>m</sup> - 1)/(&#964; - 1)</code>.
* @param k The integer to be reduced.
* @param m The bitlength of the underlying finite field.
* @param a The parameter <code>a</code> of the elliptic curve.
* @param s The auxiliary values <code>s<sub>0</sub></code> and
* <code>s<sub>1</sub></code>.
* @param mu The parameter &#956; of the elliptic curve.
* @param c The precision (number of bits of accuracy) of the partial
* modular reduction.
* @return <code>&#961; := k partmod (&#964;<sup>m</sup> - 1)/(&#964; - 1)</code>
*/
public static ZTauElement PartModReduction(BigInteger k, int m, sbyte a,
BigInteger[] s, sbyte mu, sbyte c)
{
// d0 = s[0] + mu*s[1]; mu is either 1 or -1
BigInteger d0;
if (mu == 1)
{
d0 = s[0].Add(s[1]);
}
else
{
d0 = s[0].Subtract(s[1]);
}
BigInteger[] v = GetLucas(mu, m, true);
BigInteger vm = v[1];
SimpleBigDecimal lambda0 = ApproximateDivisionByN(
k, s[0], vm, a, m, c);
SimpleBigDecimal lambda1 = ApproximateDivisionByN(
k, s[1], vm, a, m, c);
ZTauElement q = Round(lambda0, lambda1, mu);
// r0 = n - d0*q0 - 2*s1*q1
BigInteger r0 = k.Subtract(d0.Multiply(q.u)).Subtract(
BigInteger.ValueOf(2).Multiply(s[1]).Multiply(q.v));
// r1 = s1*q0 - s0*q1
BigInteger r1 = s[1].Multiply(q.u).Subtract(s[0].Multiply(q.v));
return new ZTauElement(r0, r1);
}
/**
* Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
* by a <code>BigInteger</code> using the reduced <code>&#964;</code>-adic
* NAF (RTNAF) method.
* @param p The F2mPoint to Multiply.
* @param k The <code>BigInteger</code> by which to Multiply <code>p</code>.
* @return <code>k * p</code>
*/
public static F2mPoint MultiplyRTnaf(F2mPoint p, BigInteger k)
{
F2mCurve curve = (F2mCurve) p.Curve;
int m = curve.M;
sbyte a = (sbyte) curve.A.ToBigInteger().IntValue;
sbyte mu = curve.GetMu();
BigInteger[] s = curve.GetSi();
ZTauElement rho = PartModReduction(k, m, a, s, mu, (sbyte)10);
return MultiplyTnaf(p, rho);
}
/**
* Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
* by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>
* using the <code>&#964;</code>-adic NAF (TNAF) method.
* @param p The F2mPoint to Multiply.
* @param lambda The element <code>&#955;</code> of
* <code><b>Z</b>[&#964;]</code>.
* @return <code>&#955; * p</code>
*/
public static F2mPoint MultiplyTnaf(F2mPoint p, ZTauElement lambda)
{
F2mCurve curve = (F2mCurve)p.Curve;
sbyte mu = curve.GetMu();
sbyte[] u = TauAdicNaf(mu, lambda);
F2mPoint q = MultiplyFromTnaf(p, u);
return q;
}
/**
* Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
* by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>
* using the <code>&#964;</code>-adic NAF (TNAF) method, given the TNAF
* of <code>&#955;</code>.
* @param p The F2mPoint to Multiply.
* @param u The the TNAF of <code>&#955;</code>..
* @return <code>&#955; * p</code>
*/
public static F2mPoint MultiplyFromTnaf(F2mPoint p, sbyte[] u)
{
F2mCurve curve = (F2mCurve)p.Curve;
F2mPoint q = (F2mPoint) curve.Infinity;
for (int i = u.Length - 1; i >= 0; i--)
{
q = Tau(q);
if (u[i] == 1)
{
q = (F2mPoint)q.AddSimple(p);
}
else if (u[i] == -1)
{
q = (F2mPoint)q.SubtractSimple(p);
}
}
return q;
}
/**
* Computes the <code>[&#964;]</code>-adic window NAF of an element
* <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>.
* @param mu The parameter &#956; of the elliptic curve.
* @param lambda The element <code>&#955;</code> of
* <code><b>Z</b>[&#964;]</code> of which to compute the
* <code>[&#964;]</code>-adic NAF.
* @param width The window width of the resulting WNAF.
* @param pow2w 2<sup>width</sup>.
* @param tw The auxiliary value <code>t<sub>w</sub></code>.
* @param alpha The <code>&#945;<sub>u</sub></code>'s for the window width.
* @return The <code>[&#964;]</code>-adic window NAF of
* <code>&#955;</code>.
*/
public static sbyte[] TauAdicWNaf(sbyte mu, ZTauElement lambda,
sbyte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)
{
if (!((mu == 1) || (mu == -1)))
throw new ArgumentException("mu must be 1 or -1");
BigInteger norm = Norm(mu, lambda);
// Ceiling of log2 of the norm
int log2Norm = norm.BitLength;
// If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width;
// The array holding the TNAF
sbyte[] u = new sbyte[maxLength];
// 2^(width - 1)
BigInteger pow2wMin1 = pow2w.ShiftRight(1);
// Split lambda into two BigIntegers to simplify calculations
BigInteger r0 = lambda.u;
BigInteger r1 = lambda.v;
int i = 0;
// while lambda <> (0, 0)
while (!((r0.Equals(BigInteger.Zero))&&(r1.Equals(BigInteger.Zero))))
{
// if r0 is odd
if (r0.TestBit(0))
{
// uUnMod = r0 + r1*tw Mod 2^width
BigInteger uUnMod
= r0.Add(r1.Multiply(tw)).Mod(pow2w);
sbyte uLocal;
// if uUnMod >= 2^(width - 1)
if (uUnMod.CompareTo(pow2wMin1) >= 0)
{
uLocal = (sbyte) uUnMod.Subtract(pow2w).IntValue;
}
else
{
uLocal = (sbyte) uUnMod.IntValue;
}
// uLocal is now in [-2^(width-1), 2^(width-1)-1]
u[i] = uLocal;
bool s = true;
if (uLocal < 0)
{
s = false;
uLocal = (sbyte)-uLocal;
}
// uLocal is now >= 0
if (s)
{
r0 = r0.Subtract(alpha[uLocal].u);
r1 = r1.Subtract(alpha[uLocal].v);
}
else
{
r0 = r0.Add(alpha[uLocal].u);
r1 = r1.Add(alpha[uLocal].v);
}
}
else
{
u[i] = 0;
}
BigInteger t = r0;
if (mu == 1)
{
r0 = r1.Add(r0.ShiftRight(1));
}
else
{
// mu == -1
r0 = r1.Subtract(r0.ShiftRight(1));
}
r1 = t.ShiftRight(1).Negate();
i++;
}
return u;
}
/**
* Does the precomputation for WTNAF multiplication.
* @param p The <code>ECPoint</code> for which to do the precomputation.
* @param a The parameter <code>a</code> of the elliptic curve.
* @return The precomputation array for <code>p</code>.
*/
public static F2mPoint[] GetPreComp(F2mPoint p, sbyte a)
{
F2mPoint[] pu;
pu = new F2mPoint[16];
pu[1] = p;
sbyte[][] alphaTnaf;
if (a == 0)
{
alphaTnaf = Tnaf.Alpha0Tnaf;
}
else
{
// a == 1
alphaTnaf = Tnaf.Alpha1Tnaf;
}
int precompLen = alphaTnaf.Length;
for (int i = 3; i < precompLen; i = i + 2)
{
pu[i] = Tnaf.MultiplyFromTnaf(p, alphaTnaf[i]);
}
return pu;
}
}
}

View File

@@ -0,0 +1,36 @@
namespace Org.BouncyCastle.Math.EC.Abc
{
/**
* Class representing an element of <code><b>Z</b>[&#964;]</code>. Let
* <code>&#955;</code> be an element of <code><b>Z</b>[&#964;]</code>. Then
* <code>&#955;</code> is given as <code>&#955; = u + v&#964;</code>. The
* components <code>u</code> and <code>v</code> may be used directly, there
* are no accessor methods.
* Immutable class.
*/
internal class ZTauElement
{
/**
* The &quot;real&quot; part of <code>&#955;</code>.
*/
public readonly BigInteger u;
/**
* The &quot;<code>&#964;</code>-adic&quot; part of <code>&#955;</code>.
*/
public readonly BigInteger v;
/**
* Constructor for an element <code>&#955;</code> of
* <code><b>Z</b>[&#964;]</code>.
* @param u The &quot;real&quot; part of <code>&#955;</code>.
* @param v The &quot;<code>&#964;</code>-adic&quot; part of
* <code>&#955;</code>.
*/
public ZTauElement(BigInteger u, BigInteger v)
{
this.u = u;
this.v = v;
}
}
}

View File

@@ -0,0 +1,18 @@
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Interface for classes encapsulating a point multiplication algorithm
* for <code>ECPoint</code>s.
*/
internal interface ECMultiplier
{
/**
* Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e.
* <code>p</code> is added <code>k</code> times to itself.
* @param p The <code>ECPoint</code> to be multiplied.
* @param k The factor by which <code>p</code> i multiplied.
* @return <code>p</code> multiplied by <code>k</code>.
*/
ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo);
}
}

View File

@@ -0,0 +1,39 @@
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class implementing the NAF (Non-Adjacent Form) multiplication algorithm.
*/
internal class FpNafMultiplier
: ECMultiplier
{
/**
* D.3.2 pg 101
* @see org.bouncycastle.math.ec.multiplier.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger)
*/
public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
{
// TODO Probably should try to add this
// BigInteger e = k.Mod(n); // n == order of p
BigInteger e = k;
BigInteger h = e.Multiply(BigInteger.Three);
ECPoint neg = p.Negate();
ECPoint R = p;
for (int i = h.BitLength - 2; i > 0; --i)
{
R = R.Twice();
bool hBit = h.TestBit(i);
bool eBit = e.TestBit(i);
if (hBit != eBit)
{
R = R.Add(hBit ? p : neg);
}
}
return R;
}
}
}

View File

@@ -0,0 +1,11 @@
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Interface for classes storing precomputation data for multiplication
* algorithms. Used as a Memento (see GOF patterns) for
* <code>WNafMultiplier</code>.
*/
internal interface PreCompInfo
{
}
}

View File

@@ -0,0 +1,30 @@
namespace Org.BouncyCastle.Math.EC.Multiplier
{
internal class ReferenceMultiplier
: ECMultiplier
{
/**
* Simple shift-and-add multiplication. Serves as reference implementation
* to verify (possibly faster) implementations in
* {@link org.bouncycastle.math.ec.ECPoint ECPoint}.
*
* @param p The point to multiply.
* @param k The factor by which to multiply.
* @return The result of the point multiplication <code>k * p</code>.
*/
public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
{
ECPoint q = p.Curve.Infinity;
int t = k.BitLength;
for (int i = 0; i < t; i++)
{
if (k.TestBit(i))
{
q = q.Add(p);
}
p = p.Twice();
}
return q;
}
}
}

View File

@@ -0,0 +1,241 @@
using System;
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class implementing the WNAF (Window Non-Adjacent Form) multiplication
* algorithm.
*/
internal class WNafMultiplier
: ECMultiplier
{
/**
* Computes the Window NAF (non-adjacent Form) of an integer.
* @param width The width <code>w</code> of the Window NAF. The width is
* defined as the minimal number <code>w</code>, such that for any
* <code>w</code> consecutive digits in the resulting representation, at
* most one is non-zero.
* @param k The integer of which the Window NAF is computed.
* @return The Window NAF of the given width, such that the following holds:
* <code>k = &#8722;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
* </code>, where the <code>k<sub>i</sub></code> denote the elements of the
* returned <code>sbyte[]</code>.
*/
public sbyte[] WindowNaf(sbyte width, BigInteger k)
{
// The window NAF is at most 1 element longer than the binary
// representation of the integer k. sbyte can be used instead of short or
// int unless the window width is larger than 8. For larger width use
// short or int. However, a width of more than 8 is not efficient for
// m = log2(q) smaller than 2305 Bits. Note: Values for m larger than
// 1000 Bits are currently not used in practice.
sbyte[] wnaf = new sbyte[k.BitLength + 1];
// 2^width as short and BigInteger
short pow2wB = (short)(1 << width);
BigInteger pow2wBI = BigInteger.ValueOf(pow2wB);
int i = 0;
// The actual length of the WNAF
int length = 0;
// while k >= 1
while (k.SignValue > 0)
{
// if k is odd
if (k.TestBit(0))
{
// k Mod 2^width
BigInteger remainder = k.Mod(pow2wBI);
// if remainder > 2^(width - 1) - 1
if (remainder.TestBit(width - 1))
{
wnaf[i] = (sbyte)(remainder.IntValue - pow2wB);
}
else
{
wnaf[i] = (sbyte)remainder.IntValue;
}
// wnaf[i] is now in [-2^(width-1), 2^(width-1)-1]
k = k.Subtract(BigInteger.ValueOf(wnaf[i]));
length = i;
}
else
{
wnaf[i] = 0;
}
// k = k/2
k = k.ShiftRight(1);
i++;
}
length++;
// Reduce the WNAF array to its actual length
sbyte[] wnafShort = new sbyte[length];
Array.Copy(wnaf, 0, wnafShort, 0, length);
return wnafShort;
}
/**
* Multiplies <code>this</code> by an integer <code>k</code> using the
* Window NAF method.
* @param k The integer by which <code>this</code> is multiplied.
* @return A new <code>ECPoint</code> which equals <code>this</code>
* multiplied by <code>k</code>.
*/
public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
{
WNafPreCompInfo wnafPreCompInfo;
if ((preCompInfo != null) && (preCompInfo is WNafPreCompInfo))
{
wnafPreCompInfo = (WNafPreCompInfo)preCompInfo;
}
else
{
// Ignore empty PreCompInfo or PreCompInfo of incorrect type
wnafPreCompInfo = new WNafPreCompInfo();
}
// floor(log2(k))
int m = k.BitLength;
// width of the Window NAF
sbyte width;
// Required length of precomputation array
int reqPreCompLen;
// Determine optimal width and corresponding length of precomputation
// array based on literature values
if (m < 13)
{
width = 2;
reqPreCompLen = 1;
}
else
{
if (m < 41)
{
width = 3;
reqPreCompLen = 2;
}
else
{
if (m < 121)
{
width = 4;
reqPreCompLen = 4;
}
else
{
if (m < 337)
{
width = 5;
reqPreCompLen = 8;
}
else
{
if (m < 897)
{
width = 6;
reqPreCompLen = 16;
}
else
{
if (m < 2305)
{
width = 7;
reqPreCompLen = 32;
}
else
{
width = 8;
reqPreCompLen = 127;
}
}
}
}
}
}
// The length of the precomputation array
int preCompLen = 1;
ECPoint[] preComp = wnafPreCompInfo.GetPreComp();
ECPoint twiceP = wnafPreCompInfo.GetTwiceP();
// Check if the precomputed ECPoints already exist
if (preComp == null)
{
// Precomputation must be performed from scratch, create an empty
// precomputation array of desired length
preComp = new ECPoint[]{ p };
}
else
{
// Take the already precomputed ECPoints to start with
preCompLen = preComp.Length;
}
if (twiceP == null)
{
// Compute twice(p)
twiceP = p.Twice();
}
if (preCompLen < reqPreCompLen)
{
// Precomputation array must be made bigger, copy existing preComp
// array into the larger new preComp array
ECPoint[] oldPreComp = preComp;
preComp = new ECPoint[reqPreCompLen];
Array.Copy(oldPreComp, 0, preComp, 0, preCompLen);
for (int i = preCompLen; i < reqPreCompLen; i++)
{
// Compute the new ECPoints for the precomputation array.
// The values 1, 3, 5, ..., 2^(width-1)-1 times p are
// computed
preComp[i] = twiceP.Add(preComp[i - 1]);
}
}
// Compute the Window NAF of the desired width
sbyte[] wnaf = WindowNaf(width, k);
int l = wnaf.Length;
// Apply the Window NAF to p using the precomputed ECPoint values.
ECPoint q = p.Curve.Infinity;
for (int i = l - 1; i >= 0; i--)
{
q = q.Twice();
if (wnaf[i] != 0)
{
if (wnaf[i] > 0)
{
q = q.Add(preComp[(wnaf[i] - 1)/2]);
}
else
{
// wnaf[i] < 0
q = q.Subtract(preComp[(-wnaf[i] - 1)/2]);
}
}
}
// Set PreCompInfo in ECPoint, such that it is available for next
// multiplication.
wnafPreCompInfo.SetPreComp(preComp);
wnafPreCompInfo.SetTwiceP(twiceP);
p.SetPreCompInfo(wnafPreCompInfo);
return q;
}
}
}

View File

@@ -0,0 +1,46 @@
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
* algorithm.
*/
internal class WNafPreCompInfo
: PreCompInfo
{
/**
* Array holding the precomputed <code>ECPoint</code>s used for the Window
* NAF multiplication in <code>
* {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
* WNafMultiplier.multiply()}</code>.
*/
private ECPoint[] preComp = null;
/**
* Holds an <code>ECPoint</code> representing twice(this). Used for the
* Window NAF multiplication in <code>
* {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
* WNafMultiplier.multiply()}</code>.
*/
private ECPoint twiceP = null;
internal ECPoint[] GetPreComp()
{
return preComp;
}
internal void SetPreComp(ECPoint[] preComp)
{
this.preComp = preComp;
}
internal ECPoint GetTwiceP()
{
return twiceP;
}
internal void SetTwiceP(ECPoint twiceThis)
{
this.twiceP = twiceThis;
}
}
}

View File

@@ -0,0 +1,120 @@
using System;
using Org.BouncyCastle.Math.EC.Abc;
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class implementing the WTNAF (Window
* <code>&#964;</code>-adic Non-Adjacent Form) algorithm.
*/
internal class WTauNafMultiplier
: ECMultiplier
{
/**
* Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
* by <code>k</code> using the reduced <code>&#964;</code>-adic NAF (RTNAF)
* method.
* @param p The F2mPoint to multiply.
* @param k The integer by which to multiply <code>k</code>.
* @return <code>p</code> multiplied by <code>k</code>.
*/
public ECPoint Multiply(ECPoint point, BigInteger k, PreCompInfo preCompInfo)
{
if (!(point is F2mPoint))
throw new ArgumentException("Only F2mPoint can be used in WTauNafMultiplier");
F2mPoint p = (F2mPoint)point;
F2mCurve curve = (F2mCurve) p.Curve;
int m = curve.M;
sbyte a = (sbyte) curve.A.ToBigInteger().IntValue;
sbyte mu = curve.GetMu();
BigInteger[] s = curve.GetSi();
ZTauElement rho = Tnaf.PartModReduction(k, m, a, s, mu, (sbyte)10);
return MultiplyWTnaf(p, rho, preCompInfo, a, mu);
}
/**
* Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
* by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code> using
* the <code>&#964;</code>-adic NAF (TNAF) method.
* @param p The F2mPoint to multiply.
* @param lambda The element <code>&#955;</code> of
* <code><b>Z</b>[&#964;]</code> of which to compute the
* <code>[&#964;]</code>-adic NAF.
* @return <code>p</code> multiplied by <code>&#955;</code>.
*/
private F2mPoint MultiplyWTnaf(F2mPoint p, ZTauElement lambda,
PreCompInfo preCompInfo, sbyte a, sbyte mu)
{
ZTauElement[] alpha;
if (a == 0)
{
alpha = Tnaf.Alpha0;
}
else
{
// a == 1
alpha = Tnaf.Alpha1;
}
BigInteger tw = Tnaf.GetTw(mu, Tnaf.Width);
sbyte[]u = Tnaf.TauAdicWNaf(mu, lambda, Tnaf.Width,
BigInteger.ValueOf(Tnaf.Pow2Width), tw, alpha);
return MultiplyFromWTnaf(p, u, preCompInfo);
}
/**
* Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
* by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>
* using the window <code>&#964;</code>-adic NAF (TNAF) method, given the
* WTNAF of <code>&#955;</code>.
* @param p The F2mPoint to multiply.
* @param u The the WTNAF of <code>&#955;</code>..
* @return <code>&#955; * p</code>
*/
private static F2mPoint MultiplyFromWTnaf(F2mPoint p, sbyte[] u,
PreCompInfo preCompInfo)
{
F2mCurve curve = (F2mCurve)p.Curve;
sbyte a = (sbyte) curve.A.ToBigInteger().IntValue;
F2mPoint[] pu;
if ((preCompInfo == null) || !(preCompInfo is WTauNafPreCompInfo))
{
pu = Tnaf.GetPreComp(p, a);
p.SetPreCompInfo(new WTauNafPreCompInfo(pu));
}
else
{
pu = ((WTauNafPreCompInfo)preCompInfo).GetPreComp();
}
// q = infinity
F2mPoint q = (F2mPoint) p.Curve.Infinity;
for (int i = u.Length - 1; i >= 0; i--)
{
q = Tnaf.Tau(q);
if (u[i] != 0)
{
if (u[i] > 0)
{
q = q.AddSimple(pu[u[i]]);
}
else
{
// u[i] < 0
q = q.SubtractSimple(pu[-u[i]]);
}
}
}
return q;
}
}
}

View File

@@ -0,0 +1,41 @@
namespace Org.BouncyCastle.Math.EC.Multiplier
{
/**
* Class holding precomputation data for the WTNAF (Window
* <code>&#964;</code>-adic Non-Adjacent Form) algorithm.
*/
internal class WTauNafPreCompInfo
: PreCompInfo
{
/**
* Array holding the precomputed <code>F2mPoint</code>s used for the
* WTNAF multiplication in <code>
* {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
* WTauNafMultiplier.multiply()}</code>.
*/
private readonly F2mPoint[] preComp;
/**
* Constructor for <code>WTauNafPreCompInfo</code>
* @param preComp Array holding the precomputed <code>F2mPoint</code>s
* used for the WTNAF multiplication in <code>
* {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
* WTauNafMultiplier.multiply()}</code>.
*/
internal WTauNafPreCompInfo(F2mPoint[] preComp)
{
this.preComp = preComp;
}
/**
* @return the array holding the precomputed <code>F2mPoint</code>s
* used for the WTNAF multiplication in <code>
* {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
* WTauNafMultiplier.multiply()}</code>.
*/
internal F2mPoint[] GetPreComp()
{
return preComp;
}
}
}