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