OpenSSLDSAPrivateKey.java revision 908975092f7ac7b7562f242c5fd99fbf228acf0f
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.DSAParams;
22import java.security.interfaces.DSAPrivateKey;
23import java.security.spec.DSAPrivateKeySpec;
24import java.security.spec.InvalidKeySpecException;
25
26public class OpenSSLDSAPrivateKey implements DSAPrivateKey {
27    private static final long serialVersionUID = 6524734576187424628L;
28
29    private final OpenSSLKey key;
30
31    private OpenSSLDSAParams params;
32
33    OpenSSLDSAPrivateKey(OpenSSLKey key) {
34        this.key = key;
35    }
36
37    OpenSSLKey getOpenSSLKey() {
38        return key;
39    }
40
41    OpenSSLDSAPrivateKey(DSAPrivateKeySpec dsaKeySpec) throws InvalidKeySpecException {
42        try {
43            key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_DSA(
44                    dsaKeySpec.getP().toByteArray(),
45                    dsaKeySpec.getQ().toByteArray(),
46                    dsaKeySpec.getG().toByteArray(),
47                    null,
48                    dsaKeySpec.getX().toByteArray()));
49        } catch (Exception e) {
50            throw new InvalidKeySpecException(e);
51        }
52    }
53
54    private void ensureReadParams() {
55        if (params == null) {
56            params = new OpenSSLDSAParams(key);
57        }
58    }
59
60    static OpenSSLKey getInstance(DSAPrivateKey dsaPrivateKey) throws InvalidKeyException {
61        try {
62            DSAParams dsaParams = dsaPrivateKey.getParams();
63            return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_DSA(
64                    dsaParams.getP().toByteArray(),
65                    dsaParams.getQ().toByteArray(),
66                    dsaParams.getG().toByteArray(),
67                    null,
68                    dsaPrivateKey.getX().toByteArray()));
69        } catch (Exception e) {
70            throw new InvalidKeyException(e);
71        }
72    }
73
74    @Override
75    public DSAParams getParams() {
76        ensureReadParams();
77        return params;
78    }
79
80    @Override
81    public String getAlgorithm() {
82        return "DSA";
83    }
84
85    @Override
86    public String getFormat() {
87        /*
88         * If we're using an OpenSSL ENGINE, there's no guarantee we can export
89         * the key. Returning {@code null} tells the caller that there's no
90         * encoded format.
91         */
92        if (key.isEngineBased()) {
93            return null;
94        }
95
96        return "PKCS#8";
97    }
98
99    @Override
100    public byte[] getEncoded() {
101        /*
102         * If we're using an OpenSSL ENGINE, there's no guarantee we can export
103         * the key. Returning {@code null} tells the caller that there's no
104         * encoded format.
105         */
106        if (key.isEngineBased()) {
107            return null;
108        }
109
110        return NativeCrypto.i2d_PKCS8_PRIV_KEY_INFO(key.getPkeyContext());
111    }
112
113    @Override
114    public BigInteger getX() {
115        ensureReadParams();
116        return params.getX();
117    }
118
119    public int getPkeyContext() {
120        return key.getPkeyContext();
121    }
122
123    @Override
124    public boolean equals(Object o) {
125        if (o == this) {
126            return true;
127        }
128
129        if (o instanceof OpenSSLDSAPrivateKey) {
130            OpenSSLDSAPrivateKey other = (OpenSSLDSAPrivateKey) o;
131
132            /*
133             * We can shortcut the true case, but it still may be equivalent but
134             * different copies.
135             */
136            if (key.equals(other.getOpenSSLKey())) {
137                return true;
138            }
139        }
140
141        if (!(o instanceof DSAPrivateKey)) {
142            return false;
143        }
144
145        ensureReadParams();
146
147        final BigInteger x = params.getX();
148        if (x == null) {
149            /*
150             * If our X is null, we can't tell if these two private keys are
151             * equivalent. This usually happens if this key is ENGINE-based. If
152             * the other key was ENGINE-based, we should have caught it in the
153             * OpenSSLDSAPrivateKey case.
154             */
155            return false;
156        }
157
158        final DSAPrivateKey other = (DSAPrivateKey) o;
159        return x.equals(other.getX()) && params.equals(other.getParams());
160    }
161
162    @Override
163    public int hashCode() {
164        ensureReadParams();
165
166        int hash = 1;
167
168        final BigInteger x = getX();
169        if (x != null) {
170            hash = hash * 3 + x.hashCode();
171        }
172
173        hash = hash * 7 + params.hashCode();
174
175        return hash;
176    }
177
178    @Override
179    public String toString() {
180        final StringBuilder sb = new StringBuilder("OpenSSLDSAPrivateKey{");
181
182        if (key.isEngineBased()) {
183            sb.append("key=");
184            sb.append(key);
185            sb.append('}');
186            return sb.toString();
187        }
188
189        ensureReadParams();
190        sb.append("X=");
191        sb.append(params.getX().toString(16));
192        sb.append(',');
193        sb.append("params=");
194        sb.append(params.toString());
195        sb.append('}');
196
197        return sb.toString();
198    }
199}
200