1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 package com.android.org.bouncycastle.jcajce.provider.asymmetric.ec; 3 4 import java.io.IOException; 5 import java.io.ObjectInputStream; 6 import java.io.ObjectOutputStream; 7 import java.security.interfaces.ECPublicKey; 8 import java.security.spec.ECParameterSpec; 9 import java.security.spec.ECPoint; 10 import java.security.spec.ECPublicKeySpec; 11 import java.security.spec.EllipticCurve; 12 13 import com.android.org.bouncycastle.asn1.ASN1Encodable; 14 import com.android.org.bouncycastle.asn1.ASN1OctetString; 15 import com.android.org.bouncycastle.asn1.ASN1Primitive; 16 import com.android.org.bouncycastle.asn1.DERBitString; 17 import com.android.org.bouncycastle.asn1.DEROctetString; 18 import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier; 19 import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 20 import com.android.org.bouncycastle.asn1.x9.X962Parameters; 21 import com.android.org.bouncycastle.asn1.x9.X9ECPoint; 22 import com.android.org.bouncycastle.asn1.x9.X9IntegerConverter; 23 import com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 24 import com.android.org.bouncycastle.crypto.params.ECDomainParameters; 25 import com.android.org.bouncycastle.crypto.params.ECPublicKeyParameters; 26 import com.android.org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; 27 import com.android.org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; 28 import com.android.org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; 29 import com.android.org.bouncycastle.jcajce.provider.config.ProviderConfiguration; 30 import com.android.org.bouncycastle.jce.interfaces.ECPointEncoder; 31 import com.android.org.bouncycastle.jce.provider.BouncyCastleProvider; 32 import com.android.org.bouncycastle.math.ec.ECCurve; 33 34 /** 35 * @hide This class is not part of the Android public SDK API 36 */ 37 public class BCECPublicKey 38 implements ECPublicKey, com.android.org.bouncycastle.jce.interfaces.ECPublicKey, ECPointEncoder 39 { 40 static final long serialVersionUID = 2422789860422731812L; 41 42 private String algorithm = "EC"; 43 private boolean withCompression; 44 45 private transient ECPublicKeyParameters ecPublicKey; 46 private transient ECParameterSpec ecSpec; 47 private transient ProviderConfiguration configuration; 48 49 public BCECPublicKey( 50 String algorithm, 51 BCECPublicKey key) 52 { 53 this.algorithm = algorithm; 54 this.ecPublicKey = key.ecPublicKey; 55 this.ecSpec = key.ecSpec; 56 this.withCompression = key.withCompression; 57 this.configuration = key.configuration; 58 } 59 60 public BCECPublicKey( 61 String algorithm, 62 ECPublicKeySpec spec, 63 ProviderConfiguration configuration) 64 { 65 this.algorithm = algorithm; 66 this.ecSpec = spec.getParams(); 67 this.ecPublicKey = new ECPublicKeyParameters(EC5Util.convertPoint(ecSpec, spec.getW(), false), EC5Util.getDomainParameters(configuration, spec.getParams())); 68 this.configuration = configuration; 69 } 70 71 public BCECPublicKey( 72 String algorithm, 73 com.android.org.bouncycastle.jce.spec.ECPublicKeySpec spec, 74 ProviderConfiguration configuration) 75 { 76 this.algorithm = algorithm; 77 78 if (spec.getParams() != null) // can be null if implictlyCa 79 { 80 ECCurve curve = spec.getParams().getCurve(); 81 EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed()); 82 83 // this may seem a little long-winded but it's how we pick up the custom curve. 84 this.ecPublicKey = new ECPublicKeyParameters( 85 spec.getQ(), ECUtil.getDomainParameters(configuration, spec.getParams())); 86 this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams()); 87 } 88 else 89 { 90 com.android.org.bouncycastle.jce.spec.ECParameterSpec s = configuration.getEcImplicitlyCa(); 91 92 this.ecPublicKey = new ECPublicKeyParameters(s.getCurve().createPoint(spec.getQ().getAffineXCoord().toBigInteger(), spec.getQ().getAffineYCoord().toBigInteger()), EC5Util.getDomainParameters(configuration, (ECParameterSpec)null)); 93 this.ecSpec = null; 94 } 95 96 this.configuration = configuration; 97 } 98 99 public BCECPublicKey( 100 String algorithm, 101 ECPublicKeyParameters params, 102 ECParameterSpec spec, 103 ProviderConfiguration configuration) 104 { 105 ECDomainParameters dp = params.getParameters(); 106 107 this.algorithm = algorithm; 108 this.ecPublicKey = params; 109 110 if (spec == null) 111 { 112 EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed()); 113 114 this.ecSpec = createSpec(ellipticCurve, dp); 115 } 116 else 117 { 118 this.ecSpec = spec; 119 } 120 121 this.configuration = configuration; 122 } 123 124 public BCECPublicKey( 125 String algorithm, 126 ECPublicKeyParameters params, 127 com.android.org.bouncycastle.jce.spec.ECParameterSpec spec, 128 ProviderConfiguration configuration) 129 { 130 ECDomainParameters dp = params.getParameters(); 131 132 this.algorithm = algorithm; 133 134 if (spec == null) 135 { 136 EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed()); 137 138 this.ecSpec = createSpec(ellipticCurve, dp); 139 } 140 else 141 { 142 EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed()); 143 144 this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec); 145 } 146 147 this.ecPublicKey = params; 148 this.configuration = configuration; 149 } 150 151 /* 152 * called for implicitCA 153 */ 154 public BCECPublicKey( 155 String algorithm, 156 ECPublicKeyParameters params, 157 ProviderConfiguration configuration) 158 { 159 this.algorithm = algorithm; 160 this.ecPublicKey = params; 161 this.ecSpec = null; 162 this.configuration = configuration; 163 } 164 165 public BCECPublicKey( 166 ECPublicKey key, 167 ProviderConfiguration configuration) 168 { 169 this.algorithm = key.getAlgorithm(); 170 this.ecSpec = key.getParams(); 171 this.ecPublicKey = new ECPublicKeyParameters(EC5Util.convertPoint(this.ecSpec, key.getW(), false), EC5Util.getDomainParameters(configuration, key.getParams())); 172 } 173 174 BCECPublicKey( 175 String algorithm, 176 SubjectPublicKeyInfo info, 177 ProviderConfiguration configuration) 178 { 179 this.algorithm = algorithm; 180 this.configuration = configuration; 181 populateFromPubKeyInfo(info); 182 } 183 184 private ECParameterSpec createSpec(EllipticCurve ellipticCurve, ECDomainParameters dp) 185 { 186 return new ECParameterSpec( 187 ellipticCurve, 188 EC5Util.convertPoint(dp.getG()), 189 dp.getN(), 190 dp.getH().intValue()); 191 } 192 193 private void populateFromPubKeyInfo(SubjectPublicKeyInfo info) 194 { 195 X962Parameters params = X962Parameters.getInstance(info.getAlgorithm().getParameters()); 196 ECCurve curve = EC5Util.getCurve(configuration, params); 197 ecSpec = EC5Util.convertToSpec(params, curve); 198 199 DERBitString bits = info.getPublicKeyData(); 200 byte[] data = bits.getBytes(); 201 ASN1OctetString key = new DEROctetString(data); 202 203 // 204 // extra octet string - one of our old certs... 205 // 206 if (data[0] == 0x04 && data[1] == data.length - 2 207 && (data[2] == 0x02 || data[2] == 0x03)) 208 { 209 int qLength = new X9IntegerConverter().getByteLength(curve); 210 211 if (qLength >= data.length - 3) 212 { 213 try 214 { 215 key = (ASN1OctetString) ASN1Primitive.fromByteArray(data); 216 } 217 catch (IOException ex) 218 { 219 throw new IllegalArgumentException("error recovering public key"); 220 } 221 } 222 } 223 224 X9ECPoint derQ = new X9ECPoint(curve, key); 225 226 this.ecPublicKey = new ECPublicKeyParameters(derQ.getPoint(), ECUtil.getDomainParameters(configuration, params)); 227 } 228 229 public String getAlgorithm() 230 { 231 return algorithm; 232 } 233 234 public String getFormat() 235 { 236 return "X.509"; 237 } 238 239 public byte[] getEncoded() 240 { 241 ASN1Encodable params = ECUtils.getDomainParametersFromName(ecSpec, withCompression); 242 ASN1OctetString p = ASN1OctetString.getInstance(new X9ECPoint(ecPublicKey.getQ(), withCompression).toASN1Primitive()); 243 244 // stored curve is null if ImplicitlyCa 245 SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets()); 246 247 return KeyUtil.getEncodedSubjectPublicKeyInfo(info); 248 } 249 250 public ECParameterSpec getParams() 251 { 252 return ecSpec; 253 } 254 255 public com.android.org.bouncycastle.jce.spec.ECParameterSpec getParameters() 256 { 257 if (ecSpec == null) // implictlyCA 258 { 259 return null; 260 } 261 262 return EC5Util.convertSpec(ecSpec, withCompression); 263 } 264 265 public ECPoint getW() 266 { 267 return EC5Util.convertPoint(ecPublicKey.getQ()); 268 } 269 270 public com.android.org.bouncycastle.math.ec.ECPoint getQ() 271 { 272 com.android.org.bouncycastle.math.ec.ECPoint q = ecPublicKey.getQ(); 273 274 if (ecSpec == null) 275 { 276 return q.getDetachedPoint(); 277 } 278 279 return q; 280 } 281 282 ECPublicKeyParameters engineGetKeyParameters() 283 { 284 return ecPublicKey; 285 } 286 287 com.android.org.bouncycastle.jce.spec.ECParameterSpec engineGetSpec() 288 { 289 if (ecSpec != null) 290 { 291 return EC5Util.convertSpec(ecSpec, withCompression); 292 } 293 294 return configuration.getEcImplicitlyCa(); 295 } 296 297 public String toString() 298 { 299 return ECUtil.publicKeyToString("EC", ecPublicKey.getQ(), engineGetSpec()); 300 } 301 302 public void setPointFormat(String style) 303 { 304 withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style)); 305 } 306 307 public boolean equals(Object o) 308 { 309 if (!(o instanceof BCECPublicKey)) 310 { 311 return false; 312 } 313 314 BCECPublicKey other = (BCECPublicKey)o; 315 316 return ecPublicKey.getQ().equals(other.ecPublicKey.getQ()) && (engineGetSpec().equals(other.engineGetSpec())); 317 } 318 319 public int hashCode() 320 { 321 return ecPublicKey.getQ().hashCode() ^ engineGetSpec().hashCode(); 322 } 323 324 private void readObject( 325 ObjectInputStream in) 326 throws IOException, ClassNotFoundException 327 { 328 in.defaultReadObject(); 329 330 byte[] enc = (byte[])in.readObject(); 331 332 this.configuration = BouncyCastleProvider.CONFIGURATION; 333 334 populateFromPubKeyInfo(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(enc))); 335 } 336 337 private void writeObject( 338 ObjectOutputStream out) 339 throws IOException 340 { 341 out.defaultWriteObject(); 342 343 out.writeObject(this.getEncoded()); 344 } 345 } 346