1 package org.bouncycastle.jcajce.provider.asymmetric.util; 2 3 import java.math.BigInteger; 4 import java.security.spec.ECField; 5 import java.security.spec.ECFieldF2m; 6 import java.security.spec.ECFieldFp; 7 import java.security.spec.ECParameterSpec; 8 import java.security.spec.ECPoint; 9 import java.security.spec.EllipticCurve; 10 import java.util.Enumeration; 11 import java.util.HashMap; 12 import java.util.Map; 13 14 import org.bouncycastle.asn1.ASN1ObjectIdentifier; 15 import org.bouncycastle.asn1.x9.ECNamedCurveTable; 16 import org.bouncycastle.asn1.x9.X962Parameters; 17 import org.bouncycastle.asn1.x9.X9ECParameters; 18 import org.bouncycastle.crypto.ec.CustomNamedCurves; 19 import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; 20 import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; 21 import org.bouncycastle.jce.spec.ECNamedCurveSpec; 22 import org.bouncycastle.math.ec.ECAlgorithms; 23 import org.bouncycastle.math.ec.ECCurve; 24 import org.bouncycastle.math.field.FiniteField; 25 import org.bouncycastle.math.field.Polynomial; 26 import org.bouncycastle.math.field.PolynomialExtensionField; 27 import org.bouncycastle.util.Arrays; 28 29 public class EC5Util 30 { 31 private static Map customCurves = new HashMap(); 32 33 static 34 { 35 Enumeration e = CustomNamedCurves.getNames(); 36 while (e.hasMoreElements()) 37 { 38 String name = (String)e.nextElement(); 39 40 X9ECParameters curveParams = ECNamedCurveTable.getByName(name); 41 if (curveParams != null) // there may not be a regular curve, may just be a custom curve. 42 { curveParams.getCurve()43 customCurves.put(curveParams.getCurve(), CustomNamedCurves.getByName(name).getCurve()); 44 } 45 } 46 } 47 getCurve( ProviderConfiguration configuration, X962Parameters params)48 public static ECCurve getCurve( 49 ProviderConfiguration configuration, 50 X962Parameters params) 51 { 52 ECCurve curve; 53 54 if (params.isNamedCurve()) 55 { 56 ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters()); 57 X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); 58 59 curve = ecP.getCurve(); 60 } 61 else if (params.isImplicitlyCA()) 62 { 63 curve = configuration.getEcImplicitlyCa().getCurve(); 64 } 65 else 66 { 67 X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); 68 69 curve = ecP.getCurve(); 70 } 71 72 return curve; 73 } 74 convertToSpec( X962Parameters params, ECCurve curve)75 public static ECParameterSpec convertToSpec( 76 X962Parameters params, ECCurve curve) 77 { 78 ECParameterSpec ecSpec; 79 EllipticCurve ellipticCurve; 80 81 if (params.isNamedCurve()) 82 { 83 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); 84 X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); 85 86 ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); 87 88 ecSpec = new ECNamedCurveSpec( 89 ECUtil.getCurveName(oid), 90 ellipticCurve, 91 new ECPoint( 92 ecP.getG().getAffineXCoord().toBigInteger(), 93 ecP.getG().getAffineYCoord().toBigInteger()), 94 ecP.getN(), 95 ecP.getH()); 96 } 97 else if (params.isImplicitlyCA()) 98 { 99 ecSpec = null; 100 } 101 else 102 { 103 X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); 104 105 ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); 106 107 if (ecP.getH() != null) 108 { 109 ecSpec = new ECParameterSpec( 110 ellipticCurve, 111 new ECPoint( 112 ecP.getG().getAffineXCoord().toBigInteger(), 113 ecP.getG().getAffineYCoord().toBigInteger()), 114 ecP.getN(), 115 ecP.getH().intValue()); 116 } 117 else 118 { 119 ecSpec = new ECParameterSpec( 120 ellipticCurve, 121 new ECPoint( 122 ecP.getG().getAffineXCoord().toBigInteger(), 123 ecP.getG().getAffineYCoord().toBigInteger()), 124 ecP.getN(), 1); // TODO: not strictly correct... need to fix the test data... 125 } 126 } 127 128 return ecSpec; 129 } 130 convertToSpec( X9ECParameters domainParameters)131 public static ECParameterSpec convertToSpec( 132 X9ECParameters domainParameters) 133 { 134 return new ECParameterSpec( 135 convertCurve(domainParameters.getCurve(), null), // JDK 1.5 has trouble with this if it's not null... 136 new ECPoint( 137 domainParameters.getG().getAffineXCoord().toBigInteger(), 138 domainParameters.getG().getAffineYCoord().toBigInteger()), 139 domainParameters.getN(), 140 domainParameters.getH().intValue()); 141 } 142 convertCurve( ECCurve curve, byte[] seed)143 public static EllipticCurve convertCurve( 144 ECCurve curve, 145 byte[] seed) 146 { 147 ECField field = convertField(curve.getField()); 148 BigInteger a = curve.getA().toBigInteger(), b = curve.getB().toBigInteger(); 149 150 // TODO: the Sun EC implementation doesn't currently handle the seed properly 151 // so at the moment it's set to null. Should probably look at making this configurable 152 return new EllipticCurve(field, a, b, null); 153 } 154 convertCurve( EllipticCurve ec)155 public static ECCurve convertCurve( 156 EllipticCurve ec) 157 { 158 ECField field = ec.getField(); 159 BigInteger a = ec.getA(); 160 BigInteger b = ec.getB(); 161 162 if (field instanceof ECFieldFp) 163 { 164 ECCurve.Fp curve = new ECCurve.Fp(((ECFieldFp)field).getP(), a, b); 165 166 if (customCurves.containsKey(curve)) 167 { 168 return (ECCurve)customCurves.get(curve); 169 } 170 171 return curve; 172 } 173 else 174 { 175 ECFieldF2m fieldF2m = (ECFieldF2m)field; 176 int m = fieldF2m.getM(); 177 int ks[] = ECUtil.convertMidTerms(fieldF2m.getMidTermsOfReductionPolynomial()); 178 return new ECCurve.F2m(m, ks[0], ks[1], ks[2], a, b); 179 } 180 } 181 convertField(FiniteField field)182 public static ECField convertField(FiniteField field) 183 { 184 if (ECAlgorithms.isFpField(field)) 185 { 186 return new ECFieldFp(field.getCharacteristic()); 187 } 188 else //if (ECAlgorithms.isF2mField(curveField)) 189 { 190 Polynomial poly = ((PolynomialExtensionField)field).getMinimalPolynomial(); 191 int[] exponents = poly.getExponentsPresent(); 192 int[] ks = Arrays.reverse(Arrays.copyOfRange(exponents, 1, exponents.length - 1)); 193 return new ECFieldF2m(poly.getDegree(), ks); 194 } 195 } 196 convertSpec( EllipticCurve ellipticCurve, org.bouncycastle.jce.spec.ECParameterSpec spec)197 public static ECParameterSpec convertSpec( 198 EllipticCurve ellipticCurve, 199 org.bouncycastle.jce.spec.ECParameterSpec spec) 200 { 201 if (spec instanceof ECNamedCurveParameterSpec) 202 { 203 return new ECNamedCurveSpec( 204 ((ECNamedCurveParameterSpec)spec).getName(), 205 ellipticCurve, 206 new ECPoint( 207 spec.getG().getAffineXCoord().toBigInteger(), 208 spec.getG().getAffineYCoord().toBigInteger()), 209 spec.getN(), 210 spec.getH()); 211 } 212 else 213 { 214 return new ECParameterSpec( 215 ellipticCurve, 216 new ECPoint( 217 spec.getG().getAffineXCoord().toBigInteger(), 218 spec.getG().getAffineYCoord().toBigInteger()), 219 spec.getN(), 220 spec.getH().intValue()); 221 } 222 } 223 convertSpec( ECParameterSpec ecSpec, boolean withCompression)224 public static org.bouncycastle.jce.spec.ECParameterSpec convertSpec( 225 ECParameterSpec ecSpec, 226 boolean withCompression) 227 { 228 ECCurve curve = convertCurve(ecSpec.getCurve()); 229 230 return new org.bouncycastle.jce.spec.ECParameterSpec( 231 curve, 232 convertPoint(curve, ecSpec.getGenerator(), withCompression), 233 ecSpec.getOrder(), 234 BigInteger.valueOf(ecSpec.getCofactor()), 235 ecSpec.getCurve().getSeed()); 236 } 237 convertPoint( ECParameterSpec ecSpec, ECPoint point, boolean withCompression)238 public static org.bouncycastle.math.ec.ECPoint convertPoint( 239 ECParameterSpec ecSpec, 240 ECPoint point, 241 boolean withCompression) 242 { 243 return convertPoint(convertCurve(ecSpec.getCurve()), point, withCompression); 244 } 245 convertPoint( ECCurve curve, ECPoint point, boolean withCompression)246 public static org.bouncycastle.math.ec.ECPoint convertPoint( 247 ECCurve curve, 248 ECPoint point, 249 boolean withCompression) 250 { 251 return curve.createPoint(point.getAffineX(), point.getAffineY()); 252 } 253 } 254