1aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root/*
2aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root * Copyright (C) 2012 The Android Open Source Project
3aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root *
4aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root * you may not use this file except in compliance with the License.
6aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root * You may obtain a copy of the License at
7aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root *
8aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root *
10aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root * Unless required by applicable law or agreed to in writing, software
11aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root * See the License for the specific language governing permissions and
14aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root * limitations under the License.
15aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root */
16aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt;
18aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
19aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Rootimport java.io.IOException;
20aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Rootimport java.io.NotSerializableException;
21aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Rootimport java.io.ObjectInputStream;
22aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Rootimport java.io.ObjectOutputStream;
23aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootimport java.math.BigInteger;
24aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootimport java.security.InvalidKeyException;
25aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootimport java.security.interfaces.DSAParams;
26aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootimport java.security.interfaces.DSAPrivateKey;
27aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootimport java.security.spec.DSAPrivateKeySpec;
28aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootimport java.security.spec.InvalidKeySpecException;
29aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
3047cc520bd63c1eabfdef23cbab10457701f2a395Kenny Rootpublic class OpenSSLDSAPrivateKey implements DSAPrivateKey, OpenSSLKeyHolder {
31c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    private static final long serialVersionUID = 6524734576187424628L;
32c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
33aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root    private transient OpenSSLKey key;
34aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
35aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root    private transient OpenSSLDSAParams params;
36aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
37aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    OpenSSLDSAPrivateKey(OpenSSLKey key) {
38aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        this.key = key;
39aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
40aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
4147cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root    @Override
4247cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root    public OpenSSLKey getOpenSSLKey() {
439df6cea08a4eb527ba5b6fc9275e8b0571c12892Kenny Root        return key;
449df6cea08a4eb527ba5b6fc9275e8b0571c12892Kenny Root    }
459df6cea08a4eb527ba5b6fc9275e8b0571c12892Kenny Root
46aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    OpenSSLDSAPrivateKey(DSAPrivateKeySpec dsaKeySpec) throws InvalidKeySpecException {
47aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        try {
48aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root            key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_DSA(
49aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    dsaKeySpec.getP().toByteArray(),
50aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    dsaKeySpec.getQ().toByteArray(),
51aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    dsaKeySpec.getG().toByteArray(),
52aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    null,
53aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    dsaKeySpec.getX().toByteArray()));
54aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        } catch (Exception e) {
55aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root            throw new InvalidKeySpecException(e);
56aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        }
57aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
58aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
59aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    private void ensureReadParams() {
60aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        if (params == null) {
61aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root            params = new OpenSSLDSAParams(key);
62aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        }
63aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
64aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
65aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    static OpenSSLKey getInstance(DSAPrivateKey dsaPrivateKey) throws InvalidKeyException {
66f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root        /**
67f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root         * If the key is not encodable (PKCS11-like key), then wrap it and use
68f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root         * JNI upcalls to satisfy requests.
69f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root         */
70f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root        if (dsaPrivateKey.getFormat() == null) {
71f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root            return wrapPlatformKey(dsaPrivateKey);
72f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root        }
73f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root
74aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        try {
75aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root            DSAParams dsaParams = dsaPrivateKey.getParams();
76aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root            return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_DSA(
77aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    dsaParams.getP().toByteArray(),
78aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    dsaParams.getQ().toByteArray(),
79aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    dsaParams.getG().toByteArray(),
80aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    null,
81aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root                    dsaPrivateKey.getX().toByteArray()));
82aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        } catch (Exception e) {
83aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root            throw new InvalidKeyException(e);
84aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        }
85aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
86aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
87f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root    public static OpenSSLKey wrapPlatformKey(DSAPrivateKey dsaPrivateKey) {
88dac92c69d3a147ea57bc7bd28c96b6365c1988e2Kenny Root        return new OpenSSLKey(NativeCrypto.getDSAPrivateKeyWrapper(dsaPrivateKey), true);
89f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root    }
90f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root
91aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    @Override
92aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    public DSAParams getParams() {
93aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        ensureReadParams();
94aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        return params;
95aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
96aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
97aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    @Override
98aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    public String getAlgorithm() {
99aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        return "DSA";
100aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
101aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
102aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    @Override
103aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    public String getFormat() {
104a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root        /*
105a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root         * If we're using an OpenSSL ENGINE, there's no guarantee we can export
106a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root         * the key. Returning {@code null} tells the caller that there's no
107a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root         * encoded format.
108a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root         */
109b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        if (key.isEngineBased()) {
110a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root            return null;
111a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root        }
112a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root
113aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        return "PKCS#8";
114aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
115aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
116aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    @Override
117aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    public byte[] getEncoded() {
118a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root        /*
119a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root         * If we're using an OpenSSL ENGINE, there's no guarantee we can export
120a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root         * the key. Returning {@code null} tells the caller that there's no
121a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root         * encoded format.
122a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root         */
123b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        if (key.isEngineBased()) {
124a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root            return null;
125a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root        }
126a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root
127aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        return NativeCrypto.i2d_PKCS8_PRIV_KEY_INFO(key.getPkeyContext());
128aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
129aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
130aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    @Override
131aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    public BigInteger getX() {
132f42ec17cfa43a002814e901d63ae8a93d77f7fc3Kenny Root        if (key.isEngineBased()) {
133f42ec17cfa43a002814e901d63ae8a93d77f7fc3Kenny Root            throw new UnsupportedOperationException("private key value X cannot be extracted");
134f42ec17cfa43a002814e901d63ae8a93d77f7fc3Kenny Root        }
135f42ec17cfa43a002814e901d63ae8a93d77f7fc3Kenny Root
136aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        ensureReadParams();
137aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        return params.getX();
138aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
139c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
140c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    @Override
141c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    public boolean equals(Object o) {
142c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        if (o == this) {
143c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root            return true;
144c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        }
145c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
146c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        if (o instanceof OpenSSLDSAPrivateKey) {
147c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root            OpenSSLDSAPrivateKey other = (OpenSSLDSAPrivateKey) o;
148c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
149c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root            /*
150c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root             * We can shortcut the true case, but it still may be equivalent but
151c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root             * different copies.
152c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root             */
153c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root            if (key.equals(other.getOpenSSLKey())) {
154c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root                return true;
155c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root            }
156c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        }
157c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
158c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        if (!(o instanceof DSAPrivateKey)) {
159c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root            return false;
160c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        }
161c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
162c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        ensureReadParams();
163c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
164b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        final BigInteger x = params.getX();
165b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        if (x == null) {
166b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root            /*
167b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root             * If our X is null, we can't tell if these two private keys are
168b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root             * equivalent. This usually happens if this key is ENGINE-based. If
169b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root             * the other key was ENGINE-based, we should have caught it in the
170b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root             * OpenSSLDSAPrivateKey case.
171b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root             */
172b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root            return false;
173b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        }
174b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root
175b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        final DSAPrivateKey other = (DSAPrivateKey) o;
176b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        return x.equals(other.getX()) && params.equals(other.getParams());
177c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    }
178c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
179c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    @Override
180c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    public int hashCode() {
181c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        ensureReadParams();
182c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
183b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        int hash = 1;
184b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root
185b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        final BigInteger x = getX();
186b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        if (x != null) {
187b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root            hash = hash * 3 + x.hashCode();
188b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        }
189b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root
190b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        hash = hash * 7 + params.hashCode();
191b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root
192b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        return hash;
193c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    }
194c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
195c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    @Override
196c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    public String toString() {
197c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        final StringBuilder sb = new StringBuilder("OpenSSLDSAPrivateKey{");
198a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root
199b4fa75e1c6216696157135b6103eedb75f772f14Kenny Root        if (key.isEngineBased()) {
200a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root            sb.append("key=");
201a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root            sb.append(key);
202a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root            sb.append('}');
203a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root            return sb.toString();
204a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root        }
205a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root
206a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root        ensureReadParams();
207c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        sb.append("X=");
208c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        sb.append(params.getX().toString(16));
209c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        sb.append(',');
210c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        sb.append("params=");
211c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        sb.append(params.toString());
212c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        sb.append('}');
213c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root
214c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root        return sb.toString();
215c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root    }
216aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root
217aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
218aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        stream.defaultReadObject();
219aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root
220aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        final BigInteger g = (BigInteger) stream.readObject();
221aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        final BigInteger p = (BigInteger) stream.readObject();
222aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        final BigInteger q = (BigInteger) stream.readObject();
223aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        final BigInteger x = (BigInteger) stream.readObject();
224aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root
225aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_DSA(
226aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root                p.toByteArray(),
227aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root                q.toByteArray(),
228aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root                g.toByteArray(),
229aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root                null,
230aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root                x.toByteArray()));
231aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root    }
232aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root
233aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root    private void writeObject(ObjectOutputStream stream) throws IOException {
234aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        if (getOpenSSLKey().isEngineBased()) {
235aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root            throw new NotSerializableException("engine-based keys can not be serialized");
236aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        }
237f42ec17cfa43a002814e901d63ae8a93d77f7fc3Kenny Root
238aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        stream.defaultWriteObject();
239aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root
240aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        ensureReadParams();
241aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        stream.writeObject(params.getG());
242aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        stream.writeObject(params.getP());
243aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        stream.writeObject(params.getQ());
244aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root        stream.writeObject(params.getX());
245aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root    }
246aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root}
247