Java tutorial
package org.bouncycastle.jcajce.provider.asymmetric.util; import java.math.BigInteger; import java.security.spec.ECField; import java.security.spec.ECFieldF2m; import java.security.spec.ECFieldFp; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.EllipticCurve; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECAlgorithms; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.field.FiniteField; import org.bouncycastle.math.field.Polynomial; import org.bouncycastle.math.field.PolynomialExtensionField; import org.bouncycastle.util.Arrays; public class EC5Util { private static Map customCurves = new HashMap(); static { Enumeration e = CustomNamedCurves.getNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); X9ECParameters curveParams = ECNamedCurveTable.getByName(name); if (curveParams != null) // there may not be a regular curve, may just be a custom curve. { customCurves.put(curveParams.getCurve(), CustomNamedCurves.getByName(name).getCurve()); } } X9ECParameters x9_25519 = CustomNamedCurves.getByName("Curve25519"); ECCurve c_25519 = x9_25519.getCurve(); customCurves.put(new ECCurve.Fp(c_25519.getField().getCharacteristic(), c_25519.getA().toBigInteger(), c_25519.getB().toBigInteger(), c_25519.getOrder(), c_25519.getCofactor()), c_25519); } public static ECCurve getCurve(ProviderConfiguration configuration, X962Parameters params) { ECCurve curve; Set acceptableCurves = configuration.getAcceptableNamedCurves(); if (params.isNamedCurve()) { ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters()); if (acceptableCurves.isEmpty() || acceptableCurves.contains(oid)) { X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); if (ecP == null) { ecP = (X9ECParameters) configuration.getAdditionalECParameters().get(oid); } curve = ecP.getCurve(); } else { throw new IllegalStateException("named curve not acceptable"); } } else if (params.isImplicitlyCA()) { curve = configuration.getEcImplicitlyCa().getCurve(); } else if (acceptableCurves.isEmpty()) { X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); curve = ecP.getCurve(); } else { throw new IllegalStateException("encoded parameters not acceptable"); } return curve; } public static ECDomainParameters getDomainParameters(ProviderConfiguration configuration, java.security.spec.ECParameterSpec params) { ECDomainParameters domainParameters; if (params == null) { org.bouncycastle.jce.spec.ECParameterSpec iSpec = configuration.getEcImplicitlyCa(); domainParameters = new ECDomainParameters(iSpec.getCurve(), iSpec.getG(), iSpec.getN(), iSpec.getH(), iSpec.getSeed()); } else { domainParameters = ECUtil.getDomainParameters(configuration, convertSpec(params)); } return domainParameters; } public static ECParameterSpec convertToSpec(X962Parameters params, ECCurve curve) { ECParameterSpec ecSpec; EllipticCurve ellipticCurve; if (params.isNamedCurve()) { ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) params.getParameters(); X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); if (ecP == null) { Map additionalECParameters = BouncyCastleProvider.CONFIGURATION.getAdditionalECParameters(); if (!additionalECParameters.isEmpty()) { ecP = (X9ECParameters) additionalECParameters.get(oid); } } ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); ecSpec = new ECNamedCurveSpec(ECUtil.getCurveName(oid), ellipticCurve, convertPoint(ecP.getG()), ecP.getN(), ecP.getH()); } else if (params.isImplicitlyCA()) { ecSpec = null; } else { X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); if (ecP.getH() != null) { ecSpec = new ECParameterSpec(ellipticCurve, convertPoint(ecP.getG()), ecP.getN(), ecP.getH().intValue()); } else { ecSpec = new ECParameterSpec(ellipticCurve, convertPoint(ecP.getG()), ecP.getN(), 1); // TODO: not strictly correct... need to fix the test data... } } return ecSpec; } public static ECParameterSpec convertToSpec(X9ECParameters domainParameters) { return new ECParameterSpec(convertCurve(domainParameters.getCurve(), null), // JDK 1.5 has trouble with this if it's not null... EC5Util.convertPoint(domainParameters.getG()), domainParameters.getN(), domainParameters.getH().intValue()); } public static ECParameterSpec convertToSpec(ECDomainParameters domainParameters) { return new ECParameterSpec(convertCurve(domainParameters.getCurve(), null), // JDK 1.5 has trouble with this if it's not null... EC5Util.convertPoint(domainParameters.getG()), domainParameters.getN(), domainParameters.getH().intValue()); } public static EllipticCurve convertCurve(ECCurve curve, byte[] seed) { ECField field = convertField(curve.getField()); BigInteger a = curve.getA().toBigInteger(), b = curve.getB().toBigInteger(); // TODO: the Sun EC implementation doesn't currently handle the seed properly // so at the moment it's set to null. Should probably look at making this configurable return new EllipticCurve(field, a, b, null); } public static ECCurve convertCurve(EllipticCurve ec) { ECField field = ec.getField(); BigInteger a = ec.getA(); BigInteger b = ec.getB(); if (field instanceof ECFieldFp) { ECCurve.Fp curve = new ECCurve.Fp(((ECFieldFp) field).getP(), a, b); if (customCurves.containsKey(curve)) { return (ECCurve) customCurves.get(curve); } return curve; } else { ECFieldF2m fieldF2m = (ECFieldF2m) field; int m = fieldF2m.getM(); int ks[] = ECUtil.convertMidTerms(fieldF2m.getMidTermsOfReductionPolynomial()); return new ECCurve.F2m(m, ks[0], ks[1], ks[2], a, b); } } public static ECField convertField(FiniteField field) { if (ECAlgorithms.isFpField(field)) { return new ECFieldFp(field.getCharacteristic()); } else //if (ECAlgorithms.isF2mField(curveField)) { Polynomial poly = ((PolynomialExtensionField) field).getMinimalPolynomial(); int[] exponents = poly.getExponentsPresent(); int[] ks = Arrays.reverse(Arrays.copyOfRange(exponents, 1, exponents.length - 1)); return new ECFieldF2m(poly.getDegree(), ks); } } public static ECParameterSpec convertSpec(EllipticCurve ellipticCurve, org.bouncycastle.jce.spec.ECParameterSpec spec) { ECPoint g = convertPoint(spec.getG()); if (spec instanceof ECNamedCurveParameterSpec) { String name = ((ECNamedCurveParameterSpec) spec).getName(); return new ECNamedCurveSpec(name, ellipticCurve, g, spec.getN(), spec.getH()); } else { return new ECParameterSpec(ellipticCurve, g, spec.getN(), spec.getH().intValue()); } } public static org.bouncycastle.jce.spec.ECParameterSpec convertSpec(ECParameterSpec ecSpec) { ECCurve curve = convertCurve(ecSpec.getCurve()); org.bouncycastle.math.ec.ECPoint g = convertPoint(curve, ecSpec.getGenerator()); BigInteger n = ecSpec.getOrder(); BigInteger h = BigInteger.valueOf(ecSpec.getCofactor()); byte[] seed = ecSpec.getCurve().getSeed(); if (ecSpec instanceof ECNamedCurveSpec) { return new org.bouncycastle.jce.spec.ECNamedCurveParameterSpec(((ECNamedCurveSpec) ecSpec).getName(), curve, g, n, h, seed); } else { return new org.bouncycastle.jce.spec.ECParameterSpec(curve, g, n, h, seed); } } public static org.bouncycastle.math.ec.ECPoint convertPoint(ECParameterSpec ecSpec, ECPoint point) { return convertPoint(convertCurve(ecSpec.getCurve()), point); } public static org.bouncycastle.math.ec.ECPoint convertPoint(ECCurve curve, ECPoint point) { return curve.createPoint(point.getAffineX(), point.getAffineY()); } public static ECPoint convertPoint(org.bouncycastle.math.ec.ECPoint point) { point = point.normalize(); return new ECPoint(point.getAffineXCoord().toBigInteger(), point.getAffineYCoord().toBigInteger()); } }