1a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrompackage org.bouncycastle.jcajce.provider.asymmetric.util;
28212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
38212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.math.BigInteger;
48212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.ECField;
58212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.ECFieldF2m;
68212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.ECFieldFp;
78212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.ECParameterSpec;
88212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.ECPoint;
98212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.security.spec.EllipticCurve;
10d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport java.util.Enumeration;
11d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport java.util.HashMap;
12d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport java.util.Map;
138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
14d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.asn1.x9.ECNamedCurveTable;
15d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.asn1.x9.X9ECParameters;
16d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.crypto.ec.CustomNamedCurves;
178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.jce.spec.ECNamedCurveSpec;
19d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.ec.ECAlgorithms;
208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.math.ec.ECCurve;
218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompublic class EC5Util
238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom{
24d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    private static Map customCurves = new HashMap();
25d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
26d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    static
27d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
28d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        Enumeration e = CustomNamedCurves.getNames();
29d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        while (e.hasMoreElements())
30d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
31d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            String name = (String)e.nextElement();
32d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
33d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            X9ECParameters curveParams = ECNamedCurveTable.getByName(name);
34d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            if (curveParams != null)  // there may not be a regular curve, may just be a custom curve.
35d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
36d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                customCurves.put(curveParams.getCurve(), CustomNamedCurves.getByName(name).getCurve());
37d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
38d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
39d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
40d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static EllipticCurve convertCurve(
428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECCurve curve,
438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte[]  seed)
448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // TODO: the Sun EC implementation doesn't currently handle the seed properly
468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // so at the moment it's set to null. Should probably look at making this configurable
47d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (ECAlgorithms.isFpCurve(curve))
488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
49d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return new EllipticCurve(new ECFieldFp(curve.getField().getCharacteristic()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null);
508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECCurve.F2m curveF2m = (ECCurve.F2m)curve;
548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int ks[];
558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (curveF2m.isTrinomial())
578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ks = new int[] { curveF2m.getK1() };
598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return new EllipticCurve(new ECFieldF2m(curveF2m.getM(), ks), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null);
618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ks = new int[] { curveF2m.getK3(), curveF2m.getK2(), curveF2m.getK1() };
658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return new EllipticCurve(new ECFieldF2m(curveF2m.getM(), ks), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null);
678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static ECCurve convertCurve(
728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        EllipticCurve ec)
738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECField field = ec.getField();
758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger a = ec.getA();
768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger b = ec.getB();
778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (field instanceof ECFieldFp)
798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
80d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            ECCurve.Fp curve = new ECCurve.Fp(((ECFieldFp)field).getP(), a, b);
81d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
82d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            if (customCurves.containsKey(curve))
83d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
84d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                return (ECCurve)customCurves.get(curve);
85d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
86d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
87d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return curve;
888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldF2m fieldF2m = (ECFieldF2m)field;
928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int m = fieldF2m.getM();
938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int ks[] = ECUtil.convertMidTerms(fieldF2m.getMidTermsOfReductionPolynomial());
948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECCurve.F2m(m, ks[0], ks[1], ks[2], a, b);
958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static ECParameterSpec convertSpec(
998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        EllipticCurve ellipticCurve,
1008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        org.bouncycastle.jce.spec.ECParameterSpec spec)
1018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (spec instanceof ECNamedCurveParameterSpec)
1038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECNamedCurveSpec(
1058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ((ECNamedCurveParameterSpec)spec).getName(),
1068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ellipticCurve,
1078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                new ECPoint(
1085db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    spec.getG().getAffineXCoord().toBigInteger(),
1095db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    spec.getG().getAffineYCoord().toBigInteger()),
1108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                spec.getN(),
1118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                spec.getH());
1128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
1148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECParameterSpec(
1168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ellipticCurve,
1178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                new ECPoint(
1185db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    spec.getG().getAffineXCoord().toBigInteger(),
1195db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    spec.getG().getAffineYCoord().toBigInteger()),
1208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                spec.getN(),
1218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                spec.getH().intValue());
1228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static org.bouncycastle.jce.spec.ECParameterSpec convertSpec(
1268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECParameterSpec ecSpec,
1278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        boolean withCompression)
1288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECCurve curve = convertCurve(ecSpec.getCurve());
1308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return new org.bouncycastle.jce.spec.ECParameterSpec(
1328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            curve,
1338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            convertPoint(curve, ecSpec.getGenerator(), withCompression),
1348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ecSpec.getOrder(),
1358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger.valueOf(ecSpec.getCofactor()),
1368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ecSpec.getCurve().getSeed());
1378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static org.bouncycastle.math.ec.ECPoint convertPoint(
1408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECParameterSpec ecSpec,
1418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPoint point,
1428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        boolean withCompression)
1438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return convertPoint(convertCurve(ecSpec.getCurve()), point, withCompression);
1458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static org.bouncycastle.math.ec.ECPoint convertPoint(
1488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECCurve curve,
1498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPoint point,
1508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        boolean withCompression)
1518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return curve.createPoint(point.getAffineX(), point.getAffineY(), withCompression);
1538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom}
155