SslCertificate.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/*
2 * Copyright (C) 2006 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 android.net.http;
18
19import android.os.Bundle;
20
21import java.text.DateFormat;
22import java.util.Vector;
23
24import java.security.cert.X509Certificate;
25
26import org.bouncycastle.asn1.DERObjectIdentifier;
27import org.bouncycastle.asn1.x509.X509Name;
28
29/**
30 * SSL certificate info (certificate details) class
31 */
32public class SslCertificate {
33
34    /**
35     * Name of the entity this certificate is issued to
36     */
37    private DName mIssuedTo;
38
39    /**
40     * Name of the entity this certificate is issued by
41     */
42    private DName mIssuedBy;
43
44    /**
45     * Not-before date from the validity period
46     */
47    private String mValidNotBefore;
48
49    /**
50     * Not-after date from the validity period
51     */
52    private String mValidNotAfter;
53
54     /**
55     * Bundle key names
56     */
57    private static final String ISSUED_TO = "issued-to";
58    private static final String ISSUED_BY = "issued-by";
59    private static final String VALID_NOT_BEFORE = "valid-not-before";
60    private static final String VALID_NOT_AFTER = "valid-not-after";
61
62    /**
63     * Saves the certificate state to a bundle
64     * @param certificate The SSL certificate to store
65     * @return A bundle with the certificate stored in it or null if fails
66     */
67    public static Bundle saveState(SslCertificate certificate) {
68        Bundle bundle = null;
69
70        if (certificate != null) {
71            bundle = new Bundle();
72
73            bundle.putString(ISSUED_TO, certificate.getIssuedTo().getDName());
74            bundle.putString(ISSUED_BY, certificate.getIssuedBy().getDName());
75
76            bundle.putString(VALID_NOT_BEFORE, certificate.getValidNotBefore());
77            bundle.putString(VALID_NOT_AFTER, certificate.getValidNotAfter());
78        }
79
80        return bundle;
81    }
82
83    /**
84     * Restores the certificate stored in the bundle
85     * @param bundle The bundle with the certificate state stored in it
86     * @return The SSL certificate stored in the bundle or null if fails
87     */
88    public static SslCertificate restoreState(Bundle bundle) {
89        if (bundle != null) {
90            return new SslCertificate(
91                bundle.getString(ISSUED_TO),
92                bundle.getString(ISSUED_BY),
93                bundle.getString(VALID_NOT_BEFORE),
94                bundle.getString(VALID_NOT_AFTER));
95        }
96
97        return null;
98    }
99
100    /**
101     * Creates a new SSL certificate object
102     * @param issuedTo The entity this certificate is issued to
103     * @param issuedBy The entity that issued this certificate
104     * @param validNotBefore The not-before date from the certificate validity period
105     * @param validNotAfter The not-after date from the certificate validity period
106     */
107    public SslCertificate(
108        String issuedTo, String issuedBy, String validNotBefore, String validNotAfter) {
109        mIssuedTo = new DName(issuedTo);
110        mIssuedBy = new DName(issuedBy);
111
112        mValidNotBefore = validNotBefore;
113        mValidNotAfter = validNotAfter;
114    }
115
116    /**
117     * Creates a new SSL certificate object from an X509 certificate
118     * @param certificate X509 certificate
119     */
120    public SslCertificate(X509Certificate certificate) {
121        this(certificate.getSubjectDN().getName(),
122             certificate.getIssuerDN().getName(),
123             DateFormat.getInstance().format(certificate.getNotBefore()),
124             DateFormat.getInstance().format(certificate.getNotAfter()));
125    }
126
127    /**
128     * @return Not-before date from the certificate validity period or
129     * "" if none has been set
130     */
131    public String getValidNotBefore() {
132        return mValidNotBefore != null ? mValidNotBefore : "";
133    }
134
135    /**
136     * @return Not-after date from the certificate validity period or
137     * "" if none has been set
138     */
139    public String getValidNotAfter() {
140        return mValidNotAfter != null ? mValidNotAfter : "";
141    }
142
143    /**
144     * @return Issued-to distinguished name or null if none has been set
145     */
146    public DName getIssuedTo() {
147        return mIssuedTo;
148    }
149
150    /**
151     * @return Issued-by distinguished name or null if none has been set
152     */
153    public DName getIssuedBy() {
154        return mIssuedBy;
155    }
156
157    /**
158     * @return A string representation of this certificate for debugging
159     */
160    public String toString() {
161        return
162            "Issued to: " + mIssuedTo.getDName() + ";\n" +
163            "Issued by: " + mIssuedBy.getDName() + ";\n";
164    }
165
166    /**
167     * A distinguished name helper class: a 3-tuple of:
168     * - common name (CN),
169     * - organization (O),
170     * - organizational unit (OU)
171     */
172    public class DName {
173        /**
174         * Distinguished name (normally includes CN, O, and OU names)
175         */
176        private String mDName;
177
178        /**
179         * Common-name (CN) component of the name
180         */
181        private String mCName;
182
183        /**
184         * Organization (O) component of the name
185         */
186        private String mOName;
187
188        /**
189         * Organizational Unit (OU) component of the name
190         */
191        private String mUName;
192
193        /**
194         * Creates a new distinguished name
195         * @param dName The distinguished name
196         */
197        public DName(String dName) {
198            if (dName != null) {
199                X509Name x509Name = new X509Name(mDName = dName);
200
201                Vector val = x509Name.getValues();
202                Vector oid = x509Name.getOIDs();
203
204                for (int i = 0; i < oid.size(); i++) {
205                    if (oid.elementAt(i).equals(X509Name.CN)) {
206                        mCName = (String) val.elementAt(i);
207                        continue;
208                    }
209
210                    if (oid.elementAt(i).equals(X509Name.O)) {
211                        mOName = (String) val.elementAt(i);
212                        continue;
213                    }
214
215                    if (oid.elementAt(i).equals(X509Name.OU)) {
216                        mUName = (String) val.elementAt(i);
217                        continue;
218                    }
219                }
220            }
221        }
222
223        /**
224         * @return The distinguished name (normally includes CN, O, and OU names)
225         */
226        public String getDName() {
227            return mDName != null ? mDName : "";
228        }
229
230        /**
231         * @return The Common-name (CN) component of this name
232         */
233        public String getCName() {
234            return mCName != null ? mCName : "";
235        }
236
237        /**
238         * @return The Organization (O) component of this name
239         */
240        public String getOName() {
241            return mOName != null ? mOName : "";
242        }
243
244        /**
245         * @return The Organizational Unit (OU) component of this name
246         */
247        public String getUName() {
248            return mUName != null ? mUName : "";
249        }
250    }
251}
252