1746a236e2be5dee62c482e27f4c682496d071d8bKenny Root/* 2746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * Copyright (C) 2012 The Android Open Source Project 3746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * 4746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 5746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * you may not use this file except in compliance with the License. 6746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * You may obtain a copy of the License at 7746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * 8746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * http://www.apache.org/licenses/LICENSE-2.0 9746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * 10746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * Unless required by applicable law or agreed to in writing, software 11746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 12746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * See the License for the specific language governing permissions and 14746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * limitations under the License. 15746a236e2be5dee62c482e27f4c682496d071d8bKenny Root */ 16746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 17746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootpackage org.apache.harmony.xnet.provider.jsse; 18746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 19746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.math.BigInteger; 20746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.InvalidKeyException; 21746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.interfaces.RSAPublicKey; 22746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.InvalidKeySpecException; 23746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.RSAPublicKeySpec; 24746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 25746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootpublic class OpenSSLRSAPublicKey implements RSAPublicKey { 26d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root private static final long serialVersionUID = 123125005824688292L; 27d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 28746a236e2be5dee62c482e27f4c682496d071d8bKenny Root private final OpenSSLKey key; 29746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 30746a236e2be5dee62c482e27f4c682496d071d8bKenny Root private BigInteger publicExponent; 31746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 32746a236e2be5dee62c482e27f4c682496d071d8bKenny Root private BigInteger modulus; 33746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 34746a236e2be5dee62c482e27f4c682496d071d8bKenny Root private boolean fetchedParams; 35746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 36746a236e2be5dee62c482e27f4c682496d071d8bKenny Root OpenSSLRSAPublicKey(OpenSSLKey key) { 37746a236e2be5dee62c482e27f4c682496d071d8bKenny Root this.key = key; 38746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 39746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 4091bb5fbe55b854df891ff7720e30d42081dbcd58Kenny Root OpenSSLKey getOpenSSLKey() { 4191bb5fbe55b854df891ff7720e30d42081dbcd58Kenny Root return key; 4291bb5fbe55b854df891ff7720e30d42081dbcd58Kenny Root } 4391bb5fbe55b854df891ff7720e30d42081dbcd58Kenny Root 44746a236e2be5dee62c482e27f4c682496d071d8bKenny Root OpenSSLRSAPublicKey(RSAPublicKeySpec spec) throws InvalidKeySpecException { 45746a236e2be5dee62c482e27f4c682496d071d8bKenny Root try { 46746a236e2be5dee62c482e27f4c682496d071d8bKenny Root key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 47746a236e2be5dee62c482e27f4c682496d071d8bKenny Root spec.getModulus().toByteArray(), 48746a236e2be5dee62c482e27f4c682496d071d8bKenny Root spec.getPublicExponent().toByteArray(), 49746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 50746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 51746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 52746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 53746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 54746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null)); 55746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } catch (Exception e) { 56746a236e2be5dee62c482e27f4c682496d071d8bKenny Root throw new InvalidKeySpecException(e); 57746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 58746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 59746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 60746a236e2be5dee62c482e27f4c682496d071d8bKenny Root static OpenSSLKey getInstance(RSAPublicKey rsaPublicKey) throws InvalidKeyException { 61746a236e2be5dee62c482e27f4c682496d071d8bKenny Root try { 62746a236e2be5dee62c482e27f4c682496d071d8bKenny Root return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 63746a236e2be5dee62c482e27f4c682496d071d8bKenny Root rsaPublicKey.getModulus().toByteArray(), 64746a236e2be5dee62c482e27f4c682496d071d8bKenny Root rsaPublicKey.getPublicExponent().toByteArray(), 65746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 66746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 67746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 68746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 69746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null, 70746a236e2be5dee62c482e27f4c682496d071d8bKenny Root null)); 71746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } catch (Exception e) { 72746a236e2be5dee62c482e27f4c682496d071d8bKenny Root throw new InvalidKeyException(e); 73746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 74746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 75746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 76746a236e2be5dee62c482e27f4c682496d071d8bKenny Root @Override 77746a236e2be5dee62c482e27f4c682496d071d8bKenny Root public String getAlgorithm() { 78746a236e2be5dee62c482e27f4c682496d071d8bKenny Root return "RSA"; 79746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 80746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 81746a236e2be5dee62c482e27f4c682496d071d8bKenny Root @Override 82746a236e2be5dee62c482e27f4c682496d071d8bKenny Root public String getFormat() { 83746a236e2be5dee62c482e27f4c682496d071d8bKenny Root return "X.509"; 84746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 85746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 86746a236e2be5dee62c482e27f4c682496d071d8bKenny Root @Override 87746a236e2be5dee62c482e27f4c682496d071d8bKenny Root public byte[] getEncoded() { 88746a236e2be5dee62c482e27f4c682496d071d8bKenny Root return NativeCrypto.i2d_PUBKEY(key.getPkeyContext()); 89746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 90746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 91746a236e2be5dee62c482e27f4c682496d071d8bKenny Root private void ensureReadParams() { 92746a236e2be5dee62c482e27f4c682496d071d8bKenny Root if (fetchedParams) { 93746a236e2be5dee62c482e27f4c682496d071d8bKenny Root return; 94746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 95746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 96746a236e2be5dee62c482e27f4c682496d071d8bKenny Root byte[][] params = NativeCrypto.get_RSA_public_params(key.getPkeyContext()); 97746a236e2be5dee62c482e27f4c682496d071d8bKenny Root modulus = new BigInteger(params[0]); 98746a236e2be5dee62c482e27f4c682496d071d8bKenny Root publicExponent = new BigInteger(params[1]); 99746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 100746a236e2be5dee62c482e27f4c682496d071d8bKenny Root fetchedParams = true; 101746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 102746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 103746a236e2be5dee62c482e27f4c682496d071d8bKenny Root @Override 104746a236e2be5dee62c482e27f4c682496d071d8bKenny Root public BigInteger getModulus() { 105746a236e2be5dee62c482e27f4c682496d071d8bKenny Root ensureReadParams(); 106746a236e2be5dee62c482e27f4c682496d071d8bKenny Root return modulus; 107746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 108746a236e2be5dee62c482e27f4c682496d071d8bKenny Root 109746a236e2be5dee62c482e27f4c682496d071d8bKenny Root @Override 110746a236e2be5dee62c482e27f4c682496d071d8bKenny Root public BigInteger getPublicExponent() { 111746a236e2be5dee62c482e27f4c682496d071d8bKenny Root ensureReadParams(); 112746a236e2be5dee62c482e27f4c682496d071d8bKenny Root return publicExponent; 113746a236e2be5dee62c482e27f4c682496d071d8bKenny Root } 114d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 115d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root @Override 116d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root public boolean equals(Object o) { 117d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root if (o == this) { 118d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root return true; 119d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root } 120d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 121d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root if (o instanceof OpenSSLRSAPublicKey) { 122d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root OpenSSLRSAPublicKey other = (OpenSSLRSAPublicKey) o; 123d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 124d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root /* 125d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root * We can shortcut the true case, but it still may be equivalent but 126d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root * different copies. 127d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root */ 128d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root if (key.equals(other.getOpenSSLKey())) { 129d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root return true; 130d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root } 131d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root } 132d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 133d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root if (!(o instanceof RSAPublicKey)) { 134d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root return false; 135d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root } 136d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 137d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root ensureReadParams(); 138d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 139d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root RSAPublicKey other = (RSAPublicKey) o; 140d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root return modulus.equals(other.getModulus()) 141d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root && publicExponent.equals(other.getPublicExponent()); 142d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root } 143d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 144d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root @Override 145d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root public int hashCode() { 146d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root ensureReadParams(); 147d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 148d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root return modulus.hashCode() ^ publicExponent.hashCode(); 149d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root } 150d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 151d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root @Override 152d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root public String toString() { 153d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root ensureReadParams(); 154d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 155d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root final StringBuilder sb = new StringBuilder("OpenSSLRSAPublicKey{"); 156d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root sb.append("modulus="); 157d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root sb.append(modulus.toString(16)); 158d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root sb.append(','); 159d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root sb.append("publicExponent="); 160d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root sb.append(publicExponent.toString(16)); 161d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root sb.append('}'); 162d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root 163d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root return sb.toString(); 164d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root } 165746a236e2be5dee62c482e27f4c682496d071d8bKenny Root} 166