OpenSSLECPublicKey.java revision 47cc520bd63c1eabfdef23cbab10457701f2a395
18b7521eb38878822be3817270cc074ee1e22095dKenny Root/* 28b7521eb38878822be3817270cc074ee1e22095dKenny Root * Copyright (C) 2012 The Android Open Source Project 38b7521eb38878822be3817270cc074ee1e22095dKenny Root * 48b7521eb38878822be3817270cc074ee1e22095dKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 58b7521eb38878822be3817270cc074ee1e22095dKenny Root * you may not use this file except in compliance with the License. 68b7521eb38878822be3817270cc074ee1e22095dKenny Root * You may obtain a copy of the License at 78b7521eb38878822be3817270cc074ee1e22095dKenny Root * 88b7521eb38878822be3817270cc074ee1e22095dKenny Root * http://www.apache.org/licenses/LICENSE-2.0 98b7521eb38878822be3817270cc074ee1e22095dKenny Root * 108b7521eb38878822be3817270cc074ee1e22095dKenny Root * Unless required by applicable law or agreed to in writing, software 118b7521eb38878822be3817270cc074ee1e22095dKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 128b7521eb38878822be3817270cc074ee1e22095dKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138b7521eb38878822be3817270cc074ee1e22095dKenny Root * See the License for the specific language governing permissions and 148b7521eb38878822be3817270cc074ee1e22095dKenny Root * limitations under the License. 158b7521eb38878822be3817270cc074ee1e22095dKenny Root */ 168b7521eb38878822be3817270cc074ee1e22095dKenny Root 178b7521eb38878822be3817270cc074ee1e22095dKenny Rootpackage org.apache.harmony.xnet.provider.jsse; 188b7521eb38878822be3817270cc074ee1e22095dKenny Root 198b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.io.IOException; 208b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.io.NotSerializableException; 218b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.io.ObjectInputStream; 228b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.io.ObjectOutputStream; 238b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.math.BigInteger; 248b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.security.InvalidAlgorithmParameterException; 258b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.security.InvalidKeyException; 268b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.security.interfaces.ECPublicKey; 278b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.security.spec.ECParameterSpec; 288b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.security.spec.ECPoint; 298b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.util.Arrays; 308b7521eb38878822be3817270cc074ee1e22095dKenny Root 3147cc520bd63c1eabfdef23cbab10457701f2a395Kenny Rootpublic final class OpenSSLECPublicKey implements ECPublicKey, OpenSSLKeyHolder { 328b7521eb38878822be3817270cc074ee1e22095dKenny Root private static final long serialVersionUID = 3215842926808298020L; 338b7521eb38878822be3817270cc074ee1e22095dKenny Root 348b7521eb38878822be3817270cc074ee1e22095dKenny Root private static final String ALGORITHM = "EC"; 358b7521eb38878822be3817270cc074ee1e22095dKenny Root 368b7521eb38878822be3817270cc074ee1e22095dKenny Root protected transient OpenSSLKey key; 378b7521eb38878822be3817270cc074ee1e22095dKenny Root 388b7521eb38878822be3817270cc074ee1e22095dKenny Root protected transient OpenSSLECGroupContext group; 398b7521eb38878822be3817270cc074ee1e22095dKenny Root 408b7521eb38878822be3817270cc074ee1e22095dKenny Root public OpenSSLECPublicKey(OpenSSLECGroupContext group, OpenSSLKey key) { 418b7521eb38878822be3817270cc074ee1e22095dKenny Root this.group = group; 428b7521eb38878822be3817270cc074ee1e22095dKenny Root this.key = key; 438b7521eb38878822be3817270cc074ee1e22095dKenny Root } 448b7521eb38878822be3817270cc074ee1e22095dKenny Root 4547cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root public OpenSSLECPublicKey(OpenSSLKey key) { 4647cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root final int origGroup = NativeCrypto.EC_KEY_get0_group(key.getPkeyContext()); 4747cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root this.group = new OpenSSLECGroupContext(NativeCrypto.EC_GROUP_dup(origGroup)); 4847cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root this.key = key; 4947cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root } 5047cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root 518b7521eb38878822be3817270cc074ee1e22095dKenny Root public static OpenSSLKey getInstance(ECPublicKey ecPublicKey) throws InvalidKeyException { 528b7521eb38878822be3817270cc074ee1e22095dKenny Root try { 538b7521eb38878822be3817270cc074ee1e22095dKenny Root OpenSSLECGroupContext group = OpenSSLECGroupContext 548b7521eb38878822be3817270cc074ee1e22095dKenny Root .getInstance(ecPublicKey.getParams()); 558b7521eb38878822be3817270cc074ee1e22095dKenny Root OpenSSLECPointContext pubKey = OpenSSLECPointContext.getInstance( 568b7521eb38878822be3817270cc074ee1e22095dKenny Root NativeCrypto.get_EC_GROUP_type(group.getContext()), group, ecPublicKey.getW()); 578b7521eb38878822be3817270cc074ee1e22095dKenny Root return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_EC_KEY(group.getContext(), 588b7521eb38878822be3817270cc074ee1e22095dKenny Root pubKey.getContext(), null)); 598b7521eb38878822be3817270cc074ee1e22095dKenny Root } catch (Exception e) { 608b7521eb38878822be3817270cc074ee1e22095dKenny Root throw new InvalidKeyException(e); 618b7521eb38878822be3817270cc074ee1e22095dKenny Root } 628b7521eb38878822be3817270cc074ee1e22095dKenny Root } 638b7521eb38878822be3817270cc074ee1e22095dKenny Root 648b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 658b7521eb38878822be3817270cc074ee1e22095dKenny Root public String getAlgorithm() { 668b7521eb38878822be3817270cc074ee1e22095dKenny Root return ALGORITHM; 678b7521eb38878822be3817270cc074ee1e22095dKenny Root } 688b7521eb38878822be3817270cc074ee1e22095dKenny Root 698b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 708b7521eb38878822be3817270cc074ee1e22095dKenny Root public String getFormat() { 718b7521eb38878822be3817270cc074ee1e22095dKenny Root return "X.509"; 728b7521eb38878822be3817270cc074ee1e22095dKenny Root } 738b7521eb38878822be3817270cc074ee1e22095dKenny Root 748b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 758b7521eb38878822be3817270cc074ee1e22095dKenny Root public byte[] getEncoded() { 768b7521eb38878822be3817270cc074ee1e22095dKenny Root return NativeCrypto.i2d_PUBKEY(key.getPkeyContext()); 778b7521eb38878822be3817270cc074ee1e22095dKenny Root } 788b7521eb38878822be3817270cc074ee1e22095dKenny Root 798b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 808b7521eb38878822be3817270cc074ee1e22095dKenny Root public ECParameterSpec getParams() { 818b7521eb38878822be3817270cc074ee1e22095dKenny Root return group.getECParameterSpec(); 828b7521eb38878822be3817270cc074ee1e22095dKenny Root } 838b7521eb38878822be3817270cc074ee1e22095dKenny Root 848b7521eb38878822be3817270cc074ee1e22095dKenny Root private ECPoint getPublicKey() { 858b7521eb38878822be3817270cc074ee1e22095dKenny Root final OpenSSLECPointContext pubKey = new OpenSSLECPointContext(group, 868b7521eb38878822be3817270cc074ee1e22095dKenny Root NativeCrypto.EC_KEY_get_public_key(key.getPkeyContext())); 878b7521eb38878822be3817270cc074ee1e22095dKenny Root 888b7521eb38878822be3817270cc074ee1e22095dKenny Root return pubKey.getECPoint(); 898b7521eb38878822be3817270cc074ee1e22095dKenny Root } 908b7521eb38878822be3817270cc074ee1e22095dKenny Root 918b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 928b7521eb38878822be3817270cc074ee1e22095dKenny Root public ECPoint getW() { 938b7521eb38878822be3817270cc074ee1e22095dKenny Root return getPublicKey(); 948b7521eb38878822be3817270cc074ee1e22095dKenny Root } 958b7521eb38878822be3817270cc074ee1e22095dKenny Root 9647cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root @Override 978b7521eb38878822be3817270cc074ee1e22095dKenny Root public OpenSSLKey getOpenSSLKey() { 988b7521eb38878822be3817270cc074ee1e22095dKenny Root return key; 998b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1008b7521eb38878822be3817270cc074ee1e22095dKenny Root 1018b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 1028b7521eb38878822be3817270cc074ee1e22095dKenny Root public boolean equals(Object o) { 1038b7521eb38878822be3817270cc074ee1e22095dKenny Root if (o == this) { 1048b7521eb38878822be3817270cc074ee1e22095dKenny Root return true; 1058b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1068b7521eb38878822be3817270cc074ee1e22095dKenny Root 1078b7521eb38878822be3817270cc074ee1e22095dKenny Root if (o instanceof OpenSSLECPrivateKey) { 1088b7521eb38878822be3817270cc074ee1e22095dKenny Root OpenSSLECPrivateKey other = (OpenSSLECPrivateKey) o; 1098b7521eb38878822be3817270cc074ee1e22095dKenny Root return key.equals(other.key); 1108b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1118b7521eb38878822be3817270cc074ee1e22095dKenny Root 1128b7521eb38878822be3817270cc074ee1e22095dKenny Root if (!(o instanceof ECPublicKey)) { 1138b7521eb38878822be3817270cc074ee1e22095dKenny Root return false; 1148b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1158b7521eb38878822be3817270cc074ee1e22095dKenny Root 1168b7521eb38878822be3817270cc074ee1e22095dKenny Root final ECPublicKey other = (ECPublicKey) o; 1178b7521eb38878822be3817270cc074ee1e22095dKenny Root if (!getPublicKey().equals(other.getW())) { 1188b7521eb38878822be3817270cc074ee1e22095dKenny Root return false; 1198b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1208b7521eb38878822be3817270cc074ee1e22095dKenny Root 1218b7521eb38878822be3817270cc074ee1e22095dKenny Root final ECParameterSpec spec = getParams(); 1228b7521eb38878822be3817270cc074ee1e22095dKenny Root final ECParameterSpec otherSpec = other.getParams(); 1238b7521eb38878822be3817270cc074ee1e22095dKenny Root 1248b7521eb38878822be3817270cc074ee1e22095dKenny Root return spec.getCurve().equals(otherSpec.getCurve()) 1258b7521eb38878822be3817270cc074ee1e22095dKenny Root && spec.getGenerator().equals(otherSpec.getGenerator()) 1268b7521eb38878822be3817270cc074ee1e22095dKenny Root && spec.getOrder().equals(otherSpec.getOrder()) 1278b7521eb38878822be3817270cc074ee1e22095dKenny Root && spec.getCofactor() == otherSpec.getCofactor(); 1288b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1298b7521eb38878822be3817270cc074ee1e22095dKenny Root 1308b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 1318b7521eb38878822be3817270cc074ee1e22095dKenny Root public int hashCode() { 1328b7521eb38878822be3817270cc074ee1e22095dKenny Root return Arrays.hashCode(NativeCrypto.i2d_PUBKEY(key.getPkeyContext())); 1338b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1348b7521eb38878822be3817270cc074ee1e22095dKenny Root 1358b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 1368b7521eb38878822be3817270cc074ee1e22095dKenny Root public String toString() { 1378b7521eb38878822be3817270cc074ee1e22095dKenny Root return NativeCrypto.EVP_PKEY_print_public(key.getPkeyContext()); 1388b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1398b7521eb38878822be3817270cc074ee1e22095dKenny Root 1408b7521eb38878822be3817270cc074ee1e22095dKenny Root private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 1418b7521eb38878822be3817270cc074ee1e22095dKenny Root stream.defaultReadObject(); 1428b7521eb38878822be3817270cc074ee1e22095dKenny Root 1438b7521eb38878822be3817270cc074ee1e22095dKenny Root final ECParameterSpec params = (ECParameterSpec) stream.readObject(); 1448b7521eb38878822be3817270cc074ee1e22095dKenny Root final BigInteger pubkeyX = (BigInteger) stream.readObject(); 1458b7521eb38878822be3817270cc074ee1e22095dKenny Root final BigInteger pubkeyY = (BigInteger) stream.readObject(); 1468b7521eb38878822be3817270cc074ee1e22095dKenny Root 1478b7521eb38878822be3817270cc074ee1e22095dKenny Root final OpenSSLECGroupContext group; 1488b7521eb38878822be3817270cc074ee1e22095dKenny Root try { 1498b7521eb38878822be3817270cc074ee1e22095dKenny Root group = OpenSSLECGroupContext.getInstance(params); 1508b7521eb38878822be3817270cc074ee1e22095dKenny Root } catch (InvalidAlgorithmParameterException e) { 1518b7521eb38878822be3817270cc074ee1e22095dKenny Root throw new ClassNotFoundException("cannot restore field type", e); 1528b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1538b7521eb38878822be3817270cc074ee1e22095dKenny Root 1548b7521eb38878822be3817270cc074ee1e22095dKenny Root final int curveType = NativeCrypto.get_EC_GROUP_type(group.getContext()); 1558b7521eb38878822be3817270cc074ee1e22095dKenny Root final ECPoint javaPubKey = new ECPoint(pubkeyX, pubkeyY); 1568b7521eb38878822be3817270cc074ee1e22095dKenny Root final OpenSSLECPointContext pubKey = OpenSSLECPointContext.getInstance(curveType, group, 1578b7521eb38878822be3817270cc074ee1e22095dKenny Root javaPubKey); 1588b7521eb38878822be3817270cc074ee1e22095dKenny Root key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_EC_KEY(group.getContext(), 1598b7521eb38878822be3817270cc074ee1e22095dKenny Root pubKey.getContext(), null)); 1608b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1618b7521eb38878822be3817270cc074ee1e22095dKenny Root 1628b7521eb38878822be3817270cc074ee1e22095dKenny Root private void writeObject(ObjectOutputStream stream) throws IOException { 1638b7521eb38878822be3817270cc074ee1e22095dKenny Root if (key.isEngineBased()) { 1648b7521eb38878822be3817270cc074ee1e22095dKenny Root throw new NotSerializableException("engine-based keys can not be serialized"); 1658b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1668b7521eb38878822be3817270cc074ee1e22095dKenny Root 1678b7521eb38878822be3817270cc074ee1e22095dKenny Root stream.defaultWriteObject(); 1688b7521eb38878822be3817270cc074ee1e22095dKenny Root stream.writeObject(getParams()); 1698b7521eb38878822be3817270cc074ee1e22095dKenny Root final ECPoint pubKey = getPublicKey(); 1708b7521eb38878822be3817270cc074ee1e22095dKenny Root stream.writeObject(pubKey.getAffineX()); 1718b7521eb38878822be3817270cc074ee1e22095dKenny Root stream.writeObject(pubKey.getAffineY()); 1728b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1738b7521eb38878822be3817270cc074ee1e22095dKenny Root} 174