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