diff src/org/keyczar/jce/EcCore.java @ 0:0ce5cc452d02

initial version
author Carl Byington <carl@five-ten-sg.com>
date Thu, 22 May 2014 10:41:19 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/keyczar/jce/EcCore.java	Thu May 22 10:41:19 2014 -0700
@@ -0,0 +1,678 @@
+/*
+ * 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;
+//  private static final BigInteger ONE = BigInteger.ONE;
+//  private static final BigInteger TWO = BigInteger.valueOf(2);
+// END connectbot-removed
+    private static final BigInteger THREE = BigInteger.valueOf(3);
+// BEGIN connectbot-removed
+//  private static final BigInteger FOUR = BigInteger.valueOf(4);
+//  private static final BigInteger EIGHT = BigInteger.valueOf(8);
+// END connectbot-removed
+
+    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;
+    }
+
+    public 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;
+    }
+
+// BEGIN 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
+}