1 package org.bouncycastle.jcajce.provider.asymmetric.util; 2 3 import java.math.BigInteger; 4 import java.security.InvalidKeyException; 5 import java.security.PrivateKey; 6 import java.security.PublicKey; 7 import java.util.Enumeration; 8 9 import org.bouncycastle.asn1.ASN1ObjectIdentifier; 10 // BEGIN android-removed 11 // import org.bouncycastle.asn1.anssi.ANSSINamedCurves; 12 // import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; 13 // END android-removed 14 import org.bouncycastle.asn1.nist.NISTNamedCurves; 15 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; 16 import org.bouncycastle.asn1.sec.SECNamedCurves; 17 // BEGIN android-removed 18 // import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; 19 // END android-removed 20 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 21 import org.bouncycastle.asn1.x9.ECNamedCurveTable; 22 import org.bouncycastle.asn1.x9.X962NamedCurves; 23 import org.bouncycastle.asn1.x9.X9ECParameters; 24 import org.bouncycastle.crypto.ec.CustomNamedCurves; 25 import org.bouncycastle.crypto.params.AsymmetricKeyParameter; 26 import org.bouncycastle.crypto.params.ECDomainParameters; 27 import org.bouncycastle.crypto.params.ECPrivateKeyParameters; 28 import org.bouncycastle.crypto.params.ECPublicKeyParameters; 29 import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; 30 import org.bouncycastle.jce.interfaces.ECPrivateKey; 31 import org.bouncycastle.jce.interfaces.ECPublicKey; 32 import org.bouncycastle.jce.provider.BouncyCastleProvider; 33 import org.bouncycastle.jce.spec.ECParameterSpec; 34 35 /** 36 * utility class for converting jce/jca ECDSA, ECDH, and ECDHC 37 * objects into their org.bouncycastle.crypto counterparts. 38 */ 39 public class ECUtil 40 { 41 /** 42 * Returns a sorted array of middle terms of the reduction polynomial. 43 * @param k The unsorted array of middle terms of the reduction polynomial 44 * of length 1 or 3. 45 * @return the sorted array of middle terms of the reduction polynomial. 46 * This array always has length 3. 47 */ convertMidTerms( int[] k)48 static int[] convertMidTerms( 49 int[] k) 50 { 51 int[] res = new int[3]; 52 53 if (k.length == 1) 54 { 55 res[0] = k[0]; 56 } 57 else 58 { 59 if (k.length != 3) 60 { 61 throw new IllegalArgumentException("Only Trinomials and pentanomials supported"); 62 } 63 64 if (k[0] < k[1] && k[0] < k[2]) 65 { 66 res[0] = k[0]; 67 if (k[1] < k[2]) 68 { 69 res[1] = k[1]; 70 res[2] = k[2]; 71 } 72 else 73 { 74 res[1] = k[2]; 75 res[2] = k[1]; 76 } 77 } 78 else if (k[1] < k[2]) 79 { 80 res[0] = k[1]; 81 if (k[0] < k[2]) 82 { 83 res[1] = k[0]; 84 res[2] = k[2]; 85 } 86 else 87 { 88 res[1] = k[2]; 89 res[2] = k[0]; 90 } 91 } 92 else 93 { 94 res[0] = k[2]; 95 if (k[0] < k[1]) 96 { 97 res[1] = k[0]; 98 res[2] = k[1]; 99 } 100 else 101 { 102 res[1] = k[1]; 103 res[2] = k[0]; 104 } 105 } 106 } 107 108 return res; 109 } 110 generatePublicKeyParameter( PublicKey key)111 public static AsymmetricKeyParameter generatePublicKeyParameter( 112 PublicKey key) 113 throws InvalidKeyException 114 { 115 if (key instanceof ECPublicKey) 116 { 117 ECPublicKey k = (ECPublicKey)key; 118 ECParameterSpec s = k.getParameters(); 119 120 if (s == null) 121 { 122 s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa(); 123 124 return new ECPublicKeyParameters( 125 ((BCECPublicKey)k).engineGetQ(), 126 new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); 127 } 128 else 129 { 130 return new ECPublicKeyParameters( 131 k.getQ(), 132 new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); 133 } 134 } 135 else if (key instanceof java.security.interfaces.ECPublicKey) 136 { 137 java.security.interfaces.ECPublicKey pubKey = (java.security.interfaces.ECPublicKey)key; 138 ECParameterSpec s = EC5Util.convertSpec(pubKey.getParams(), false); 139 return new ECPublicKeyParameters( 140 EC5Util.convertPoint(pubKey.getParams(), pubKey.getW(), false), 141 new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); 142 } 143 else 144 { 145 // see if we can build a key from key.getEncoded() 146 try 147 { 148 byte[] bytes = key.getEncoded(); 149 150 if (bytes == null) 151 { 152 throw new InvalidKeyException("no encoding for EC public key"); 153 } 154 155 PublicKey publicKey = BouncyCastleProvider.getPublicKey(SubjectPublicKeyInfo.getInstance(bytes)); 156 157 if (publicKey instanceof java.security.interfaces.ECPublicKey) 158 { 159 return ECUtil.generatePublicKeyParameter(publicKey); 160 } 161 } 162 catch (Exception e) 163 { 164 throw new InvalidKeyException("cannot identify EC public key: " + e.toString()); 165 } 166 } 167 168 throw new InvalidKeyException("cannot identify EC public key."); 169 } 170 generatePrivateKeyParameter( PrivateKey key)171 public static AsymmetricKeyParameter generatePrivateKeyParameter( 172 PrivateKey key) 173 throws InvalidKeyException 174 { 175 if (key instanceof ECPrivateKey) 176 { 177 ECPrivateKey k = (ECPrivateKey)key; 178 ECParameterSpec s = k.getParameters(); 179 180 if (s == null) 181 { 182 s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa(); 183 } 184 185 return new ECPrivateKeyParameters( 186 k.getD(), 187 new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); 188 } 189 else if (key instanceof java.security.interfaces.ECPrivateKey) 190 { 191 java.security.interfaces.ECPrivateKey privKey = (java.security.interfaces.ECPrivateKey)key; 192 ECParameterSpec s = EC5Util.convertSpec(privKey.getParams(), false); 193 return new ECPrivateKeyParameters( 194 privKey.getS(), 195 new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); 196 } 197 else 198 { 199 // see if we can build a key from key.getEncoded() 200 try 201 { 202 byte[] bytes = key.getEncoded(); 203 204 if (bytes == null) 205 { 206 throw new InvalidKeyException("no encoding for EC private key"); 207 } 208 209 PrivateKey privateKey = BouncyCastleProvider.getPrivateKey(PrivateKeyInfo.getInstance(bytes)); 210 211 if (privateKey instanceof java.security.interfaces.ECPrivateKey) 212 { 213 return ECUtil.generatePrivateKeyParameter(privateKey); 214 } 215 } 216 catch (Exception e) 217 { 218 throw new InvalidKeyException("cannot identify EC private key: " + e.toString()); 219 } 220 } 221 222 throw new InvalidKeyException("can't identify EC private key."); 223 } 224 getOrderBitLength(BigInteger order, BigInteger privateValue)225 public static int getOrderBitLength(BigInteger order, BigInteger privateValue) 226 { 227 if (order == null) // implicitly CA 228 { 229 ECParameterSpec implicitCA = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa(); 230 231 if (implicitCA == null) 232 { 233 return privateValue.bitLength(); // a guess but better than an exception! 234 } 235 236 return implicitCA.getN().bitLength(); 237 } 238 else 239 { 240 return order.bitLength(); 241 } 242 } 243 getNamedCurveOid( String curveName)244 public static ASN1ObjectIdentifier getNamedCurveOid( 245 String curveName) 246 { 247 String name; 248 249 if (curveName.indexOf(' ') > 0) 250 { 251 name = curveName.substring(curveName.indexOf(' ') + 1); 252 } 253 else 254 { 255 name = curveName; 256 } 257 258 try 259 { 260 if (name.charAt(0) >= '0' && name.charAt(0) <= '2') 261 { 262 return new ASN1ObjectIdentifier(name); 263 } 264 else 265 { 266 return lookupOidByName(name); 267 } 268 } 269 catch (IllegalArgumentException ex) 270 { 271 return lookupOidByName(name); 272 } 273 } 274 lookupOidByName(String name)275 private static ASN1ObjectIdentifier lookupOidByName(String name) 276 { 277 ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name); 278 279 if (oid == null) 280 { 281 oid = SECNamedCurves.getOID(name); 282 if (oid == null) 283 { 284 oid = NISTNamedCurves.getOID(name); 285 } 286 // BEGIN android-removed 287 // if (oid == null) 288 // { 289 // oid = TeleTrusTNamedCurves.getOID(name); 290 // } 291 // if (oid == null) 292 // { 293 // oid = ECGOST3410NamedCurves.getOID(name); 294 // } 295 // if (oid == null) 296 // { 297 // oid = ANSSINamedCurves.getOID(name); 298 // } 299 // END android-removed 300 } 301 302 return oid; 303 } 304 getNamedCurveOid( ECParameterSpec ecParameterSpec)305 public static ASN1ObjectIdentifier getNamedCurveOid( 306 ECParameterSpec ecParameterSpec) 307 { 308 for (Enumeration names = ECNamedCurveTable.getNames(); names.hasMoreElements();) 309 { 310 String name = (String)names.nextElement(); 311 312 X9ECParameters params = ECNamedCurveTable.getByName(name); 313 314 if (params.getN().equals(ecParameterSpec.getN()) 315 && params.getH().equals(ecParameterSpec.getH()) 316 && params.getCurve().equals(ecParameterSpec.getCurve()) 317 && params.getG().equals(ecParameterSpec.getG())) 318 { 319 return org.bouncycastle.asn1.x9.ECNamedCurveTable.getOID(name); 320 } 321 } 322 323 return null; 324 } 325 getNamedCurveByOid( ASN1ObjectIdentifier oid)326 public static X9ECParameters getNamedCurveByOid( 327 ASN1ObjectIdentifier oid) 328 { 329 X9ECParameters params = CustomNamedCurves.getByOID(oid); 330 331 if (params == null) 332 { 333 params = X962NamedCurves.getByOID(oid); 334 if (params == null) 335 { 336 params = SECNamedCurves.getByOID(oid); 337 } 338 if (params == null) 339 { 340 params = NISTNamedCurves.getByOID(oid); 341 } 342 // BEGIN android-removed 343 // if (params == null) 344 // { 345 // params = TeleTrusTNamedCurves.getByOID(oid); 346 // } 347 // END android-removed 348 } 349 350 return params; 351 } 352 getNamedCurveByName( String curveName)353 public static X9ECParameters getNamedCurveByName( 354 String curveName) 355 { 356 X9ECParameters params = CustomNamedCurves.getByName(curveName); 357 358 if (params == null) 359 { 360 params = X962NamedCurves.getByName(curveName); 361 if (params == null) 362 { 363 params = SECNamedCurves.getByName(curveName); 364 } 365 if (params == null) 366 { 367 params = NISTNamedCurves.getByName(curveName); 368 } 369 // BEGIN android-removed 370 // if (params == null) 371 // { 372 // params = TeleTrusTNamedCurves.getByName(curveName); 373 // } 374 // END android-removed 375 } 376 377 return params; 378 } 379 getCurveName( ASN1ObjectIdentifier oid)380 public static String getCurveName( 381 ASN1ObjectIdentifier oid) 382 { 383 String name = X962NamedCurves.getName(oid); 384 385 if (name == null) 386 { 387 name = SECNamedCurves.getName(oid); 388 if (name == null) 389 { 390 name = NISTNamedCurves.getName(oid); 391 } 392 // BEGIN android-removed 393 // if (name == null) 394 // { 395 // name = TeleTrusTNamedCurves.getName(oid); 396 // } 397 // if (name == null) 398 // { 399 // name = ECGOST3410NamedCurves.getName(oid); 400 // } 401 // END android-removed 402 } 403 404 return name; 405 } 406 } 407