OpenSSLECPrivateKey.java revision 8acd6134dc84b387608746fbf2054c6d7dcd4f52
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.ECPrivateKey; 27import java.security.spec.ECParameterSpec; 28import java.security.spec.ECPrivateKeySpec; 29import java.security.spec.InvalidKeySpecException; 30import java.util.Arrays; 31 32public final class OpenSSLECPrivateKey implements ECPrivateKey, OpenSSLKeyHolder { 33 private static final long serialVersionUID = -4036633595001083922L; 34 35 private static final String ALGORITHM = "EC"; 36 37 protected transient OpenSSLKey key; 38 39 protected transient OpenSSLECGroupContext group; 40 41 public OpenSSLECPrivateKey(OpenSSLECGroupContext group, OpenSSLKey key) { 42 this.group = group; 43 this.key = key; 44 } 45 46 public OpenSSLECPrivateKey(OpenSSLKey key) { 47 final long origGroup = NativeCrypto.EC_KEY_get0_group(key.getPkeyContext()); 48 this.group = new OpenSSLECGroupContext(NativeCrypto.EC_GROUP_dup(origGroup)); 49 this.key = key; 50 } 51 52 public OpenSSLECPrivateKey(ECPrivateKeySpec ecKeySpec) throws InvalidKeySpecException { 53 try { 54 OpenSSLECGroupContext group = OpenSSLECGroupContext.getInstance(ecKeySpec 55 .getParams()); 56 final BigInteger privKey = ecKeySpec.getS(); 57 key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_EC_KEY(group.getContext(), 0, 58 privKey.toByteArray())); 59 } catch (Exception e) { 60 throw new InvalidKeySpecException(e); 61 } 62 } 63 64 public static OpenSSLKey getInstance(ECPrivateKey ecPrivateKey) throws InvalidKeyException { 65 try { 66 OpenSSLECGroupContext group = OpenSSLECGroupContext.getInstance(ecPrivateKey 67 .getParams()); 68 final BigInteger privKey = ecPrivateKey.getS(); 69 return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_EC_KEY(group.getContext(), 0, 70 privKey.toByteArray())); 71 } catch (Exception e) { 72 throw new InvalidKeyException(e); 73 } 74 } 75 76 @Override 77 public String getAlgorithm() { 78 return ALGORITHM; 79 } 80 81 @Override 82 public String getFormat() { 83 return "PKCS#8"; 84 } 85 86 @Override 87 public byte[] getEncoded() { 88 return NativeCrypto.i2d_PKCS8_PRIV_KEY_INFO(key.getPkeyContext()); 89 } 90 91 @Override 92 public ECParameterSpec getParams() { 93 return group.getECParameterSpec(); 94 } 95 96 @Override 97 public BigInteger getS() { 98 return getPrivateKey(); 99 } 100 101 private BigInteger getPrivateKey() { 102 return new BigInteger(NativeCrypto.EC_KEY_get_private_key(key.getPkeyContext())); 103 } 104 105 @Override 106 public OpenSSLKey getOpenSSLKey() { 107 return key; 108 } 109 110 @Override 111 public boolean equals(Object o) { 112 if (o == this) { 113 return true; 114 } 115 116 if (o instanceof OpenSSLECPrivateKey) { 117 OpenSSLECPrivateKey other = (OpenSSLECPrivateKey) o; 118 return key.equals(other.key); 119 } 120 121 if (!(o instanceof ECPrivateKey)) { 122 return false; 123 } 124 125 final ECPrivateKey other = (ECPrivateKey) o; 126 if (!getPrivateKey().equals(other.getS())) { 127 return false; 128 } 129 130 final ECParameterSpec spec = getParams(); 131 final ECParameterSpec otherSpec = other.getParams(); 132 133 return spec.getCurve().equals(otherSpec.getCurve()) 134 && spec.getGenerator().equals(otherSpec.getGenerator()) 135 && spec.getOrder().equals(otherSpec.getOrder()) 136 && spec.getCofactor() == otherSpec.getCofactor(); 137 } 138 139 @Override 140 public int hashCode() { 141 return Arrays.hashCode(NativeCrypto.i2d_PKCS8_PRIV_KEY_INFO(key.getPkeyContext())); 142 } 143 144 @Override 145 public String toString() { 146 return NativeCrypto.EVP_PKEY_print_private(key.getPkeyContext()); 147 } 148 149 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 150 stream.defaultReadObject(); 151 152 byte[] encoded = (byte[]) stream.readObject(); 153 154 key = new OpenSSLKey(NativeCrypto.d2i_PKCS8_PRIV_KEY_INFO(encoded)); 155 156 final long origGroup = NativeCrypto.EC_KEY_get0_group(key.getPkeyContext()); 157 group = new OpenSSLECGroupContext(NativeCrypto.EC_GROUP_dup(origGroup)); 158 } 159 160 private void writeObject(ObjectOutputStream stream) throws IOException { 161 if (key.isEngineBased()) { 162 throw new NotSerializableException("engine-based keys can not be serialized"); 163 } 164 165 stream.defaultWriteObject(); 166 stream.writeObject(getEncoded()); 167 } 168} 169