Initial Commit
This commit is contained in:
3152
iTechSharp/srcbc/math/BigInteger.cs
Normal file
3152
iTechSharp/srcbc/math/BigInteger.cs
Normal file
File diff suppressed because it is too large
Load Diff
94
iTechSharp/srcbc/math/ec/ECAlgorithms.cs
Normal file
94
iTechSharp/srcbc/math/ec/ECAlgorithms.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
661
iTechSharp/srcbc/math/ec/ECCurve.cs
Normal file
661
iTechSharp/srcbc/math/ec/ECCurve.cs
Normal 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>μ</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>μ</code> of the elliptic curve.
|
||||
* @return <code>μ</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; }
|
||||
}
|
||||
}
|
||||
}
|
1253
iTechSharp/srcbc/math/ec/ECFieldElement.cs
Normal file
1253
iTechSharp/srcbc/math/ec/ECFieldElement.cs
Normal file
File diff suppressed because it is too large
Load Diff
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();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
486
iTechSharp/srcbc/math/ec/IntArray.cs
Normal file
486
iTechSharp/srcbc/math/ec/IntArray.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
241
iTechSharp/srcbc/math/ec/abc/SimpleBigDecimal.cs
Normal file
241
iTechSharp/srcbc/math/ec/abc/SimpleBigDecimal.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
834
iTechSharp/srcbc/math/ec/abc/Tnaf.cs
Normal file
834
iTechSharp/srcbc/math/ec/abc/Tnaf.cs
Normal file
@@ -0,0 +1,834 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Math.EC.Abc
|
||||
{
|
||||
/**
|
||||
* Class holding methods for point multiplication based on the window
|
||||
* τ-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>α<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>α<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>α<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>α<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>α<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>λ</code> of
|
||||
* <code><b>Z</b>[τ]</code>.
|
||||
* @param mu The parameter <code>μ</code> of the elliptic curve.
|
||||
* @param lambda The element <code>λ</code> of
|
||||
* <code><b>Z</b>[τ]</code>.
|
||||
* @return The norm of <code>λ</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>λ</code> of
|
||||
* <code><b>R</b>[τ]</code>, where <code>λ = u + vτ</code>
|
||||
* and <code>u</code> and <code>u</code> are real numbers (elements of
|
||||
* <code><b>R</b></code>).
|
||||
* @param mu The parameter <code>μ</code> of the elliptic curve.
|
||||
* @param u The real part of the element <code>λ</code> of
|
||||
* <code><b>R</b>[τ]</code>.
|
||||
* @param v The <code>τ</code>-adic part of the element
|
||||
* <code>λ</code> of <code><b>R</b>[τ]</code>.
|
||||
* @return The norm of <code>λ</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>λ</code> of <code><b>R</b>[τ]</code>
|
||||
* to an element of <code><b>Z</b>[τ]</code>, such that their difference
|
||||
* has minimal norm. <code>λ</code> is given as
|
||||
* <code>λ = λ<sub>0</sub> + λ<sub>1</sub>τ</code>.
|
||||
* @param lambda0 The component <code>λ<sub>0</sub></code>.
|
||||
* @param lambda1 The component <code>λ<sub>1</sub></code>.
|
||||
* @param mu The parameter <code>μ</code> of the elliptic curve. Must
|
||||
* equal 1 or -1.
|
||||
* @return The rounded element of <code><b>Z</b>[τ]</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>λ = 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>λ = 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>τ</code>-adic NAF (non-adjacent form) of an
|
||||
* element <code>λ</code> of <code><b>Z</b>[τ]</code>.
|
||||
* @param mu The parameter <code>μ</code> of the elliptic curve.
|
||||
* @param lambda The element <code>λ</code> of
|
||||
* <code><b>Z</b>[τ]</code>.
|
||||
* @return The <code>τ</code>-adic NAF of <code>λ</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>τ()</code> to an
|
||||
* <code>F2mPoint</code>.
|
||||
* @param p The F2mPoint to which <code>τ()</code> is applied.
|
||||
* @return <code>τ(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>μ</code> of the elliptic curve.
|
||||
* @param curve The elliptic curve from which to obtain <code>μ</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>μ</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>μ</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>μ</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>(τ<sup>m</sup> - 1)/(τ - 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 μ of the elliptic curve.
|
||||
* @param c The precision (number of bits of accuracy) of the partial
|
||||
* modular reduction.
|
||||
* @return <code>ρ := k partmod (τ<sup>m</sup> - 1)/(τ - 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>τ</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>λ</code> of <code><b>Z</b>[τ]</code>
|
||||
* using the <code>τ</code>-adic NAF (TNAF) method.
|
||||
* @param p The F2mPoint to Multiply.
|
||||
* @param lambda The element <code>λ</code> of
|
||||
* <code><b>Z</b>[τ]</code>.
|
||||
* @return <code>λ * 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>λ</code> of <code><b>Z</b>[τ]</code>
|
||||
* using the <code>τ</code>-adic NAF (TNAF) method, given the TNAF
|
||||
* of <code>λ</code>.
|
||||
* @param p The F2mPoint to Multiply.
|
||||
* @param u The the TNAF of <code>λ</code>..
|
||||
* @return <code>λ * 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>[τ]</code>-adic window NAF of an element
|
||||
* <code>λ</code> of <code><b>Z</b>[τ]</code>.
|
||||
* @param mu The parameter μ of the elliptic curve.
|
||||
* @param lambda The element <code>λ</code> of
|
||||
* <code><b>Z</b>[τ]</code> of which to compute the
|
||||
* <code>[τ]</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>α<sub>u</sub></code>'s for the window width.
|
||||
* @return The <code>[τ]</code>-adic window NAF of
|
||||
* <code>λ</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;
|
||||
}
|
||||
}
|
||||
}
|
36
iTechSharp/srcbc/math/ec/abc/ZTauElement.cs
Normal file
36
iTechSharp/srcbc/math/ec/abc/ZTauElement.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace Org.BouncyCastle.Math.EC.Abc
|
||||
{
|
||||
/**
|
||||
* Class representing an element of <code><b>Z</b>[τ]</code>. Let
|
||||
* <code>λ</code> be an element of <code><b>Z</b>[τ]</code>. Then
|
||||
* <code>λ</code> is given as <code>λ = u + vτ</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 "real" part of <code>λ</code>.
|
||||
*/
|
||||
public readonly BigInteger u;
|
||||
|
||||
/**
|
||||
* The "<code>τ</code>-adic" part of <code>λ</code>.
|
||||
*/
|
||||
public readonly BigInteger v;
|
||||
|
||||
/**
|
||||
* Constructor for an element <code>λ</code> of
|
||||
* <code><b>Z</b>[τ]</code>.
|
||||
* @param u The "real" part of <code>λ</code>.
|
||||
* @param v The "<code>τ</code>-adic" part of
|
||||
* <code>λ</code>.
|
||||
*/
|
||||
public ZTauElement(BigInteger u, BigInteger v)
|
||||
{
|
||||
this.u = u;
|
||||
this.v = v;
|
||||
}
|
||||
}
|
||||
}
|
18
iTechSharp/srcbc/math/ec/multiplier/ECMultiplier.cs
Normal file
18
iTechSharp/srcbc/math/ec/multiplier/ECMultiplier.cs
Normal 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);
|
||||
}
|
||||
}
|
39
iTechSharp/srcbc/math/ec/multiplier/FpNafMultiplier.cs
Normal file
39
iTechSharp/srcbc/math/ec/multiplier/FpNafMultiplier.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
11
iTechSharp/srcbc/math/ec/multiplier/PreCompInfo.cs
Normal file
11
iTechSharp/srcbc/math/ec/multiplier/PreCompInfo.cs
Normal 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
|
||||
{
|
||||
}
|
||||
}
|
30
iTechSharp/srcbc/math/ec/multiplier/ReferenceMultiplier.cs
Normal file
30
iTechSharp/srcbc/math/ec/multiplier/ReferenceMultiplier.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
241
iTechSharp/srcbc/math/ec/multiplier/WNafMultiplier.cs
Normal file
241
iTechSharp/srcbc/math/ec/multiplier/WNafMultiplier.cs
Normal 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 = −<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;
|
||||
}
|
||||
}
|
||||
}
|
46
iTechSharp/srcbc/math/ec/multiplier/WNafPreCompInfo.cs
Normal file
46
iTechSharp/srcbc/math/ec/multiplier/WNafPreCompInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
120
iTechSharp/srcbc/math/ec/multiplier/WTauNafMultiplier.cs
Normal file
120
iTechSharp/srcbc/math/ec/multiplier/WTauNafMultiplier.cs
Normal 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>τ</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>τ</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>λ</code> of <code><b>Z</b>[τ]</code> using
|
||||
* the <code>τ</code>-adic NAF (TNAF) method.
|
||||
* @param p The F2mPoint to multiply.
|
||||
* @param lambda The element <code>λ</code> of
|
||||
* <code><b>Z</b>[τ]</code> of which to compute the
|
||||
* <code>[τ]</code>-adic NAF.
|
||||
* @return <code>p</code> multiplied by <code>λ</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>λ</code> of <code><b>Z</b>[τ]</code>
|
||||
* using the window <code>τ</code>-adic NAF (TNAF) method, given the
|
||||
* WTNAF of <code>λ</code>.
|
||||
* @param p The F2mPoint to multiply.
|
||||
* @param u The the WTNAF of <code>λ</code>..
|
||||
* @return <code>λ * 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;
|
||||
}
|
||||
}
|
||||
}
|
41
iTechSharp/srcbc/math/ec/multiplier/WTauNafPreCompInfo.cs
Normal file
41
iTechSharp/srcbc/math/ec/multiplier/WTauNafPreCompInfo.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
namespace Org.BouncyCastle.Math.EC.Multiplier
|
||||
{
|
||||
/**
|
||||
* Class holding precomputation data for the WTNAF (Window
|
||||
* <code>τ</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;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user