diff options
Diffstat (limited to 'src/org')
-rw-r--r-- | src/org/bouncycastle/math/ec/ECConstants.java | 12 | ||||
-rw-r--r-- | src/org/bouncycastle/math/ec/ECCurve.java | 179 | ||||
-rw-r--r-- | src/org/bouncycastle/math/ec/ECFieldElement.java | 780 | ||||
-rw-r--r-- | src/org/bouncycastle/math/ec/ECMultiplier.java | 19 | ||||
-rw-r--r-- | src/org/bouncycastle/math/ec/ECPoint.java | 335 | ||||
-rw-r--r-- | src/org/bouncycastle/math/ec/FpNafMultiplier.java | 39 | ||||
-rw-r--r-- | src/org/bouncycastle/math/ec/PreCompInfo.java | 10 | ||||
-rw-r--r-- | src/org/bouncycastle/math/ec/WNafMultiplier.java | 240 | ||||
-rw-r--r-- | src/org/bouncycastle/math/ec/WNafPreCompInfo.java | 44 | ||||
-rw-r--r-- | src/org/connectbot/util/PubkeyUtils.java | 26 | ||||
-rw-r--r-- | src/org/keyczar/jce/EcCore.java | 677 |
11 files changed, 687 insertions, 1674 deletions
diff --git a/src/org/bouncycastle/math/ec/ECConstants.java b/src/org/bouncycastle/math/ec/ECConstants.java deleted file mode 100644 index 864f746..0000000 --- a/src/org/bouncycastle/math/ec/ECConstants.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.bouncycastle.math.ec; - -import java.math.BigInteger; - -public interface ECConstants -{ - public static final BigInteger ZERO = BigInteger.valueOf(0); - public static final BigInteger ONE = BigInteger.valueOf(1); - public static final BigInteger TWO = BigInteger.valueOf(2); - public static final BigInteger THREE = BigInteger.valueOf(3); - public static final BigInteger FOUR = BigInteger.valueOf(4); -} diff --git a/src/org/bouncycastle/math/ec/ECCurve.java b/src/org/bouncycastle/math/ec/ECCurve.java deleted file mode 100644 index ee7ddc3..0000000 --- a/src/org/bouncycastle/math/ec/ECCurve.java +++ /dev/null @@ -1,179 +0,0 @@ -package org.bouncycastle.math.ec; - -import java.math.BigInteger; - -/** - * base class for an elliptic curve - */ -public abstract class ECCurve -{ - ECFieldElement a, b; - - public abstract int getFieldSize(); - - public abstract ECFieldElement fromBigInteger(BigInteger x); - - public abstract ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression); - - public abstract ECPoint decodePoint(byte[] encoded); - - public abstract ECPoint getInfinity(); - - public ECFieldElement getA() - { - return a; - } - - public ECFieldElement getB() - { - return b; - } - - /** - * Elliptic curve over Fp - */ - public static class Fp extends ECCurve - { - BigInteger q; - ECPoint.Fp infinity; - - public Fp(BigInteger q, BigInteger a, BigInteger b) - { - this.q = q; - this.a = fromBigInteger(a); - this.b = fromBigInteger(b); - this.infinity = new ECPoint.Fp(this, null, null); - } - - public BigInteger getQ() - { - return q; - } - - @Override - public int getFieldSize() - { - return q.bitLength(); - } - - @Override - public ECFieldElement fromBigInteger(BigInteger x) - { - return new ECFieldElement.Fp(this.q, x); - } - - @Override - public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) - { - return new ECPoint.Fp(this, fromBigInteger(x), fromBigInteger(y), withCompression); - } - - /** - * 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. - */ - @Override - public ECPoint decodePoint(byte[] encoded) - { - ECPoint p = null; - - switch (encoded[0]) - { - // infinity - case 0x00: - if (encoded.length > 1) - { - throw new RuntimeException("Invalid point encoding"); - } - p = getInfinity(); - break; - // compressed - case 0x02: - case 0x03: - int ytilde = encoded[0] & 1; - byte[] i = new byte[encoded.length - 1]; - - System.arraycopy(encoded, 1, i, 0, i.length); - - ECFieldElement x = new ECFieldElement.Fp(this.q, new BigInteger(1, i)); - 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 RuntimeException("Invalid point compression"); - } - - int bit0 = (beta.toBigInteger().testBit(0) ? 1 : 0); - - if (bit0 == ytilde) - { - p = new ECPoint.Fp(this, x, beta, true); - } - else - { - p = new ECPoint.Fp(this, x, - new ECFieldElement.Fp(this.q, q.subtract(beta.toBigInteger())), true); - } - break; - // uncompressed - case 0x04: - // hybrid - case 0x06: - case 0x07: - byte[] xEnc = new byte[(encoded.length - 1) / 2]; - byte[] yEnc = new byte[(encoded.length - 1) / 2]; - - System.arraycopy(encoded, 1, xEnc, 0, xEnc.length); - System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length); - - p = new ECPoint.Fp(this, - new ECFieldElement.Fp(this.q, new BigInteger(1, xEnc)), - new ECFieldElement.Fp(this.q, new BigInteger(1, yEnc))); - break; - default: - throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); - } - - return p; - } - - @Override - public ECPoint getInfinity() - { - return infinity; - } - - @Override - public boolean equals( - Object anObject) - { - if (anObject == this) - { - return true; - } - - if (!(anObject instanceof ECCurve.Fp)) - { - return false; - } - - ECCurve.Fp other = (ECCurve.Fp) anObject; - - return this.q.equals(other.q) - && a.equals(other.a) && b.equals(other.b); - } - - @Override - public int hashCode() - { - return a.hashCode() ^ b.hashCode() ^ q.hashCode(); - } - } -} diff --git a/src/org/bouncycastle/math/ec/ECFieldElement.java b/src/org/bouncycastle/math/ec/ECFieldElement.java deleted file mode 100644 index 8c8f96e..0000000 --- a/src/org/bouncycastle/math/ec/ECFieldElement.java +++ /dev/null @@ -1,780 +0,0 @@ -package org.bouncycastle.math.ec; - -import java.math.BigInteger; -import java.util.Random; - -public abstract class ECFieldElement - implements ECConstants -{ - - public abstract BigInteger toBigInteger(); - public abstract String getFieldName(); - public abstract int getFieldSize(); - public abstract ECFieldElement add(ECFieldElement b); - public abstract ECFieldElement subtract(ECFieldElement b); - public abstract ECFieldElement multiply(ECFieldElement b); - public abstract ECFieldElement divide(ECFieldElement b); - public abstract ECFieldElement negate(); - public abstract ECFieldElement square(); - public abstract ECFieldElement invert(); - public abstract ECFieldElement sqrt(); - - @Override - public String toString() - { - return this.toBigInteger().toString(2); - } - - public static class Fp extends ECFieldElement - { - BigInteger x; - - BigInteger q; - - public Fp(BigInteger q, BigInteger x) - { - this.x = x; - - if (x.compareTo(q) >= 0) - { - throw new IllegalArgumentException("x value too large in field element"); - } - - this.q = q; - } - - @Override - public BigInteger toBigInteger() - { - return x; - } - - /** - * return the field name for this field. - * - * @return the string "Fp". - */ - @Override - public String getFieldName() - { - return "Fp"; - } - - @Override - public int getFieldSize() - { - return q.bitLength(); - } - - public BigInteger getQ() - { - return q; - } - - @Override - public ECFieldElement add(ECFieldElement b) - { - return new Fp(q, x.add(b.toBigInteger()).mod(q)); - } - - @Override - public ECFieldElement subtract(ECFieldElement b) - { - return new Fp(q, x.subtract(b.toBigInteger()).mod(q)); - } - - @Override - public ECFieldElement multiply(ECFieldElement b) - { - return new Fp(q, x.multiply(b.toBigInteger()).mod(q)); - } - - @Override - public ECFieldElement divide(ECFieldElement b) - { - return new Fp(q, x.multiply(b.toBigInteger().modInverse(q)).mod(q)); - } - - @Override - public ECFieldElement negate() - { - return new Fp(q, x.negate().mod(q)); - } - - @Override - public ECFieldElement square() - { - return new Fp(q, x.multiply(x).mod(q)); - } - - @Override - public ECFieldElement invert() - { - return new Fp(q, x.modInverse(q)); - } - - // D.1.4 91 - /** - * return a sqrt root - the routine verifies that the calculation - * returns the right value - if none exists it returns null. - */ - @Override - public ECFieldElement sqrt() - { - if (!q.testBit(0)) - { - throw new RuntimeException("not done yet"); - } - - // note: even though this class implements ECConstants don't be tempted to - // remove the explicit declaration, some J2ME environments don't cope. - // p mod 4 == 3 - if (q.testBit(1)) - { - // z = g^(u+1) + p, p = 4u + 3 - ECFieldElement z = new Fp(q, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q)); - - return z.square().equals(this) ? z : null; - } - - // p mod 4 == 1 - BigInteger qMinusOne = q.subtract(ECConstants.ONE); - - BigInteger legendreExponent = qMinusOne.shiftRight(1); - if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) - { - return null; - } - - BigInteger u = qMinusOne.shiftRight(2); - BigInteger k = u.shiftLeft(1).add(ECConstants.ONE); - - BigInteger Q = this.x; - BigInteger fourQ = Q.shiftLeft(2).mod(q); - - BigInteger U, V; - Random rand = new Random(); - do - { - BigInteger P; - do - { - P = new BigInteger(q.bitLength(), rand); - } - while (P.compareTo(q) >= 0 - || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne))); - - BigInteger[] result = lucasSequence(q, P, Q, k); - U = result[0]; - V = result[1]; - - if (V.multiply(V).mod(q).equals(fourQ)) - { - // Integer division by 2, mod q - if (V.testBit(0)) - { - V = V.add(q); - } - - V = V.shiftRight(1); - - //assert V.multiply(V).mod(q).equals(x); - - return new ECFieldElement.Fp(q, V); - } - } - while (U.equals(ECConstants.ONE) || U.equals(qMinusOne)); - - return null; - -// BigInteger qMinusOne = q.subtract(ECConstants.ONE); -// BigInteger legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO); -// if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) -// { -// return null; -// } -// -// Random rand = new Random(); -// BigInteger fourX = x.shiftLeft(2); -// -// BigInteger r; -// do -// { -// r = new BigInteger(q.bitLength(), rand); -// } -// while (r.compareTo(q) >= 0 -// || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne))); -// -// BigInteger n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR); -// BigInteger n2 = n1.add(ECConstants.ONE); //q.add(ECConstants.THREE).divide(ECConstants.FOUR); -// -// BigInteger wOne = WOne(r, x, q); -// BigInteger wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q); -// BigInteger twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r); -// -// BigInteger root = twoR.modPow(q.subtract(ECConstants.TWO), q) -// .multiply(x).mod(q) -// .multiply(wSum).mod(q); -// -// return new Fp(q, root); - } - -// private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p) -// { -// if (n.equals(ECConstants.ONE)) -// { -// return wOne; -// } -// boolean isEven = !n.testBit(0); -// n = n.shiftRight(1);//divide(ECConstants.TWO); -// if (isEven) -// { -// BigInteger w = W(n, wOne, p); -// return w.multiply(w).subtract(ECConstants.TWO).mod(p); -// } -// BigInteger w1 = W(n.add(ECConstants.ONE), wOne, p); -// BigInteger w2 = W(n, wOne, p); -// return w1.multiply(w2).subtract(wOne).mod(p); -// } -// -// private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p) -// { -// return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p); -// } - - private static BigInteger[] lucasSequence( - BigInteger p, - BigInteger P, - BigInteger Q, - BigInteger k) - { - int n = k.bitLength(); - int s = k.getLowestSetBit(); - - BigInteger Uh = ECConstants.ONE; - BigInteger Vl = ECConstants.TWO; - BigInteger Vh = P; - BigInteger Ql = ECConstants.ONE; - BigInteger Qh = ECConstants.ONE; - - for (int j = n - 1; j >= s + 1; --j) - { - Ql = Ql.multiply(Qh).mod(p); - - if (k.testBit(j)) - { - Qh = Ql.multiply(Q).mod(p); - Uh = Uh.multiply(Vh).mod(p); - Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); - Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p); - } - else - { - Qh = Ql; - Uh = Uh.multiply(Vl).subtract(Ql).mod(p); - Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); - Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); - } - } - - Ql = Ql.multiply(Qh).mod(p); - Qh = Ql.multiply(Q).mod(p); - Uh = Uh.multiply(Vl).subtract(Ql).mod(p); - Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); - Ql = Ql.multiply(Qh).mod(p); - - for (int j = 1; j <= s; ++j) - { - Uh = Uh.multiply(Vl).mod(p); - Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); - Ql = Ql.multiply(Ql).mod(p); - } - - return new BigInteger[]{ Uh, Vl }; - } - - @Override - public boolean equals(Object other) - { - if (other == this) - { - return true; - } - - if (!(other instanceof ECFieldElement.Fp)) - { - return false; - } - - ECFieldElement.Fp o = (ECFieldElement.Fp)other; - return q.equals(o.q) && x.equals(o.x); - } - - @Override - public int hashCode() - { - return q.hashCode() ^ x.hashCode(); - } - } - -// /** -// * Class representing the Elements of the finite field -// * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB) -// * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial -// * basis representations are supported. Gaussian normal basis (GNB) -// * representation is not supported. -// */ -// public static class F2m extends ECFieldElement -// { -// BigInteger x; -// -// /** -// * Indicates gaussian normal basis representation (GNB). Number chosen -// * according to X9.62. GNB is not implemented at present. -// */ -// public static final int GNB = 1; -// -// /** -// * Indicates trinomial basis representation (TPB). Number chosen -// * according to X9.62. -// */ -// public static final int TPB = 2; -// -// /** -// * Indicates pentanomial basis representation (PPB). Number chosen -// * according to X9.62. -// */ -// public static final int PPB = 3; -// -// /** -// * TPB or PPB. -// */ -// private int representation; -// -// /** -// * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. -// */ -// private 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 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 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 int k3; -// -// /** -// * Constructor for 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 x The BigInteger representing the value of the field element. -// */ -// public F2m( -// int m, -// int k1, -// int k2, -// int k3, -// BigInteger x) -// { -//// super(x); -// this.x = x; -// -// if ((k2 == 0) && (k3 == 0)) -// { -// this.representation = TPB; -// } -// else -// { -// if (k2 >= k3) -// { -// throw new IllegalArgumentException( -// "k2 must be smaller than k3"); -// } -// if (k2 <= 0) -// { -// throw new IllegalArgumentException( -// "k2 must be larger than 0"); -// } -// this.representation = PPB; -// } -// -// if (x.signum() < 0) -// { -// throw new IllegalArgumentException("x value cannot be negative"); -// } -// -// this.m = m; -// this.k1 = k1; -// this.k2 = k2; -// this.k3 = k3; -// } -// -// /** -// * Constructor for 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 x The BigInteger representing the value of the field element. -// */ -// public F2m(int m, int k, BigInteger x) -// { -// // Set k1 to k, and set k2 and k3 to 0 -// this(m, k, 0, 0, x); -// } -// -// public BigInteger toBigInteger() -// { -// return x; -// } -// -// public String getFieldName() -// { -// return "F2m"; -// } -// -// public int getFieldSize() -// { -// return m; -// } -// -// /** -// * Checks, if the ECFieldElements <code>a</code> and <code>b</code> -// * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code> -// * (having the same representation). -// * @param a field element. -// * @param b field element to be compared. -// * @throws IllegalArgumentException if <code>a</code> and <code>b</code> -// * are not elements of the same field -// * <code>F<sub>2<sup>m</sup></sub></code> (having the same -// * representation). -// */ -// public static void checkFieldElements( -// ECFieldElement a, -// ECFieldElement b) -// { -// if ((!(a instanceof F2m)) || (!(b instanceof F2m))) -// { -// throw new IllegalArgumentException("Field elements are not " -// + "both instances of ECFieldElement.F2m"); -// } -// -// if ((a.toBigInteger().signum() < 0) || (b.toBigInteger().signum() < 0)) -// { -// throw new IllegalArgumentException( -// "x value may not be negative"); -// } -// -// ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; -// ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; -// -// if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) -// || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) -// { -// throw new IllegalArgumentException("Field elements are not " -// + "elements of the same field F2m"); -// } -// -// if (aF2m.representation != bF2m.representation) -// { -// // Should never occur -// throw new IllegalArgumentException( -// "One of the field " -// + "elements are not elements has incorrect representation"); -// } -// } -// -// /** -// * Computes <code>z * a(z) mod f(z)</code>, where <code>f(z)</code> is -// * the reduction polynomial of <code>this</code>. -// * @param a The polynomial <code>a(z)</code> to be multiplied by -// * <code>z mod f(z)</code>. -// * @return <code>z * a(z) mod f(z)</code> -// */ -// private BigInteger multZModF(final BigInteger a) -// { -// // Left-shift of a(z) -// BigInteger az = a.shiftLeft(1); -// if (az.testBit(this.m)) -// { -// // If the coefficient of z^m in a(z) equals 1, reduction -// // modulo f(z) is performed: Add f(z) to to a(z): -// // Step 1: Unset mth coeffient of a(z) -// az = az.clearBit(this.m); -// -// // Step 2: Add r(z) to a(z), where r(z) is defined as -// // f(z) = z^m + r(z), and k1, k2, k3 are the positions of -// // the non-zero coefficients in r(z) -// az = az.flipBit(0); -// az = az.flipBit(this.k1); -// if (this.representation == PPB) -// { -// az = az.flipBit(this.k2); -// az = az.flipBit(this.k3); -// } -// } -// return az; -// } -// -// public ECFieldElement add(final ECFieldElement b) -// { -// // No check performed here for performance reasons. Instead the -// // elements involved are checked in ECPoint.F2m -// // checkFieldElements(this, b); -// if (b.toBigInteger().signum() == 0) -// { -// return this; -// } -// -// return new F2m(this.m, this.k1, this.k2, this.k3, this.x.xor(b.toBigInteger())); -// } -// -// public ECFieldElement subtract(final ECFieldElement b) -// { -// // Addition and subtraction are the same in F2m -// return add(b); -// } -// -// -// public ECFieldElement multiply(final ECFieldElement b) -// { -// // Left-to-right shift-and-add field multiplication in F2m -// // Input: Binary polynomials a(z) and b(z) of degree at most m-1 -// // Output: c(z) = a(z) * b(z) mod f(z) -// -// // No check performed here for performance reasons. Instead the -// // elements involved are checked in ECPoint.F2m -// // checkFieldElements(this, b); -// final BigInteger az = this.x; -// BigInteger bz = b.toBigInteger(); -// BigInteger cz; -// -// // Compute c(z) = a(z) * b(z) mod f(z) -// if (az.testBit(0)) -// { -// cz = bz; -// } -// else -// { -// cz = ECConstants.ZERO; -// } -// -// for (int i = 1; i < this.m; i++) -// { -// // b(z) := z * b(z) mod f(z) -// bz = multZModF(bz); -// -// if (az.testBit(i)) -// { -// // If the coefficient of x^i in a(z) equals 1, b(z) is added -// // to c(z) -// cz = cz.xor(bz); -// } -// } -// return new ECFieldElement.F2m(m, this.k1, this.k2, this.k3, cz); -// } -// -// -// public ECFieldElement divide(final ECFieldElement b) -// { -// // There may be more efficient implementations -// ECFieldElement bInv = b.invert(); -// return multiply(bInv); -// } -// -// public ECFieldElement negate() -// { -// // -x == x holds for all x in F2m -// return this; -// } -// -// public ECFieldElement square() -// { -// // Naive implementation, can probably be speeded up using modular -// // reduction -// return multiply(this); -// } -// -// public ECFieldElement invert() -// { -// // Inversion in F2m using the extended Euclidean algorithm -// // Input: A nonzero polynomial a(z) of degree at most m-1 -// // Output: a(z)^(-1) mod f(z) -// -// // u(z) := a(z) -// BigInteger uz = this.x; -// if (uz.signum() <= 0) -// { -// throw new ArithmeticException("x is zero or negative, " + -// "inversion is impossible"); -// } -// -// // v(z) := f(z) -// BigInteger vz = ECConstants.ZERO.setBit(m); -// vz = vz.setBit(0); -// vz = vz.setBit(this.k1); -// if (this.representation == PPB) -// { -// vz = vz.setBit(this.k2); -// vz = vz.setBit(this.k3); -// } -// -// // g1(z) := 1, g2(z) := 0 -// BigInteger g1z = ECConstants.ONE; -// BigInteger g2z = ECConstants.ZERO; -// -// // while u != 1 -// while (!(uz.equals(ECConstants.ZERO))) -// { -// // j := deg(u(z)) - deg(v(z)) -// int j = uz.bitLength() - vz.bitLength(); -// -// // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j -// if (j < 0) -// { -// final BigInteger uzCopy = uz; -// uz = vz; -// vz = uzCopy; -// -// final BigInteger g1zCopy = g1z; -// g1z = g2z; -// g2z = g1zCopy; -// -// j = -j; -// } -// -// // u(z) := u(z) + z^j * v(z) -// // Note, that no reduction modulo f(z) is required, because -// // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) -// // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) -// // = deg(u(z)) -// uz = uz.xor(vz.shiftLeft(j)); -// -// // g1(z) := g1(z) + z^j * g2(z) -// g1z = g1z.xor(g2z.shiftLeft(j)); -//// if (g1z.bitLength() > this.m) { -//// throw new ArithmeticException( -//// "deg(g1z) >= m, g1z = " + g1z.toString(2)); -//// } -// } -// return new ECFieldElement.F2m( -// this.m, this.k1, this.k2, this.k3, g2z); -// } -// -// public ECFieldElement sqrt() -// { -// throw new RuntimeException("Not implemented"); -// } -// -// /** -// * @return the representation of the field -// * <code>F<sub>2<sup>m</sup></sub></code>, either of -// * TPB (trinomial -// * basis representation) or -// * PPB (pentanomial -// * basis representation). -// */ -// public int getRepresentation() -// { -// return this.representation; -// } -// -// /** -// * @return the degree <code>m</code> of the reduction polynomial -// * <code>f(z)</code>. -// */ -// public int getM() -// { -// return this.m; -// } -// -// /** -// * @return 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> -// */ -// public int getK1() -// { -// return this.k1; -// } -// -// /** -// * @return TPB: Always returns <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> -// */ -// public int getK2() -// { -// return this.k2; -// } -// -// /** -// * @return 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> -// */ -// public int getK3() -// { -// return this.k3; -// } -// -// public boolean equals(Object anObject) -// { -// if (anObject == this) -// { -// return true; -// } -// -// if (!(anObject instanceof ECFieldElement.F2m)) -// { -// return false; -// } -// -// ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; -// -// return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2) -// && (this.k3 == b.k3) -// && (this.representation == b.representation) -// && (this.x.equals(b.x))); -// } -// -// public int hashCode() -// { -// return x.hashCode() ^ m ^ k1 ^ k2 ^ k3; -// } -// } -} diff --git a/src/org/bouncycastle/math/ec/ECMultiplier.java b/src/org/bouncycastle/math/ec/ECMultiplier.java deleted file mode 100644 index 4d72e33..0000000 --- a/src/org/bouncycastle/math/ec/ECMultiplier.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.bouncycastle.math.ec; - -import java.math.BigInteger; - -/** - * Interface for classes encapsulating a point multiplication algorithm - * for <code>ECPoint</code>s. - */ -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); -} diff --git a/src/org/bouncycastle/math/ec/ECPoint.java b/src/org/bouncycastle/math/ec/ECPoint.java deleted file mode 100644 index f4056bb..0000000 --- a/src/org/bouncycastle/math/ec/ECPoint.java +++ /dev/null @@ -1,335 +0,0 @@ -package org.bouncycastle.math.ec; - -import java.math.BigInteger; - -/** - * base class for points on elliptic curves. - */ -public abstract class ECPoint -{ - ECCurve curve; - ECFieldElement x; - ECFieldElement y; - - protected boolean withCompression; - - protected ECMultiplier multiplier = null; - - protected PreCompInfo preCompInfo = null; - -// private static X9IntegerConverter converter = new X9IntegerConverter(); - - protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y) - { - this.curve = curve; - this.x = x; - this.y = y; - } - - public ECCurve getCurve() - { - return curve; - } - - public ECFieldElement getX() - { - return x; - } - - public ECFieldElement getY() - { - return y; - } - - public boolean isInfinity() - { - return x == null && y == null; - } - - public boolean isCompressed() - { - return withCompression; - } - - @Override - public boolean equals( - Object other) - { - if (other == this) - { - return true; - } - - if (!(other instanceof ECPoint)) - { - return false; - } - - ECPoint o = (ECPoint)other; - - if (this.isInfinity()) - { - return o.isInfinity(); - } - - return x.equals(o.x) && y.equals(o.y); - } - - @Override - public int hashCode() - { - if (this.isInfinity()) - { - return 0; - } - - return x.hashCode() ^ y.hashCode(); - } - -// /** -// * Mainly for testing. Explicitly set the <code>ECMultiplier</code>. -// * @param multiplier The <code>ECMultiplier</code> to be used to multiply -// * this <code>ECPoint</code>. -// */ -// public 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>. - */ - 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(); - - /** - * Sets the default <code>ECMultiplier</code>, unless already set. - */ - synchronized void assertECMultiplier() - { - if (this.multiplier == null) - { - this.multiplier = new FpNafMultiplier(); - } - } - - /** - * Multiplies this <code>ECPoint</code> by the given number. - * @param k The multiplicator. - * @return <code>k * this</code>. - */ - public ECPoint multiply(BigInteger k) - { - if (k.signum() < 0) - { - throw new IllegalArgumentException("The multiplicator cannot be negative"); - } - - if (this.isInfinity()) - { - return this; - } - - if (k.signum() == 0) - { - return this.curve.getInfinity(); - } - - assertECMultiplier(); - return this.multiplier.multiply(this, k, preCompInfo); - } - - /** - * Elliptic curve points over Fp - */ - public static class Fp extends ECPoint - { - - /** - * 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 Fp(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 Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) - { - super(curve, x, y); - - if ((x != null && y == null) || (x == null && y != null)) - { - throw new IllegalArgumentException("Exactly one of the field elements is null"); - } - - this.withCompression = withCompression; - } - - /** - * return the field element encoded with point compression. (S 4.3.6) - */ - public byte[] getEncoded() - { - return null; - // BEGIN connectbot-removed -// if (this.isInfinity()) -// { -// return new byte[1]; -// } -// -// int qLength = converter.getByteLength(x); -// -// if (withCompression) -// { -// byte PC; -// -// if (this.getY().toBigInteger().testBit(0)) -// { -// PC = 0x03; -// } -// else -// { -// PC = 0x02; -// } -// -// byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); -// byte[] PO = new byte[X.length + 1]; -// -// PO[0] = PC; -// System.arraycopy(X, 0, PO, 1, X.length); -// -// return PO; -// } -// else -// { -// byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); -// byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength); -// byte[] PO = new byte[X.length + Y.length + 1]; -// -// PO[0] = 0x04; -// System.arraycopy(X, 0, PO, 1, X.length); -// System.arraycopy(Y, 0, PO, X.length + 1, Y.length); -// -// return PO; -// } - } - - // B.3 pg 62 - @Override - public 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(); - } - - // this = -b, i.e. the result is the point at infinity - return this.curve.getInfinity(); - } - - 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 ECPoint.Fp(curve, x3, y3); - } - - // B.3 pg 62 - @Override - public ECPoint twice() - { - if (this.isInfinity()) - { - // Twice identity element (point at infinity) is identity - return this; - } - - if (this.y.toBigInteger().signum() == 0) - { - // if y1 == 0, then (x1, y1) == (x1, -y1) - // and hence this = -this and thus 2(x1, y1) == infinity - return this.curve.getInfinity(); - } - - ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2)); - ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3)); - 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 ECPoint.Fp(curve, x3, y3, this.withCompression); - } - - // D.3.2 pg 102 (see Note:) - @Override - public ECPoint subtract(ECPoint b) - { - if (b.isInfinity()) - { - return this; - } - - // Add -b - return add(b.negate()); - } - - @Override - public ECPoint negate() - { - return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression); - } - - /** - * Sets the default <code>ECMultiplier</code>, unless already set. - */ - @Override - synchronized void assertECMultiplier() - { - if (this.multiplier == null) - { - this.multiplier = new WNafMultiplier(); - } - } - } -} diff --git a/src/org/bouncycastle/math/ec/FpNafMultiplier.java b/src/org/bouncycastle/math/ec/FpNafMultiplier.java deleted file mode 100644 index 35e601d..0000000 --- a/src/org/bouncycastle/math/ec/FpNafMultiplier.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.bouncycastle.math.ec; - -import java.math.BigInteger; - -/** - * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm. - */ -class FpNafMultiplier implements ECMultiplier -{ - /** - * D.3.2 pg 101 - * @see org.bouncycastle.math.ec.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.valueOf(3)); - - ECPoint neg = p.negate(); - ECPoint R = p; - - for (int i = h.bitLength() - 2; i > 0; --i) - { - R = R.twice(); - - boolean hBit = h.testBit(i); - boolean eBit = e.testBit(i); - - if (hBit != eBit) - { - R = R.add(hBit ? p : neg); - } - } - - return R; - } -} diff --git a/src/org/bouncycastle/math/ec/PreCompInfo.java b/src/org/bouncycastle/math/ec/PreCompInfo.java deleted file mode 100644 index 804dcf7..0000000 --- a/src/org/bouncycastle/math/ec/PreCompInfo.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.bouncycastle.math.ec; - -/** - * Interface for classes storing precomputation data for multiplication - * algorithms. Used as a Memento (see GOF patterns) for - * <code>WNafMultiplier</code>. - */ -interface PreCompInfo -{ -} diff --git a/src/org/bouncycastle/math/ec/WNafMultiplier.java b/src/org/bouncycastle/math/ec/WNafMultiplier.java deleted file mode 100644 index 10c8ed2..0000000 --- a/src/org/bouncycastle/math/ec/WNafMultiplier.java +++ /dev/null @@ -1,240 +0,0 @@ -package org.bouncycastle.math.ec; - -import java.math.BigInteger; - -/** - * Class implementing the WNAF (Window Non-Adjacent Form) multiplication - * algorithm. - */ -class WNafMultiplier implements 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>byte[]</code>. - */ - public byte[] windowNaf(byte width, BigInteger k) - { - // The window NAF is at most 1 element longer than the binary - // representation of the integer k. byte 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. - byte[] wnaf = new byte[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.signum() > 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] = (byte)(remainder.intValue() - pow2wB); - } - else - { - wnaf[i] = (byte)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 - byte[] wnafShort = new byte[length]; - System.arraycopy(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 instanceof 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 - byte 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]; - System.arraycopy(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 - byte[] wnaf = windowNaf(width, k); - int l = wnaf.length; - - // Apply the Window NAF to p using the precomputed ECPoint values. - ECPoint q = p.getCurve().getInfinity(); - 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; - } - -} diff --git a/src/org/bouncycastle/math/ec/WNafPreCompInfo.java b/src/org/bouncycastle/math/ec/WNafPreCompInfo.java deleted file mode 100644 index fc0d5fe..0000000 --- a/src/org/bouncycastle/math/ec/WNafPreCompInfo.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.bouncycastle.math.ec; - -/** - * Class holding precomputation data for the WNAF (Window Non-Adjacent Form) - * algorithm. - */ -class WNafPreCompInfo implements 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; - - protected ECPoint[] getPreComp() - { - return preComp; - } - - protected void setPreComp(ECPoint[] preComp) - { - this.preComp = preComp; - } - - protected ECPoint getTwiceP() - { - return twiceP; - } - - protected void setTwiceP(ECPoint twiceThis) - { - this.twiceP = twiceThis; - } -} diff --git a/src/org/connectbot/util/PubkeyUtils.java b/src/org/connectbot/util/PubkeyUtils.java index c214fc7..b9e97ab 100644 --- a/src/org/connectbot/util/PubkeyUtils.java +++ b/src/org/connectbot/util/PubkeyUtils.java @@ -38,11 +38,9 @@ import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.DSAPublicKeySpec; -import java.security.spec.ECField; -import java.security.spec.ECFieldFp; import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; import java.security.spec.ECPublicKeySpec; -import java.security.spec.EllipticCurve; import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; @@ -61,8 +59,7 @@ import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import javax.crypto.spec.SecretKeySpec; -import org.bouncycastle.math.ec.ECCurve; -import org.bouncycastle.math.ec.ECPoint; +import org.keyczar.jce.EcCore; import android.util.Log; @@ -204,17 +201,14 @@ public class PubkeyUtils { ECParameterSpec params = ((ECPrivateKey) priv).getParams(); // Calculate public key Y - EllipticCurve curve = params.getCurve(); - ECField field = curve.getField(); - ECCurve bcCurve = new ECCurve.Fp(((ECFieldFp)field).getP(), curve.getA(), curve.getB()); - java.security.spec.ECPoint generator = params.getGenerator(); - ECPoint bcGenerator = bcCurve.createPoint(generator.getAffineX(), generator.getAffineY(), false); - ECPoint w = bcGenerator.multiply(((ECPrivateKey) priv).getS()); - - pubKeySpec = new ECPublicKeySpec( - new java.security.spec.ECPoint(w.getX().toBigInteger(), - w.getY().toBigInteger()), - params); + ECPoint generator = params.getGenerator(); + BigInteger[] wCoords = EcCore.multiplyPoint(new BigInteger[] { + generator.getAffineX(), + generator.getAffineY() }, + ((ECPrivateKey) priv).getS(), params); + ECPoint w = new ECPoint(wCoords[0], wCoords[1]); + + pubKeySpec = new ECPublicKeySpec(w, params); pub = kf.generatePublic(pubKeySpec); } diff --git a/src/org/keyczar/jce/EcCore.java b/src/org/keyczar/jce/EcCore.java new file mode 100644 index 0000000..c8ff7da --- /dev/null +++ b/src/org/keyczar/jce/EcCore.java @@ -0,0 +1,677 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.keyczar.jce; + +import java.math.BigInteger; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; + +/** + * This class implements the basic EC operations such as point addition and + * doubling and point multiplication. Only NSA Suite B / NIST curves are + * supported. + * + * Todo: + * - Add (more) comments - Performance optimizations - Cleanup ASN.1 code, + * possibly replace with own impl - ... + * + * References: + * + * [1] Software Implementation of the NIST Elliptic Curves Over Prime Fields, M. + * Brown et al. [2] Efficient elliptic curve exponentiation using mixed + * coordinates, H. Cohen et al. [3] SEC 1: Elliptic Curve Cryptography. [4] + * Guide to Elliptic Curve Cryptography, D. Hankerson et al., Springer. + * + * @author martclau@gmail.com + * + */ +// BEGIN connectbot-changed +public final class EcCore { +// END connectbot-changed +// BEGIN connectbot-removed +// private static final long serialVersionUID = -1376116429660095993L; +// +// private static final String INFO = "Google Keyczar (EC key/parameter generation; EC signing)"; +// +// public static final String NAME = "GooKey"; +// +// @SuppressWarnings("unchecked") +// public EcCore() { +// super(NAME, 0.1, INFO); +// AccessController.doPrivileged(new PrivilegedAction<Object>() { +// @Override +// public Object run() { +// put("Signature.SHA1withECDSA", "org.keyczar.jce.EcSignatureImpl$SHA1"); +// put("Alg.Alias.Signature.ECDSA", "SHA1withDSA"); +// put("Signature.SHA256withECDSA", +// "org.keyczar.jce.EcSignatureImpl$SHA256"); +// put("Signature.SHA384withECDSA", +// "org.keyczar.jce.EcSignatureImpl$SHA384"); +// put("Signature.SHA512withECDSA", +// "org.keyczar.jce.EcSignatureImpl$SHA512"); +// put("KeyPairGenerator.EC", "org.keyczar.jce.EcKeyPairGeneratorImpl"); +// put("KeyFactory.EC", "org.keyczar.jce.EcKeyFactoryImpl"); +// put("Signature.SHA1withECDSA KeySize", "521"); +// put("Signature.SHA1withECDSA ImplementedIn", "Software"); +// put("Signature.SHA256withECDSA KeySize", "521"); +// put("Signature.SHA256withECDSA ImplementedIn", "Software"); +// put("Signature.SHA384withECDSA KeySize", "521"); +// put("Signature.SHA384withECDSA ImplementedIn", "Software"); +// put("Signature.SHA512withECDSA KeySize", "521"); +// put("Signature.SHA512withECDSA ImplementedIn", "Software"); +// put("KeyPairGenerator.EC ImplementedIn", "Software"); +// put("KeyFactory.EC ImplementedIn", "Software"); +// return null; +// } +// }); +// } +// +// private static final ECParameterSpec P192 = new ECParameterSpec( +// new EllipticCurve( +// new ECFieldFp(new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16)), +// new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", 16), +// new BigInteger("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", 16)), +// new ECPoint( +// new BigInteger("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", 16), +// new BigInteger("07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", 16)), +// new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 16), 1); +// +// private static final ECParameterSpec P224 = new ECParameterSpec( +// new EllipticCurve(new ECFieldFp(new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", 16)), +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", 16), +// new BigInteger( +// "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", 16)), +// new ECPoint(new BigInteger( +// "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", 16), +// new BigInteger( +// "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", 16)), +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 16), 1); +// +// private static final ECParameterSpec P256 = new ECParameterSpec( +// new EllipticCurve(new ECFieldFp(new BigInteger( +// "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", +// 16)), new BigInteger( +// "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", +// 16), new BigInteger( +// "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", +// 16)), new ECPoint(new BigInteger( +// "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", +// 16), new BigInteger( +// "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", +// 16)), new BigInteger( +// "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", +// 16), 1); +// +// private static final ECParameterSpec P384 = new ECParameterSpec( +// new EllipticCurve( +// new ECFieldFp( +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", +// 16)), +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", +// 16), +// new BigInteger( +// "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", +// 16)), +// new ECPoint( +// new BigInteger( +// "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", +// 16), +// new BigInteger( +// "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", +// 16)), +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", +// 16), 1); +// +// private static final ECParameterSpec P521 = new ECParameterSpec( +// new EllipticCurve( +// new ECFieldFp( +// new BigInteger( +// "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", +// 16)), +// new BigInteger( +// "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", +// 16), +// new BigInteger( +// "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", +// 16)), +// new ECPoint( +// new BigInteger( +// "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", +// 16), +// new BigInteger( +// "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", +// 16)), +// new BigInteger( +// "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", +// 16), 1); +// +// public static final String EC_PARAMS_P192_OID = "1.2.840.10045.3.1.1"; +// public static final String EC_PARAMS_P224_OID = "1.3.132.0.33"; +// public static final String EC_PARAMS_P256_OID = "1.2.840.10045.3.1.7"; +// public static final String EC_PARAMS_P384_OID = "1.3.132.0.34"; +// public static final String EC_PARAMS_P521_OID = "1.3.132.0.35"; +// +// private static Map<String, ECParameterSpec> oidMap = new HashMap<String, ECParameterSpec>(); +// private static Map<ECParameterSpec, String> paramsMap = new HashMap<ECParameterSpec, String>(); +// private static Map<ECParameterSpec, String> friendlyNameMap = new HashMap<ECParameterSpec, String>(); +// +// static { +// oidMap.put(EC_PARAMS_P192_OID, P192); +// oidMap.put(EC_PARAMS_P224_OID, P224); +// oidMap.put(EC_PARAMS_P256_OID, P256); +// oidMap.put(EC_PARAMS_P384_OID, P384); +// oidMap.put(EC_PARAMS_P521_OID, P521); +// paramsMap.put(P192, EC_PARAMS_P192_OID); +// paramsMap.put(P224, EC_PARAMS_P224_OID); +// paramsMap.put(P256, EC_PARAMS_P256_OID); +// paramsMap.put(P384, EC_PARAMS_P384_OID); +// paramsMap.put(P521, EC_PARAMS_P521_OID); +// friendlyNameMap.put(P192, "P-192"); +// friendlyNameMap.put(P224, "P-224"); +// friendlyNameMap.put(P256, "P-256"); +// friendlyNameMap.put(P384, "P-384"); +// friendlyNameMap.put(P521, "P-521"); +// } +// +// public static ECParameterSpec getParams(String oid) { +// ECParameterSpec params; +// if ((params = oidMap.get(oid)) != null) return params; +// throw new IllegalArgumentException("Unsupported EC parameters: " + oid); +// } +// +// public static String getOID(ECParameterSpec params) { +// String oid; +// if ((oid = paramsMap.get(params)) != null) return oid; +// throw new IllegalArgumentException("Unsupport EC parameters"); +// } +// +// public static String getFriendlyName(ECParameterSpec params) { +// String name; +// if ((name = friendlyNameMap.get(params)) != null) return name; +// throw new IllegalArgumentException("Unsupport EC parameters"); +// } +// +// private static final BigInteger ZERO = BigInteger.ZERO; +// END connectbot-removed + private static final BigInteger ONE = BigInteger.ONE; + private static final BigInteger TWO = BigInteger.valueOf(2); + private static final BigInteger THREE = BigInteger.valueOf(3); + private static final BigInteger FOUR = BigInteger.valueOf(4); + private static final BigInteger EIGHT = BigInteger.valueOf(8); + +// private static BigInteger[] doublePointA(BigInteger[] P, +// ECParameterSpec params) { +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// final BigInteger a = params.getCurve().getA(); +// +// if (P[0] == null || P[1] == null) return P; +// +// BigInteger d = (P[0].pow(2).multiply(THREE).add(a)).multiply(P[1] +// .shiftLeft(1).modInverse(p)); +// BigInteger[] R = new BigInteger[2]; +// R[0] = d.pow(2).subtract(P[0].shiftLeft(1)).mod(p); +// R[1] = d.multiply(P[0].subtract(R[0])).subtract(P[1]).mod(p); +// +// return R; +// } +// +// private static BigInteger[] addPointsA(BigInteger[] P1, BigInteger[] P2, +// ECParameterSpec params) { +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// +// if (P2[0] == null || P2[1] == null) return P1; +// +// if (P1[0] == null || P1[1] == null) return P2; +// +// BigInteger d = (P2[1].subtract(P1[1])).multiply((P2[0].subtract(P1[0])) +// .modInverse(p)); +// BigInteger[] R = new BigInteger[2]; +// R[0] = d.pow(2).subtract(P1[0]).subtract(P2[0]).mod(p); +// R[1] = d.multiply(P1[0].subtract(R[0])).subtract(P1[1]).mod(p); +// +// return R; +// } +// +// private static BigInteger[] multiplyPointA(BigInteger[] P, BigInteger k, +// ECParameterSpec params) { +// BigInteger[] Q = new BigInteger[] {null, null}; +// +// for (int i = k.bitLength() - 1; i >= 0; i--) { +// Q = doublePointA(Q, params); +// if (k.testBit(i)) Q = addPointsA(Q, P, params); +// } +// +// return Q; +// } +// END connectbot-removed + + private static BigInteger[] doublePointJ(BigInteger[] P, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + BigInteger A, B, C, D; + + if (P[2].signum() == 0) // point at inf + return P; + + A = FOUR.multiply(P[0]).multiply(P[1].pow(2)).mod(p); + B = EIGHT.multiply(P[1].pow(4)).mod(p); + C = THREE.multiply(P[0].subtract(P[2].pow(2))).multiply( + P[0].add(P[2].pow(2))).mod(p); + D = C.pow(2).subtract(A.add(A)).mod(p); + + return new BigInteger[] { + D, C.multiply(A.subtract(D)).subtract(B).mod(p), + TWO.multiply(P[1]).multiply(P[2]).mod(p)}; + } + + private static BigInteger[] addPointsJA(BigInteger[] P1, BigInteger[] P2, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + BigInteger A, B, C, D; + BigInteger X3; + + if (P1[2].signum() == 0) // point at inf + return new BigInteger[] {P2[0], P2[1], ONE}; + + A = P2[0].multiply(P1[2].pow(2)).mod(p); + B = P2[1].multiply(P1[2].pow(3)).mod(p); + C = A.subtract(P1[0]).mod(p); + D = B.subtract(P1[1]).mod(p); + + X3 = D.pow(2) + .subtract(C.pow(3).add(TWO.multiply(P1[0]).multiply(C.pow(2)))).mod(p); + return new BigInteger[] { + X3, + D.multiply(P1[0].multiply(C.pow(2)).subtract(X3)).subtract( + P1[1].multiply(C.pow(3))).mod(p), P1[2].multiply(C).mod(p)}; + } + + // Binary NAF method for point multiplication + public static BigInteger[] multiplyPoint(BigInteger[] P, BigInteger k, + ECParameterSpec params) { + BigInteger h = THREE.multiply(k); + + BigInteger[] Pneg = new BigInteger[] {P[0], P[1].negate()}; + BigInteger[] R = new BigInteger[] {P[0], P[1], ONE}; + + int bitLen = h.bitLength(); + for (int i = bitLen - 2; i > 0; --i) { + R = doublePointJ(R, params); + if (h.testBit(i)) R = addPointsJA(R, P, params); + if (k.testBit(i)) R = addPointsJA(R, Pneg, params); + } + + // // <DEBUG> + // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; + // toAffine(SS, params); + // BigInteger[] RR = multiplyPointA(P, k, params); + // if (!SS[0].equals(RR[0]) || !SS[1].equals(RR[1])) + // throw new RuntimeException("Internal mult error"); + // // </DEBUG> + + return R; + } + +// // Simultaneous multiple point multiplication, also known as Shamir's trick +// static BigInteger[] multiplyPoints(BigInteger[] P, BigInteger k, +// BigInteger[] Q, BigInteger l, ECParameterSpec params) { +// BigInteger[] PQ = addPointsA(P, Q, params); +// BigInteger[] R = new BigInteger[] {null, null, ZERO}; +// +// int max = Math.max(k.bitLength(), l.bitLength()); +// for (int i = max - 1; i >= 0; --i) { +// R = doublePointJ(R, params); +// if (k.testBit(i)) { +// if (l.testBit(i)) +// R = addPointsJA(R, PQ, params); +// else +// R = addPointsJA(R, P, params); +// } else if (l.testBit(i)) R = addPointsJA(R, Q, params); +// } +// +// // // <DEBUG> +// // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; +// // toAffine(SS, params); +// // BigInteger[] AA = multiplyPointA(P, k, params); +// // BigInteger[] BB = multiplyPointA(Q, l, params); +// // BigInteger[] AB = addPointsA(AA, BB, params); +// // if (!SS[0].equals(AB[0]) || !SS[1].equals(AB[1])) +// // throw new RuntimeException("Internal mult error"); +// // // </DEBUG> +// +// return R; +// } +// +// // SEC 1, 2.3.5 +// static byte[] fieldElemToBytes(BigInteger a, ECParameterSpec params) { +// int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; +// byte[] bytes = a.toByteArray(); +// if (len < bytes.length) { +// byte[] tmp = new byte[len]; +// System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length); +// return tmp; +// } else if (len > bytes.length) { +// byte[] tmp = new byte[len]; +// System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length); +// return tmp; +// } +// return bytes; +// } +// +// static int fieldElemToBytes(BigInteger a, ECParameterSpec params, +// byte[] data, int off) { +// int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; +// byte[] bytes = a.toByteArray(); +// if (len < bytes.length) { +// System.arraycopy(bytes, bytes.length - len, data, off, len); +// return len; +// } else if (len > bytes.length) { +// System.arraycopy(bytes, 0, data, len - bytes.length + off, bytes.length); +// return len; +// } +// System.arraycopy(bytes, 0, data, off, bytes.length); +// return bytes.length; +// } +// +// // SEC 1, 2.3.3 +// static byte[] ecPointToBytes(ECPoint a, ECParameterSpec params) { +// byte[] fe1 = fieldElemToBytes(a.getAffineX(), params); +// byte[] fe2 = fieldElemToBytes(a.getAffineY(), params); +// byte[] bytes = new byte[1 + fe1.length + fe2.length]; +// bytes[0] = 0x04; +// System.arraycopy(fe1, 0, bytes, 1, fe1.length); +// System.arraycopy(fe2, 0, bytes, 1 + fe1.length, fe2.length); +// return bytes; +// } +// +// // SEC 1, 2.3.4 +// static ECPoint bytesToECPoint(byte[] bytes, ECParameterSpec params) { +// switch (bytes[0]) { +// case 0x00: // point at inf +// throw new IllegalArgumentException( +// "Point at infinity is not a valid argument"); +// case 0x02: // point compression +// case 0x03: +// throw new UnsupportedOperationException( +// "Point compression is not supported"); +// case 0x04: +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// byte[] fe = new byte[(p.bitLength() + 7) / 8]; +// System.arraycopy(bytes, 1, fe, 0, fe.length); +// BigInteger x = new BigInteger(1, fe); +// System.arraycopy(bytes, 1 + fe.length, fe, 0, fe.length); +// return new ECPoint(x, new BigInteger(1, fe)); +// default: +// throw new IllegalArgumentException("Invalid point encoding"); +// } +// } +// +// // Convert Jacobian point to affine +// static void toAffine(BigInteger[] P, ECParameterSpec params) { +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); +// P[1] = P[1].multiply(P[2].pow(3).modInverse(p)).mod(p); +// } +// +// static void toAffineX(BigInteger[] P, ECParameterSpec params) { +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); +// } +// +// static BigInteger[] internalPoint(ECPoint P) { +// return new BigInteger[] {P.getAffineX(), P.getAffineY()}; +// } +// +// // private static void printPerf(String msg, long start, long stop) { +// // String unit = "ms"; +// // long diff = stop - start; +// // if (diff > 1000) { +// // diff /= 1000; +// // unit = "s"; +// // } +// // System.out.printf("%s: %d %s\n", msg, diff, unit); +// // } +// +// public static void main(String[] args) throws Exception { +// +// Security.insertProviderAt(new EcCore(), 0); +// +// // ---- +// // Test primitives +// // ---- +// +// // GooKey EC private key, 256 bit +// // Private value: +// // a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2 +// // Parameters: P-256 (1.2.840.10045.3.1.7) +// // GooKey EC public key, 256 bit +// // Public value (x coordinate): +// // 86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c +// // Public value (y coordinate): +// // ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6 +// // Parameters: P-256 (1.2.840.10045.3.1.7) +// // GooKey EC private key, 256 bit +// // Private value: +// // b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022 +// // Parameters: P-256 (1.2.840.10045.3.1.7) +// // GooKey EC public key, 256 bit +// // Public value (x coordinate): +// // 61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1 +// // Public value (y coordinate): +// // 3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705 +// // Parameters: P-256 (1.2.840.10045.3.1.7) +// +// // P = kG +// BigInteger k = new BigInteger( +// "a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2", 16); +// BigInteger[] P = new BigInteger[] { +// new BigInteger( +// "86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c", +// 16), +// new BigInteger( +// "ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6", +// 16), ONE}; +// +// // Q = lG +// BigInteger l = new BigInteger( +// "b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022", 16); +// BigInteger[] Q = new BigInteger[] { +// new BigInteger( +// "61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1", +// 16), +// new BigInteger( +// "3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705", +// 16), ONE}; +// +// // Known answer for P+Q +// BigInteger[] kat1 = new BigInteger[] { +// new BigInteger( +// "bc7adb05bca2460bbfeb4e0f88b61c384ea88ed3fd56017938ac2582513d4220", +// 16), +// new BigInteger( +// "a640a43df2e9df39eec11445b7e3f7835b743ef1ac4a83cecb570a060b3f1c6c", +// 16)}; +// +// BigInteger[] R = addPointsA(P, Q, P256); +// if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) +// throw new RuntimeException("kat1 failed"); +// +// R = addPointsJA(P, Q, P256); +// toAffine(R, P256); +// if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) +// throw new RuntimeException("kat1 failed"); +// +// +// // Known answer for Q+Q +// BigInteger[] kat2 = new BigInteger[] { +// new BigInteger( +// "c79d7f9100c14a70f0bb9bdce59654abf99e10d1ac5afc1a0f1b6bc650d6429b", +// 16), +// new BigInteger( +// "6856814e47adce42bc0d7c3bef308c6c737c418ed093effb31e21f53c7735c97", +// 16)}; +// +// R = doublePointA(P, P256); +// if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) +// throw new RuntimeException("kat2 failed"); +// +// R = doublePointJ(P, P256); +// toAffine(R, P256); +// if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) +// throw new RuntimeException("kat2 failed"); +// +// // Known answer for kP +// BigInteger[] kat3 = new BigInteger[] { +// new BigInteger( +// "97a82a834b9e6b50660ae30d43dac9b200276e8bcd2ed6a6593048de09276d1a", +// 16), +// new BigInteger( +// "30a9590a01066d8ef54a910afcc8648dbc7400c01750af423ce95547f2154d56", +// 16)}; +// +// R = multiplyPointA(P, k, P256); +// if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) +// throw new RuntimeException("kat3 failed"); +// +// R = multiplyPoint(P, k, P256); +// toAffine(R, P256); +// if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) +// throw new RuntimeException("kat3 failed"); +// +// // Known answer for kP+lQ +// BigInteger[] kat4 = new BigInteger[] { +// new BigInteger( +// "6fd51be5cf3d6a6bcb62594bbe41ccf549b37d8fefff6e293a5bea0836efcfc6", +// 16), +// new BigInteger( +// "9bc21a930137aa3814908974c431e4545a05dce61321253c337f3883129c42ca", +// 16)}; +// +// BigInteger[] RR = multiplyPointA(Q, l, P256); +// R = addPointsA(R, RR, P256); +// if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) +// throw new RuntimeException("kat4 failed"); +// +// R = multiplyPoints(P, k, Q, l, P256); +// toAffine(R, P256); +// if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) +// throw new RuntimeException("kat4 failed"); +// +// // ---- +// // Test ECDSA in various combinations +// // ---- +// +// Provider gooProv = Security.getProvider("GooKey"); +// Provider nssProv = Security.getProvider("SunPKCS11-NSS"); +// +// // Number of iterations: trust me, this is a (stress) good test +// // and does provoke bugs in a fuzzing way. +// int iter = 50; +// +// // Iterate over all key lengths and signature schemes. +// int[] keyLengths = {192, 224, 256, 384, 521}; +// String[] ecdsas = { +// "SHA1withECDSA", "SHA256withECDSA", "SHA384withECDSA", +// "SHA512withECDSA"}; +// for (int s = 0; s < ecdsas.length; s++) { +// System.out.println("Signature scheme " + ecdsas[s]); +// for (int i = 0; i < keyLengths.length; i++) { +// System.out.print("Testing P-" + keyLengths[i] + ": "); +// for (int n = 0; n < iter; n++) { +// System.out.print("."); +// +// KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", gooProv); +// kpGen.initialize(keyLengths[i]); +// KeyPair ecKeyPair = kpGen.generateKeyPair(); +// +// ECPrivateKey ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); +// byte[] tmp = ecPrivKey.getEncoded(); +// KeyFactory keyFab = KeyFactory.getInstance("EC", gooProv); +// keyFab.generatePrivate(new PKCS8EncodedKeySpec(tmp)); +// ECPrivateKeySpec ecPrivSpec = new ECPrivateKeySpec(ecPrivKey.getS(), +// ecPrivKey.getParams()); +// keyFab.generatePrivate(ecPrivSpec); +// +// ECPublicKey ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); +// tmp = ecPubKey.getEncoded(); // dont modify tmp now - is used below +// keyFab.generatePublic(new X509EncodedKeySpec(tmp)); +// ECPublicKeySpec ecPubSpec = new ECPublicKeySpec(ecPubKey.getW(), +// ecPubKey.getParams()); +// keyFab.generatePublic(ecPubSpec); +// +// Signature ecdsa = Signature.getInstance(ecdsas[s], gooProv); +// ecdsa.initSign(ecPrivKey); +// ecdsa.update(tmp); +// byte[] sig = ecdsa.sign(); +// ecdsa.initVerify(ecPubKey); +// ecdsa.update(tmp); +// if (!ecdsa.verify(sig)) +// throw new RuntimeException("Signature not verified: " +// + keyLengths[i]); +// +// // Cross verify using NSS if present +// if (nssProv != null) { +// keyFab = KeyFactory.getInstance("EC", nssProv); +// +// // For some reason NSS doesnt seem to work for P-192 and P-224?! +// if (keyLengths[i] == 192 || keyLengths[i] == 224) continue; +// +// ECPrivateKey nssPrivKey = (ECPrivateKey) keyFab +// .generatePrivate(new PKCS8EncodedKeySpec(ecPrivKey.getEncoded())); +// ECPublicKey nssPubKey = (ECPublicKey) keyFab +// .generatePublic(new X509EncodedKeySpec(ecPubKey.getEncoded())); +// +// ecdsa = Signature.getInstance(ecdsas[s], nssProv); +// ecdsa.initVerify(nssPubKey); +// ecdsa.update(tmp); +// if (!ecdsa.verify(sig)) +// throw new RuntimeException("Signature not verified 2: " +// + keyLengths[i]); +// +// ecdsa.initSign(nssPrivKey); +// ecdsa.update(tmp); +// sig = ecdsa.sign(); +// ecdsa = Signature.getInstance(ecdsas[s], gooProv); +// ecdsa.initVerify(ecPubKey); +// ecdsa.update(tmp); +// if (!ecdsa.verify(sig)) +// throw new RuntimeException("Signature not verified 3: " +// + keyLengths[i]); +// } +// } +// System.out.println(" done"); +// } +// } +// +// // Test Keyczar integration +// // Signer ecdsaSigner = new Signer("c:\\temp\\eckeyset"); +// // String tbs = "Sign this"; +// // String sig = ecdsaSigner.sign(tbs); +// // if (ecdsaSigner.verify(sig, tbs)) +// // System.out.println("Keyczar EC OK"); +// // else +// // System.out.println("Keyczar EC not OK"); +// } +//END connectbot-removed +} |