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.math.BigInteger; 20import java.security.InvalidKeyException; 21import java.security.interfaces.RSAPublicKey; 22import java.security.spec.InvalidKeySpecException; 23import java.security.spec.RSAPublicKeySpec; 24 25public class OpenSSLRSAPublicKey implements RSAPublicKey { 26 private static final long serialVersionUID = 123125005824688292L; 27 28 private final OpenSSLKey key; 29 30 private BigInteger publicExponent; 31 32 private BigInteger modulus; 33 34 private boolean fetchedParams; 35 36 OpenSSLRSAPublicKey(OpenSSLKey key) { 37 this.key = key; 38 } 39 40 OpenSSLKey getOpenSSLKey() { 41 return key; 42 } 43 44 OpenSSLRSAPublicKey(RSAPublicKeySpec spec) throws InvalidKeySpecException { 45 try { 46 key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 47 spec.getModulus().toByteArray(), 48 spec.getPublicExponent().toByteArray(), 49 null, 50 null, 51 null, 52 null, 53 null, 54 null)); 55 } catch (Exception e) { 56 throw new InvalidKeySpecException(e); 57 } 58 } 59 60 static OpenSSLKey getInstance(RSAPublicKey rsaPublicKey) throws InvalidKeyException { 61 try { 62 return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 63 rsaPublicKey.getModulus().toByteArray(), 64 rsaPublicKey.getPublicExponent().toByteArray(), 65 null, 66 null, 67 null, 68 null, 69 null, 70 null)); 71 } catch (Exception e) { 72 throw new InvalidKeyException(e); 73 } 74 } 75 76 @Override 77 public String getAlgorithm() { 78 return "RSA"; 79 } 80 81 @Override 82 public String getFormat() { 83 return "X.509"; 84 } 85 86 @Override 87 public byte[] getEncoded() { 88 return NativeCrypto.i2d_PUBKEY(key.getPkeyContext()); 89 } 90 91 private void ensureReadParams() { 92 if (fetchedParams) { 93 return; 94 } 95 96 byte[][] params = NativeCrypto.get_RSA_public_params(key.getPkeyContext()); 97 modulus = new BigInteger(params[0]); 98 publicExponent = new BigInteger(params[1]); 99 100 fetchedParams = true; 101 } 102 103 @Override 104 public BigInteger getModulus() { 105 ensureReadParams(); 106 return modulus; 107 } 108 109 @Override 110 public BigInteger getPublicExponent() { 111 ensureReadParams(); 112 return publicExponent; 113 } 114 115 @Override 116 public boolean equals(Object o) { 117 if (o == this) { 118 return true; 119 } 120 121 if (o instanceof OpenSSLRSAPublicKey) { 122 OpenSSLRSAPublicKey other = (OpenSSLRSAPublicKey) o; 123 124 /* 125 * We can shortcut the true case, but it still may be equivalent but 126 * different copies. 127 */ 128 if (key.equals(other.getOpenSSLKey())) { 129 return true; 130 } 131 } 132 133 if (!(o instanceof RSAPublicKey)) { 134 return false; 135 } 136 137 ensureReadParams(); 138 139 RSAPublicKey other = (RSAPublicKey) o; 140 return modulus.equals(other.getModulus()) 141 && publicExponent.equals(other.getPublicExponent()); 142 } 143 144 @Override 145 public int hashCode() { 146 ensureReadParams(); 147 148 return modulus.hashCode() ^ publicExponent.hashCode(); 149 } 150 151 @Override 152 public String toString() { 153 ensureReadParams(); 154 155 final StringBuilder sb = new StringBuilder("OpenSSLRSAPublicKey{"); 156 sb.append("modulus="); 157 sb.append(modulus.toString(16)); 158 sb.append(','); 159 sb.append("publicExponent="); 160 sb.append(publicExponent.toString(16)); 161 sb.append('}'); 162 163 return sb.toString(); 164 } 165} 166