OpenSSLECPublicKey.java revision 9d2fb535e5d43ad34af09195d490da18a7694a48
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package org.apache.harmony.xnet.provider.jsse; 18 19import java.io.IOException; 20import java.io.NotSerializableException; 21import java.io.ObjectInputStream; 22import java.io.ObjectOutputStream; 23import java.math.BigInteger; 24import java.security.InvalidAlgorithmParameterException; 25import java.security.InvalidKeyException; 26import java.security.interfaces.ECPublicKey; 27import java.security.spec.ECParameterSpec; 28import java.security.spec.ECPoint; 29import java.util.Arrays; 30 31public final class OpenSSLECPublicKey implements ECPublicKey { 32 private static final long serialVersionUID = 3215842926808298020L; 33 34 private static final String ALGORITHM = "EC"; 35 36 protected transient OpenSSLKey key; 37 38 protected transient OpenSSLECGroupContext group; 39 40 public OpenSSLECPublicKey(OpenSSLECGroupContext group, OpenSSLKey key) { 41 this.group = group; 42 this.key = key; 43 } 44 45 public static OpenSSLKey getInstance(ECPublicKey ecPublicKey) throws InvalidKeyException { 46 try { 47 OpenSSLECGroupContext group = OpenSSLECGroupContext 48 .getInstance(ecPublicKey.getParams()); 49 OpenSSLECPointContext pubKey = OpenSSLECPointContext.getInstance( 50 NativeCrypto.get_EC_GROUP_type(group.getContext()), group, ecPublicKey.getW()); 51 return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_EC_KEY(group.getContext(), 52 pubKey.getContext(), null)); 53 } catch (Exception e) { 54 throw new InvalidKeyException(e); 55 } 56 } 57 58 @Override 59 public String getAlgorithm() { 60 return ALGORITHM; 61 } 62 63 @Override 64 public String getFormat() { 65 return "X.509"; 66 } 67 68 @Override 69 public byte[] getEncoded() { 70 return NativeCrypto.i2d_PUBKEY(key.getPkeyContext()); 71 } 72 73 @Override 74 public ECParameterSpec getParams() { 75 return group.getECParameterSpec(); 76 } 77 78 private ECPoint getPublicKey() { 79 final OpenSSLECPointContext pubKey = new OpenSSLECPointContext(group, 80 NativeCrypto.EC_KEY_get_public_key(key.getPkeyContext())); 81 82 return pubKey.getECPoint(); 83 } 84 85 @Override 86 public ECPoint getW() { 87 return getPublicKey(); 88 } 89 90 public OpenSSLKey getOpenSSLKey() { 91 return key; 92 } 93 94 @Override 95 public boolean equals(Object o) { 96 if (o == this) { 97 return true; 98 } 99 100 if (o instanceof OpenSSLECPrivateKey) { 101 OpenSSLECPrivateKey other = (OpenSSLECPrivateKey) o; 102 return key.equals(other.key); 103 } 104 105 if (!(o instanceof ECPublicKey)) { 106 return false; 107 } 108 109 final ECPublicKey other = (ECPublicKey) o; 110 if (!getPublicKey().equals(other.getW())) { 111 return false; 112 } 113 114 final ECParameterSpec spec = getParams(); 115 final ECParameterSpec otherSpec = other.getParams(); 116 117 return spec.getCurve().equals(otherSpec.getCurve()) 118 && spec.getGenerator().equals(otherSpec.getGenerator()) 119 && spec.getOrder().equals(otherSpec.getOrder()) 120 && spec.getCofactor() == otherSpec.getCofactor(); 121 } 122 123 @Override 124 public int hashCode() { 125 return Arrays.hashCode(NativeCrypto.i2d_PUBKEY(key.getPkeyContext())); 126 } 127 128 @Override 129 public String toString() { 130 return NativeCrypto.EVP_PKEY_print_public(key.getPkeyContext()); 131 } 132 133 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 134 stream.defaultReadObject(); 135 136 final ECParameterSpec params = (ECParameterSpec) stream.readObject(); 137 final BigInteger pubkeyX = (BigInteger) stream.readObject(); 138 final BigInteger pubkeyY = (BigInteger) stream.readObject(); 139 140 final OpenSSLECGroupContext group; 141 try { 142 group = OpenSSLECGroupContext.getInstance(params); 143 } catch (InvalidAlgorithmParameterException e) { 144 throw new ClassNotFoundException("cannot restore field type", e); 145 } 146 147 final int curveType = NativeCrypto.get_EC_GROUP_type(group.getContext()); 148 final ECPoint javaPubKey = new ECPoint(pubkeyX, pubkeyY); 149 final OpenSSLECPointContext pubKey = OpenSSLECPointContext.getInstance(curveType, group, 150 javaPubKey); 151 key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_EC_KEY(group.getContext(), 152 pubKey.getContext(), null)); 153 } 154 155 private void writeObject(ObjectOutputStream stream) throws IOException { 156 if (key.isEngineBased()) { 157 throw new NotSerializableException("engine-based keys can not be serialized"); 158 } 159 160 stream.defaultWriteObject(); 161 stream.writeObject(getParams()); 162 final ECPoint pubKey = getPublicKey(); 163 stream.writeObject(pubKey.getAffineX()); 164 stream.writeObject(pubKey.getAffineY()); 165 } 166} 167