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