blob: 01dd08f4ad9c886d4d3c833b7562ece933da2a73 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Adam Vartanian882eb1862019-03-01 13:58:28 +000019import android.annotation.Nullable;
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010020import android.annotation.UnsupportedAppUsage;
Brian Carlstrom6da00332011-06-26 21:08:03 -070021import android.content.Context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.os.Bundle;
Brian Carlstrom6da00332011-06-26 21:08:03 -070023import android.text.format.DateFormat;
24import android.view.LayoutInflater;
25import android.view.View;
26import android.widget.TextView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
Adam Vartanian6309c612018-07-27 10:35:14 +010028import com.android.internal.util.HexDump;
29import com.android.org.bouncycastle.asn1.x509.X509Name;
30
Brian Carlstrom4a062812011-07-05 17:28:44 -070031import java.io.ByteArrayInputStream;
32import java.math.BigInteger;
33import java.security.MessageDigest;
34import java.security.NoSuchAlgorithmException;
35import java.security.cert.Certificate;
36import java.security.cert.CertificateEncodingException;
37import java.security.cert.CertificateException;
38import java.security.cert.CertificateFactory;
Brian Carlstrom6da00332011-06-26 21:08:03 -070039import java.security.cert.X509Certificate;
Brian Carlstrom445d8f12010-03-02 10:02:19 -080040import java.text.ParseException;
41import java.text.SimpleDateFormat;
42import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import java.util.Vector;
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045/**
46 * SSL certificate info (certificate details) class
47 */
48public class SslCertificate {
49
50 /**
Brian Carlstrom445d8f12010-03-02 10:02:19 -080051 * SimpleDateFormat pattern for an ISO 8601 date
52 */
53 private static String ISO_8601_DATE_FORMAT = "yyyy-MM-dd HH:mm:ssZ";
54
55 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056 * Name of the entity this certificate is issued to
57 */
Brian Carlstrom4a062812011-07-05 17:28:44 -070058 private final DName mIssuedTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059
60 /**
61 * Name of the entity this certificate is issued by
62 */
Brian Carlstrom4a062812011-07-05 17:28:44 -070063 private final DName mIssuedBy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064
65 /**
66 * Not-before date from the validity period
67 */
Brian Carlstrom4a062812011-07-05 17:28:44 -070068 private final Date mValidNotBefore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069
70 /**
71 * Not-after date from the validity period
72 */
Brian Carlstrom4a062812011-07-05 17:28:44 -070073 private final Date mValidNotAfter;
74
75 /**
76 * The original source certificate, if available.
77 *
78 * TODO If deprecated constructors are removed, this should always
79 * be available, and saveState and restoreState can be simplified
80 * to be unconditional.
81 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010082 @UnsupportedAppUsage
Brian Carlstrom4a062812011-07-05 17:28:44 -070083 private final X509Certificate mX509Certificate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084
Brian Carlstrom6da00332011-06-26 21:08:03 -070085 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 * Bundle key names
87 */
88 private static final String ISSUED_TO = "issued-to";
89 private static final String ISSUED_BY = "issued-by";
90 private static final String VALID_NOT_BEFORE = "valid-not-before";
91 private static final String VALID_NOT_AFTER = "valid-not-after";
Brian Carlstrom4a062812011-07-05 17:28:44 -070092 private static final String X509_CERTIFICATE = "x509-certificate";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093
94 /**
95 * Saves the certificate state to a bundle
96 * @param certificate The SSL certificate to store
97 * @return A bundle with the certificate stored in it or null if fails
98 */
99 public static Bundle saveState(SslCertificate certificate) {
Brian Carlstrom4a062812011-07-05 17:28:44 -0700100 if (certificate == null) {
101 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 }
Brian Carlstrom4a062812011-07-05 17:28:44 -0700103 Bundle bundle = new Bundle();
104 bundle.putString(ISSUED_TO, certificate.getIssuedTo().getDName());
105 bundle.putString(ISSUED_BY, certificate.getIssuedBy().getDName());
106 bundle.putString(VALID_NOT_BEFORE, certificate.getValidNotBefore());
107 bundle.putString(VALID_NOT_AFTER, certificate.getValidNotAfter());
108 X509Certificate x509Certificate = certificate.mX509Certificate;
109 if (x509Certificate != null) {
110 try {
111 bundle.putByteArray(X509_CERTIFICATE, x509Certificate.getEncoded());
112 } catch (CertificateEncodingException ignored) {
113 }
114 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 return bundle;
116 }
117
118 /**
119 * Restores the certificate stored in the bundle
120 * @param bundle The bundle with the certificate state stored in it
121 * @return The SSL certificate stored in the bundle or null if fails
122 */
123 public static SslCertificate restoreState(Bundle bundle) {
Brian Carlstrom4a062812011-07-05 17:28:44 -0700124 if (bundle == null) {
125 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 }
Brian Carlstrom4a062812011-07-05 17:28:44 -0700127 X509Certificate x509Certificate;
128 byte[] bytes = bundle.getByteArray(X509_CERTIFICATE);
129 if (bytes == null) {
130 x509Certificate = null;
131 } else {
132 try {
133 CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
134 Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes));
135 x509Certificate = (X509Certificate) cert;
136 } catch (CertificateException e) {
137 x509Certificate = null;
138 }
139 }
140 return new SslCertificate(bundle.getString(ISSUED_TO),
141 bundle.getString(ISSUED_BY),
142 parseDate(bundle.getString(VALID_NOT_BEFORE)),
143 parseDate(bundle.getString(VALID_NOT_AFTER)),
144 x509Certificate);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 }
146
147 /**
148 * Creates a new SSL certificate object
149 * @param issuedTo The entity this certificate is issued to
150 * @param issuedBy The entity that issued this certificate
Brian Carlstrom6da00332011-06-26 21:08:03 -0700151 * @param validNotBefore The not-before date from the certificate
152 * validity period in ISO 8601 format
153 * @param validNotAfter The not-after date from the certificate
154 * validity period in ISO 8601 format
Brian Carlstromcc687c52011-02-16 11:40:15 -0800155 * @deprecated Use {@link #SslCertificate(X509Certificate)}
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800156 */
Jesse Wilson28c74252010-11-04 14:09:18 -0700157 @Deprecated
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800158 public SslCertificate(
159 String issuedTo, String issuedBy, String validNotBefore, String validNotAfter) {
Brian Carlstrom4a062812011-07-05 17:28:44 -0700160 this(issuedTo, issuedBy, parseDate(validNotBefore), parseDate(validNotAfter), null);
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800161 }
162
163 /**
164 * Creates a new SSL certificate object
165 * @param issuedTo The entity this certificate is issued to
166 * @param issuedBy The entity that issued this certificate
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 * @param validNotBefore The not-before date from the certificate validity period
168 * @param validNotAfter The not-after date from the certificate validity period
Brian Carlstromcc687c52011-02-16 11:40:15 -0800169 * @deprecated Use {@link #SslCertificate(X509Certificate)}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 */
Brian Carlstromcc687c52011-02-16 11:40:15 -0800171 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 public SslCertificate(
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800173 String issuedTo, String issuedBy, Date validNotBefore, Date validNotAfter) {
Brian Carlstrom4a062812011-07-05 17:28:44 -0700174 this(issuedTo, issuedBy, validNotBefore, validNotAfter, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 }
176
177 /**
178 * Creates a new SSL certificate object from an X509 certificate
179 * @param certificate X509 certificate
180 */
181 public SslCertificate(X509Certificate certificate) {
182 this(certificate.getSubjectDN().getName(),
183 certificate.getIssuerDN().getName(),
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800184 certificate.getNotBefore(),
Brian Carlstrom4a062812011-07-05 17:28:44 -0700185 certificate.getNotAfter(),
186 certificate);
187 }
188
189 private SslCertificate(
190 String issuedTo, String issuedBy,
191 Date validNotBefore, Date validNotAfter,
192 X509Certificate x509Certificate) {
193 mIssuedTo = new DName(issuedTo);
194 mIssuedBy = new DName(issuedBy);
195 mValidNotBefore = cloneDate(validNotBefore);
196 mValidNotAfter = cloneDate(validNotAfter);
197 mX509Certificate = x509Certificate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 }
199
200 /**
201 * @return Not-before date from the certificate validity period or
202 * "" if none has been set
203 */
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800204 public Date getValidNotBeforeDate() {
Brian Carlstroma5987a52010-03-02 14:51:22 -0800205 return cloneDate(mValidNotBefore);
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800206 }
207
208 /**
209 * @return Not-before date from the certificate validity period in
210 * ISO 8601 format or "" if none has been set
211 *
212 * @deprecated Use {@link #getValidNotBeforeDate()}
213 */
Jesse Wilson28c74252010-11-04 14:09:18 -0700214 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 public String getValidNotBefore() {
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800216 return formatDate(mValidNotBefore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 }
218
219 /**
220 * @return Not-after date from the certificate validity period or
221 * "" if none has been set
222 */
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800223 public Date getValidNotAfterDate() {
Brian Carlstroma5987a52010-03-02 14:51:22 -0800224 return cloneDate(mValidNotAfter);
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800225 }
226
227 /**
228 * @return Not-after date from the certificate validity period in
229 * ISO 8601 format or "" if none has been set
230 *
Brian Carlstrom9147a0e2010-03-02 11:24:39 -0800231 * @deprecated Use {@link #getValidNotAfterDate()}
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800232 */
Jesse Wilson28c74252010-11-04 14:09:18 -0700233 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 public String getValidNotAfter() {
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800235 return formatDate(mValidNotAfter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 }
237
238 /**
239 * @return Issued-to distinguished name or null if none has been set
240 */
241 public DName getIssuedTo() {
242 return mIssuedTo;
243 }
244
245 /**
246 * @return Issued-by distinguished name or null if none has been set
247 */
248 public DName getIssuedBy() {
249 return mIssuedBy;
250 }
251
252 /**
Adam Vartanian6309c612018-07-27 10:35:14 +0100253 * @return The {@code X509Certificate} used to create this {@code SslCertificate} or
254 * {@code null} if no certificate was provided.
255 */
Adam Vartanian882eb1862019-03-01 13:58:28 +0000256 public @Nullable X509Certificate getX509Certificate() {
Adam Vartanian6309c612018-07-27 10:35:14 +0100257 return mX509Certificate;
258 }
259
260 /**
Brian Carlstrom4a062812011-07-05 17:28:44 -0700261 * Convenience for UI presentation, not intended as public API.
262 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100263 @UnsupportedAppUsage
Brian Carlstrom4a062812011-07-05 17:28:44 -0700264 private static String getSerialNumber(X509Certificate x509Certificate) {
265 if (x509Certificate == null) {
266 return "";
267 }
268 BigInteger serialNumber = x509Certificate.getSerialNumber();
269 if (serialNumber == null) {
270 return "";
271 }
272 return fingerprint(serialNumber.toByteArray());
273 }
274
275 /**
276 * Convenience for UI presentation, not intended as public API.
277 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100278 @UnsupportedAppUsage
Brian Carlstrom4a062812011-07-05 17:28:44 -0700279 private static String getDigest(X509Certificate x509Certificate, String algorithm) {
280 if (x509Certificate == null) {
281 return "";
282 }
283 try {
284 byte[] bytes = x509Certificate.getEncoded();
285 MessageDigest md = MessageDigest.getInstance(algorithm);
286 byte[] digest = md.digest(bytes);
287 return fingerprint(digest);
288 } catch (CertificateEncodingException ignored) {
289 return "";
290 } catch (NoSuchAlgorithmException ignored) {
291 return "";
292 }
293 }
294
295 private static final String fingerprint(byte[] bytes) {
296 if (bytes == null) {
297 return "";
298 }
299 StringBuilder sb = new StringBuilder();
300 for (int i = 0; i < bytes.length; i++) {
301 byte b = bytes[i];
Przemyslaw Szczepaniak3f726042015-10-15 11:04:19 +0100302 HexDump.appendByteAsHex(sb, b, true);
Brian Carlstrom4a062812011-07-05 17:28:44 -0700303 if (i+1 != bytes.length) {
304 sb.append(':');
305 }
306 }
307 return sb.toString();
308 }
309
310 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 * @return A string representation of this certificate for debugging
312 */
313 public String toString() {
Brian Carlstrom6da00332011-06-26 21:08:03 -0700314 return ("Issued to: " + mIssuedTo.getDName() + ";\n"
315 + "Issued by: " + mIssuedBy.getDName() + ";\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 }
317
318 /**
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800319 * Parse an ISO 8601 date converting ParseExceptions to a null result;
320 */
321 private static Date parseDate(String string) {
322 try {
323 return new SimpleDateFormat(ISO_8601_DATE_FORMAT).parse(string);
324 } catch (ParseException e) {
325 return null;
326 }
327 }
328
329 /**
330 * Format a date as an ISO 8601 string, return "" for a null date
331 */
332 private static String formatDate(Date date) {
333 if (date == null) {
334 return "";
335 }
336 return new SimpleDateFormat(ISO_8601_DATE_FORMAT).format(date);
337 }
338
339 /**
Brian Carlstroma5987a52010-03-02 14:51:22 -0800340 * Clone a possibly null Date
341 */
342 private static Date cloneDate(Date date) {
343 if (date == null) {
344 return null;
345 }
346 return (Date) date.clone();
347 }
348
349 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 * A distinguished name helper class: a 3-tuple of:
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800351 * <ul>
352 * <li>the most specific common name (CN)</li>
353 * <li>the most specific organization (O)</li>
354 * <li>the most specific organizational unit (OU)</li>
355 * <ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 */
357 public class DName {
358 /**
359 * Distinguished name (normally includes CN, O, and OU names)
360 */
361 private String mDName;
362
363 /**
364 * Common-name (CN) component of the name
365 */
366 private String mCName;
367
368 /**
369 * Organization (O) component of the name
370 */
371 private String mOName;
372
373 /**
374 * Organizational Unit (OU) component of the name
375 */
376 private String mUName;
377
378 /**
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800379 * Creates a new {@code DName} from a string. The attributes
380 * are assumed to come in most significant to least
381 * significant order which is true of human readable values
382 * returned by methods such as {@code X500Principal.getName()}.
383 * Be aware that the underlying sources of distinguished names
384 * such as instances of {@code X509Certificate} are encoded in
385 * least significant to most significant order, so make sure
386 * the value passed here has the expected ordering of
387 * attributes.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 */
389 public DName(String dName) {
390 if (dName != null) {
Brian Carlstrom65051222010-01-26 23:07:42 -0800391 mDName = dName;
392 try {
393 X509Name x509Name = new X509Name(dName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394
Brian Carlstrom65051222010-01-26 23:07:42 -0800395 Vector val = x509Name.getValues();
396 Vector oid = x509Name.getOIDs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397
Brian Carlstrom65051222010-01-26 23:07:42 -0800398 for (int i = 0; i < oid.size(); i++) {
399 if (oid.elementAt(i).equals(X509Name.CN)) {
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800400 if (mCName == null) {
401 mCName = (String) val.elementAt(i);
402 }
Brian Carlstrom65051222010-01-26 23:07:42 -0800403 continue;
404 }
405
406 if (oid.elementAt(i).equals(X509Name.O)) {
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800407 if (mOName == null) {
408 mOName = (String) val.elementAt(i);
409 continue;
410 }
Brian Carlstrom65051222010-01-26 23:07:42 -0800411 }
412
413 if (oid.elementAt(i).equals(X509Name.OU)) {
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800414 if (mUName == null) {
415 mUName = (String) val.elementAt(i);
416 continue;
417 }
Brian Carlstrom65051222010-01-26 23:07:42 -0800418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 }
Brian Carlstrom65051222010-01-26 23:07:42 -0800420 } catch (IllegalArgumentException ex) {
421 // thrown if there is an error parsing the string
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 }
423 }
424 }
425
426 /**
427 * @return The distinguished name (normally includes CN, O, and OU names)
428 */
429 public String getDName() {
430 return mDName != null ? mDName : "";
431 }
432
433 /**
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800434 * @return The most specific Common-name (CN) component of this name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 */
436 public String getCName() {
437 return mCName != null ? mCName : "";
438 }
439
440 /**
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800441 * @return The most specific Organization (O) component of this name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 */
443 public String getOName() {
444 return mOName != null ? mOName : "";
445 }
446
447 /**
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800448 * @return The most specific Organizational Unit (OU) component of this name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 */
450 public String getUName() {
451 return mUName != null ? mUName : "";
452 }
453 }
Brian Carlstrom6da00332011-06-26 21:08:03 -0700454
455 /**
456 * Inflates the SSL certificate view (helper method).
457 * @return The resultant certificate view with issued-to, issued-by,
458 * issued-on, expires-on, and possibly other fields set.
Brian Carlstrom6da00332011-06-26 21:08:03 -0700459 *
460 * @hide Used by Browser and Settings
461 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100462 @UnsupportedAppUsage
Brian Carlstrom6da00332011-06-26 21:08:03 -0700463 public View inflateCertificateView(Context context) {
464 LayoutInflater factory = LayoutInflater.from(context);
465
466 View certificateView = factory.inflate(
467 com.android.internal.R.layout.ssl_certificate, null);
468
469 // issued to:
470 SslCertificate.DName issuedTo = getIssuedTo();
471 if (issuedTo != null) {
472 ((TextView) certificateView.findViewById(com.android.internal.R.id.to_common))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700473 .setText(issuedTo.getCName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700474 ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700475 .setText(issuedTo.getOName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700476 ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org_unit))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700477 .setText(issuedTo.getUName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700478 }
Brian Carlstrom4a062812011-07-05 17:28:44 -0700479 // serial number:
480 ((TextView) certificateView.findViewById(com.android.internal.R.id.serial_number))
481 .setText(getSerialNumber(mX509Certificate));
Brian Carlstrom6da00332011-06-26 21:08:03 -0700482
483 // issued by:
484 SslCertificate.DName issuedBy = getIssuedBy();
485 if (issuedBy != null) {
486 ((TextView) certificateView.findViewById(com.android.internal.R.id.by_common))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700487 .setText(issuedBy.getCName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700488 ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700489 .setText(issuedBy.getOName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700490 ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org_unit))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700491 .setText(issuedBy.getUName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700492 }
493
494 // issued on:
495 String issuedOn = formatCertificateDate(context, getValidNotBeforeDate());
496 ((TextView) certificateView.findViewById(com.android.internal.R.id.issued_on))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700497 .setText(issuedOn);
Brian Carlstrom6da00332011-06-26 21:08:03 -0700498
499 // expires on:
500 String expiresOn = formatCertificateDate(context, getValidNotAfterDate());
501 ((TextView) certificateView.findViewById(com.android.internal.R.id.expires_on))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700502 .setText(expiresOn);
503
504 // fingerprints:
505 ((TextView) certificateView.findViewById(com.android.internal.R.id.sha256_fingerprint))
506 .setText(getDigest(mX509Certificate, "SHA256"));
507 ((TextView) certificateView.findViewById(com.android.internal.R.id.sha1_fingerprint))
508 .setText(getDigest(mX509Certificate, "SHA1"));
Brian Carlstrom6da00332011-06-26 21:08:03 -0700509
510 return certificateView;
511 }
512
513 /**
514 * Formats the certificate date to a properly localized date string.
515 * @return Properly localized version of the certificate date string and
516 * the "" if it fails to localize.
517 */
518 private String formatCertificateDate(Context context, Date certificateDate) {
519 if (certificateDate == null) {
520 return "";
521 }
Charles He2b47e742017-02-20 17:32:12 +0000522 return DateFormat.getMediumDateFormat(context).format(certificateDate);
Brian Carlstrom6da00332011-06-26 21:08:03 -0700523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524}