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.DSAParams;
22746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.interfaces.DSAPublicKey;
23746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.DSAPublicKeySpec;
24746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.InvalidKeySpecException;
25746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
26746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootpublic class OpenSSLDSAPublicKey implements DSAPublicKey {
27d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    private static final long serialVersionUID = 5238609500353792232L;
28d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
29746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    private final OpenSSLKey key;
30746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
31746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    private OpenSSLDSAParams params;
32746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
33746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    OpenSSLDSAPublicKey(OpenSSLKey key) {
34746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        this.key = key;
35746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
36746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
3791bb5fbe55b854df891ff7720e30d42081dbcd58Kenny Root    OpenSSLKey getOpenSSLKey() {
3891bb5fbe55b854df891ff7720e30d42081dbcd58Kenny Root        return key;
3991bb5fbe55b854df891ff7720e30d42081dbcd58Kenny Root    }
4091bb5fbe55b854df891ff7720e30d42081dbcd58Kenny Root
41746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    OpenSSLDSAPublicKey(DSAPublicKeySpec dsaKeySpec) throws InvalidKeySpecException {
42746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        try {
43746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_DSA(
44746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    dsaKeySpec.getP().toByteArray(),
45746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    dsaKeySpec.getQ().toByteArray(),
46746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    dsaKeySpec.getG().toByteArray(),
47746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    dsaKeySpec.getY().toByteArray(),
48746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    null));
49746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } catch (Exception e) {
50746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            throw new InvalidKeySpecException(e);
51746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
52746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
53746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
54746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    private void ensureReadParams() {
55746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        if (params == null) {
56746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            params = new OpenSSLDSAParams(key);
57746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
58746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
59746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
60746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    static OpenSSLKey getInstance(DSAPublicKey dsaPublicKey) throws InvalidKeyException {
61746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        try {
62746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            final DSAParams dsaParams = dsaPublicKey.getParams();
63746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_DSA(
64746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    dsaParams.getP().toByteArray(),
65746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    dsaParams.getQ().toByteArray(),
66746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    dsaParams.getG().toByteArray(),
67746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    dsaPublicKey.getY().toByteArray(),
68746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    null));
69746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } catch (Exception e) {
70746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            throw new InvalidKeyException(e);
71746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
72746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
73746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
74746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    @Override
75746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    public DSAParams getParams() {
76746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        ensureReadParams();
77746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        return params;
78746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
79746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
80746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    @Override
81746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    public String getAlgorithm() {
82746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        return "DSA";
83746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
84746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
85746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    @Override
86746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    public String getFormat() {
87746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        return "X.509";
88746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
89746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
90746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    @Override
91746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    public byte[] getEncoded() {
92746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        return NativeCrypto.i2d_PUBKEY(key.getPkeyContext());
93746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
94746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
95746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    @Override
96746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    public BigInteger getY() {
97746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        ensureReadParams();
98746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        return params.getY();
99746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
100d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
101d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    @Override
102d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    public boolean equals(Object o) {
103d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        if (o == this) {
104d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root            return true;
105d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        }
106d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
107d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        if (o instanceof OpenSSLDSAPublicKey) {
108d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root            OpenSSLDSAPublicKey other = (OpenSSLDSAPublicKey) o;
109d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
110d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root            /*
111d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root             * We can shortcut the true case, but it still may be equivalent but
112d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root             * different copies.
113d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root             */
114d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root            if (key.equals(other.getOpenSSLKey())) {
115d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root                return true;
116d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root            }
117d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        }
118d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
119d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        if (!(o instanceof DSAPublicKey)) {
120d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root            return false;
121d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        }
122d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
123d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        ensureReadParams();
124d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
125d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        DSAPublicKey other = (DSAPublicKey) o;
126d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        return params.getY().equals(other.getY()) && params.equals(other.getParams());
127d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    }
128d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
129d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    @Override
130d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    public int hashCode() {
131d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        ensureReadParams();
132d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
133d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        return params.getY().hashCode() ^ params.hashCode();
134d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    }
135d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
136d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    @Override
137d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    public String toString() {
138d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        ensureReadParams();
139d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
140d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        final StringBuilder sb = new StringBuilder("OpenSSLDSAPublicKey{");
141d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        sb.append("Y=");
142d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        sb.append(params.getY().toString(16));
143d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        sb.append(',');
144d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        sb.append("params=");
145d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        sb.append(params.toString());
146d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        sb.append('}');
147d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root
148d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root        return sb.toString();
149d036721c2ecd146acef9f36408c7a397dd0a0785Kenny Root    }
150746a236e2be5dee62c482e27f4c682496d071d8bKenny Root}
151