OpenSSLECPublicKey.java revision 5070bdfc6277af136b7eb5fe5d0d72ad2ff6a2eb
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 17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt; 188b7521eb38878822be3817270cc074ee1e22095dKenny Root 198b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.io.IOException; 208b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.io.ObjectInputStream; 218b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.io.ObjectOutputStream; 228b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.security.InvalidKeyException; 238b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.security.interfaces.ECPublicKey; 248b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.security.spec.ECParameterSpec; 258b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.security.spec.ECPoint; 2611b3e7025853f061e2f0e0ce1e248e730eca721eKenny Rootimport java.security.spec.ECPublicKeySpec; 2711b3e7025853f061e2f0e0ce1e248e730eca721eKenny Rootimport java.security.spec.InvalidKeySpecException; 288b7521eb38878822be3817270cc074ee1e22095dKenny Rootimport java.util.Arrays; 298b7521eb38878822be3817270cc074ee1e22095dKenny Root 305070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root/** 315070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root * An implementation of a {@link java.security.PublicKey} for EC keys based on BoringSSL. 325070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root * 335070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root * @hide 345070bdfc6277af136b7eb5fe5d0d72ad2ff6a2ebKenny Root */ 3547cc520bd63c1eabfdef23cbab10457701f2a395Kenny Rootpublic final class OpenSSLECPublicKey implements ECPublicKey, OpenSSLKeyHolder { 368b7521eb38878822be3817270cc074ee1e22095dKenny Root private static final long serialVersionUID = 3215842926808298020L; 378b7521eb38878822be3817270cc074ee1e22095dKenny Root 388b7521eb38878822be3817270cc074ee1e22095dKenny Root private static final String ALGORITHM = "EC"; 398b7521eb38878822be3817270cc074ee1e22095dKenny Root 408b7521eb38878822be3817270cc074ee1e22095dKenny Root protected transient OpenSSLKey key; 418b7521eb38878822be3817270cc074ee1e22095dKenny Root 428b7521eb38878822be3817270cc074ee1e22095dKenny Root protected transient OpenSSLECGroupContext group; 438b7521eb38878822be3817270cc074ee1e22095dKenny Root 448b7521eb38878822be3817270cc074ee1e22095dKenny Root public OpenSSLECPublicKey(OpenSSLECGroupContext group, OpenSSLKey key) { 458b7521eb38878822be3817270cc074ee1e22095dKenny Root this.group = group; 468b7521eb38878822be3817270cc074ee1e22095dKenny Root this.key = key; 478b7521eb38878822be3817270cc074ee1e22095dKenny Root } 488b7521eb38878822be3817270cc074ee1e22095dKenny Root 4947cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root public OpenSSLECPublicKey(OpenSSLKey key) { 507dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root this.group = new OpenSSLECGroupContext(new NativeRef.EC_GROUP( 517dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root NativeCrypto.EC_KEY_get1_group(key.getNativeRef()))); 5247cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root this.key = key; 5347cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root } 5447cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root 5511b3e7025853f061e2f0e0ce1e248e730eca721eKenny Root public OpenSSLECPublicKey(ECPublicKeySpec ecKeySpec) throws InvalidKeySpecException { 5611b3e7025853f061e2f0e0ce1e248e730eca721eKenny Root try { 57d4600d69dba0f1df24e8df7328fa473632c32822Kenny Root group = OpenSSLECGroupContext.getInstance(ecKeySpec.getParams()); 58597fd4e460c114003257d1b007d1b75c53af9fd7Kenny Root OpenSSLECPointContext pubKey = OpenSSLECPointContext.getInstance(group, 59597fd4e460c114003257d1b007d1b75c53af9fd7Kenny Root ecKeySpec.getW()); 607dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_EC_KEY(group.getNativeRef(), 617dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root pubKey.getNativeRef(), null)); 6211b3e7025853f061e2f0e0ce1e248e730eca721eKenny Root } catch (Exception e) { 6311b3e7025853f061e2f0e0ce1e248e730eca721eKenny Root throw new InvalidKeySpecException(e); 6411b3e7025853f061e2f0e0ce1e248e730eca721eKenny Root } 6511b3e7025853f061e2f0e0ce1e248e730eca721eKenny Root } 6611b3e7025853f061e2f0e0ce1e248e730eca721eKenny Root 678b7521eb38878822be3817270cc074ee1e22095dKenny Root public static OpenSSLKey getInstance(ECPublicKey ecPublicKey) throws InvalidKeyException { 688b7521eb38878822be3817270cc074ee1e22095dKenny Root try { 698b7521eb38878822be3817270cc074ee1e22095dKenny Root OpenSSLECGroupContext group = OpenSSLECGroupContext 708b7521eb38878822be3817270cc074ee1e22095dKenny Root .getInstance(ecPublicKey.getParams()); 71597fd4e460c114003257d1b007d1b75c53af9fd7Kenny Root OpenSSLECPointContext pubKey = OpenSSLECPointContext.getInstance(group, 727dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root ecPublicKey.getW()); 737dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_EC_KEY(group.getNativeRef(), 747dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root pubKey.getNativeRef(), null)); 758b7521eb38878822be3817270cc074ee1e22095dKenny Root } catch (Exception e) { 768b7521eb38878822be3817270cc074ee1e22095dKenny Root throw new InvalidKeyException(e); 778b7521eb38878822be3817270cc074ee1e22095dKenny Root } 788b7521eb38878822be3817270cc074ee1e22095dKenny Root } 798b7521eb38878822be3817270cc074ee1e22095dKenny Root 808b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 818b7521eb38878822be3817270cc074ee1e22095dKenny Root public String getAlgorithm() { 828b7521eb38878822be3817270cc074ee1e22095dKenny Root return ALGORITHM; 838b7521eb38878822be3817270cc074ee1e22095dKenny Root } 848b7521eb38878822be3817270cc074ee1e22095dKenny Root 858b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 868b7521eb38878822be3817270cc074ee1e22095dKenny Root public String getFormat() { 878b7521eb38878822be3817270cc074ee1e22095dKenny Root return "X.509"; 888b7521eb38878822be3817270cc074ee1e22095dKenny Root } 898b7521eb38878822be3817270cc074ee1e22095dKenny Root 908b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 918b7521eb38878822be3817270cc074ee1e22095dKenny Root public byte[] getEncoded() { 9237e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root return NativeCrypto.i2d_PUBKEY(key.getNativeRef()); 938b7521eb38878822be3817270cc074ee1e22095dKenny Root } 948b7521eb38878822be3817270cc074ee1e22095dKenny Root 958b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 968b7521eb38878822be3817270cc074ee1e22095dKenny Root public ECParameterSpec getParams() { 978b7521eb38878822be3817270cc074ee1e22095dKenny Root return group.getECParameterSpec(); 988b7521eb38878822be3817270cc074ee1e22095dKenny Root } 998b7521eb38878822be3817270cc074ee1e22095dKenny Root 1008b7521eb38878822be3817270cc074ee1e22095dKenny Root private ECPoint getPublicKey() { 1018b7521eb38878822be3817270cc074ee1e22095dKenny Root final OpenSSLECPointContext pubKey = new OpenSSLECPointContext(group, 1027dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root new NativeRef.EC_POINT(NativeCrypto.EC_KEY_get_public_key(key.getNativeRef()))); 1038b7521eb38878822be3817270cc074ee1e22095dKenny Root 1048b7521eb38878822be3817270cc074ee1e22095dKenny Root return pubKey.getECPoint(); 1058b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1068b7521eb38878822be3817270cc074ee1e22095dKenny Root 1078b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 1088b7521eb38878822be3817270cc074ee1e22095dKenny Root public ECPoint getW() { 1098b7521eb38878822be3817270cc074ee1e22095dKenny Root return getPublicKey(); 1108b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1118b7521eb38878822be3817270cc074ee1e22095dKenny Root 11247cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root @Override 1138b7521eb38878822be3817270cc074ee1e22095dKenny Root public OpenSSLKey getOpenSSLKey() { 1148b7521eb38878822be3817270cc074ee1e22095dKenny Root return key; 1158b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1168b7521eb38878822be3817270cc074ee1e22095dKenny Root 1178b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 1188b7521eb38878822be3817270cc074ee1e22095dKenny Root public boolean equals(Object o) { 1198b7521eb38878822be3817270cc074ee1e22095dKenny Root if (o == this) { 1208b7521eb38878822be3817270cc074ee1e22095dKenny Root return true; 1218b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1228b7521eb38878822be3817270cc074ee1e22095dKenny Root 123cac9de82cc0c50ff1a20d1290339776c125fc63eKenny Root if (o instanceof OpenSSLECPublicKey) { 124cac9de82cc0c50ff1a20d1290339776c125fc63eKenny Root OpenSSLECPublicKey other = (OpenSSLECPublicKey) o; 1258b7521eb38878822be3817270cc074ee1e22095dKenny Root return key.equals(other.key); 1268b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1278b7521eb38878822be3817270cc074ee1e22095dKenny Root 1288b7521eb38878822be3817270cc074ee1e22095dKenny Root if (!(o instanceof ECPublicKey)) { 1298b7521eb38878822be3817270cc074ee1e22095dKenny Root return false; 1308b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1318b7521eb38878822be3817270cc074ee1e22095dKenny Root 1328b7521eb38878822be3817270cc074ee1e22095dKenny Root final ECPublicKey other = (ECPublicKey) o; 1338b7521eb38878822be3817270cc074ee1e22095dKenny Root if (!getPublicKey().equals(other.getW())) { 1348b7521eb38878822be3817270cc074ee1e22095dKenny Root return false; 1358b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1368b7521eb38878822be3817270cc074ee1e22095dKenny Root 1378b7521eb38878822be3817270cc074ee1e22095dKenny Root final ECParameterSpec spec = getParams(); 1388b7521eb38878822be3817270cc074ee1e22095dKenny Root final ECParameterSpec otherSpec = other.getParams(); 1398b7521eb38878822be3817270cc074ee1e22095dKenny Root 1408b7521eb38878822be3817270cc074ee1e22095dKenny Root return spec.getCurve().equals(otherSpec.getCurve()) 1418b7521eb38878822be3817270cc074ee1e22095dKenny Root && spec.getGenerator().equals(otherSpec.getGenerator()) 1428b7521eb38878822be3817270cc074ee1e22095dKenny Root && spec.getOrder().equals(otherSpec.getOrder()) 1438b7521eb38878822be3817270cc074ee1e22095dKenny Root && spec.getCofactor() == otherSpec.getCofactor(); 1448b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1458b7521eb38878822be3817270cc074ee1e22095dKenny Root 1468b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 1478b7521eb38878822be3817270cc074ee1e22095dKenny Root public int hashCode() { 14837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root return Arrays.hashCode(NativeCrypto.i2d_PUBKEY(key.getNativeRef())); 1498b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1508b7521eb38878822be3817270cc074ee1e22095dKenny Root 1518b7521eb38878822be3817270cc074ee1e22095dKenny Root @Override 1528b7521eb38878822be3817270cc074ee1e22095dKenny Root public String toString() { 15337e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root return NativeCrypto.EVP_PKEY_print_public(key.getNativeRef()); 1548b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1558b7521eb38878822be3817270cc074ee1e22095dKenny Root 1568b7521eb38878822be3817270cc074ee1e22095dKenny Root private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 1578b7521eb38878822be3817270cc074ee1e22095dKenny Root stream.defaultReadObject(); 1588b7521eb38878822be3817270cc074ee1e22095dKenny Root 1595b36f6cc5f013574dc453e8938fcae13185c7732Kenny Root byte[] encoded = (byte[]) stream.readObject(); 1608b7521eb38878822be3817270cc074ee1e22095dKenny Root 1615b36f6cc5f013574dc453e8938fcae13185c7732Kenny Root key = new OpenSSLKey(NativeCrypto.d2i_PUBKEY(encoded)); 1627dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root group = new OpenSSLECGroupContext(new NativeRef.EC_GROUP( 1637dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root NativeCrypto.EC_KEY_get1_group(key.getNativeRef()))); 1648b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1658b7521eb38878822be3817270cc074ee1e22095dKenny Root 1668b7521eb38878822be3817270cc074ee1e22095dKenny Root private void writeObject(ObjectOutputStream stream) throws IOException { 1678b7521eb38878822be3817270cc074ee1e22095dKenny Root stream.defaultWriteObject(); 1685b36f6cc5f013574dc453e8938fcae13185c7732Kenny Root stream.writeObject(getEncoded()); 1698b7521eb38878822be3817270cc074ee1e22095dKenny Root } 1708b7521eb38878822be3817270cc074ee1e22095dKenny Root} 171