blob: 6fcd6ebe148aba4815bb328d06d79b334eff61f9 [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
Mathew Inwood53f089f2018-08-08 14:44:44 +010019import android.annotation.UnsupportedAppUsage;
Brian Carlstrom6da00332011-06-26 21:08:03 -070020import android.content.Context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.os.Bundle;
Brian Carlstrom6da00332011-06-26 21:08:03 -070022import android.text.format.DateFormat;
23import android.view.LayoutInflater;
24import android.view.View;
25import android.widget.TextView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026
Adam Vartanian6309c612018-07-27 10:35:14 +010027import com.android.internal.util.HexDump;
28import com.android.org.bouncycastle.asn1.x509.X509Name;
29
Brian Carlstrom4a062812011-07-05 17:28:44 -070030import java.io.ByteArrayInputStream;
31import java.math.BigInteger;
32import java.security.MessageDigest;
33import java.security.NoSuchAlgorithmException;
34import java.security.cert.Certificate;
35import java.security.cert.CertificateEncodingException;
36import java.security.cert.CertificateException;
37import java.security.cert.CertificateFactory;
Brian Carlstrom6da00332011-06-26 21:08:03 -070038import java.security.cert.X509Certificate;
Brian Carlstrom445d8f12010-03-02 10:02:19 -080039import java.text.ParseException;
40import java.text.SimpleDateFormat;
41import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import java.util.Vector;
43
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044/**
45 * SSL certificate info (certificate details) class
46 */
47public class SslCertificate {
48
49 /**
Brian Carlstrom445d8f12010-03-02 10:02:19 -080050 * SimpleDateFormat pattern for an ISO 8601 date
51 */
52 private static String ISO_8601_DATE_FORMAT = "yyyy-MM-dd HH:mm:ssZ";
53
54 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 * Name of the entity this certificate is issued to
56 */
Brian Carlstrom4a062812011-07-05 17:28:44 -070057 private final DName mIssuedTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59 /**
60 * Name of the entity this certificate is issued by
61 */
Brian Carlstrom4a062812011-07-05 17:28:44 -070062 private final DName mIssuedBy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063
64 /**
65 * Not-before date from the validity period
66 */
Brian Carlstrom4a062812011-07-05 17:28:44 -070067 private final Date mValidNotBefore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068
69 /**
70 * Not-after date from the validity period
71 */
Brian Carlstrom4a062812011-07-05 17:28:44 -070072 private final Date mValidNotAfter;
73
74 /**
75 * The original source certificate, if available.
76 *
77 * TODO If deprecated constructors are removed, this should always
78 * be available, and saveState and restoreState can be simplified
79 * to be unconditional.
80 */
Mathew Inwood53f089f2018-08-08 14:44:44 +010081 @UnsupportedAppUsage
Brian Carlstrom4a062812011-07-05 17:28:44 -070082 private final X509Certificate mX509Certificate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083
Brian Carlstrom6da00332011-06-26 21:08:03 -070084 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 * Bundle key names
86 */
87 private static final String ISSUED_TO = "issued-to";
88 private static final String ISSUED_BY = "issued-by";
89 private static final String VALID_NOT_BEFORE = "valid-not-before";
90 private static final String VALID_NOT_AFTER = "valid-not-after";
Brian Carlstrom4a062812011-07-05 17:28:44 -070091 private static final String X509_CERTIFICATE = "x509-certificate";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092
93 /**
94 * Saves the certificate state to a bundle
95 * @param certificate The SSL certificate to store
96 * @return A bundle with the certificate stored in it or null if fails
97 */
98 public static Bundle saveState(SslCertificate certificate) {
Brian Carlstrom4a062812011-07-05 17:28:44 -070099 if (certificate == null) {
100 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 }
Brian Carlstrom4a062812011-07-05 17:28:44 -0700102 Bundle bundle = new Bundle();
103 bundle.putString(ISSUED_TO, certificate.getIssuedTo().getDName());
104 bundle.putString(ISSUED_BY, certificate.getIssuedBy().getDName());
105 bundle.putString(VALID_NOT_BEFORE, certificate.getValidNotBefore());
106 bundle.putString(VALID_NOT_AFTER, certificate.getValidNotAfter());
107 X509Certificate x509Certificate = certificate.mX509Certificate;
108 if (x509Certificate != null) {
109 try {
110 bundle.putByteArray(X509_CERTIFICATE, x509Certificate.getEncoded());
111 } catch (CertificateEncodingException ignored) {
112 }
113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 return bundle;
115 }
116
117 /**
118 * Restores the certificate stored in the bundle
119 * @param bundle The bundle with the certificate state stored in it
120 * @return The SSL certificate stored in the bundle or null if fails
121 */
122 public static SslCertificate restoreState(Bundle bundle) {
Brian Carlstrom4a062812011-07-05 17:28:44 -0700123 if (bundle == null) {
124 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 }
Brian Carlstrom4a062812011-07-05 17:28:44 -0700126 X509Certificate x509Certificate;
127 byte[] bytes = bundle.getByteArray(X509_CERTIFICATE);
128 if (bytes == null) {
129 x509Certificate = null;
130 } else {
131 try {
132 CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
133 Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes));
134 x509Certificate = (X509Certificate) cert;
135 } catch (CertificateException e) {
136 x509Certificate = null;
137 }
138 }
139 return new SslCertificate(bundle.getString(ISSUED_TO),
140 bundle.getString(ISSUED_BY),
141 parseDate(bundle.getString(VALID_NOT_BEFORE)),
142 parseDate(bundle.getString(VALID_NOT_AFTER)),
143 x509Certificate);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 }
145
146 /**
147 * Creates a new SSL certificate object
148 * @param issuedTo The entity this certificate is issued to
149 * @param issuedBy The entity that issued this certificate
Brian Carlstrom6da00332011-06-26 21:08:03 -0700150 * @param validNotBefore The not-before date from the certificate
151 * validity period in ISO 8601 format
152 * @param validNotAfter The not-after date from the certificate
153 * validity period in ISO 8601 format
Brian Carlstromcc687c52011-02-16 11:40:15 -0800154 * @deprecated Use {@link #SslCertificate(X509Certificate)}
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800155 */
Jesse Wilson28c74252010-11-04 14:09:18 -0700156 @Deprecated
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800157 public SslCertificate(
158 String issuedTo, String issuedBy, String validNotBefore, String validNotAfter) {
Brian Carlstrom4a062812011-07-05 17:28:44 -0700159 this(issuedTo, issuedBy, parseDate(validNotBefore), parseDate(validNotAfter), null);
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800160 }
161
162 /**
163 * Creates a new SSL certificate object
164 * @param issuedTo The entity this certificate is issued to
165 * @param issuedBy The entity that issued this certificate
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 * @param validNotBefore The not-before date from the certificate validity period
167 * @param validNotAfter The not-after date from the certificate validity period
Brian Carlstromcc687c52011-02-16 11:40:15 -0800168 * @deprecated Use {@link #SslCertificate(X509Certificate)}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 */
Brian Carlstromcc687c52011-02-16 11:40:15 -0800170 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 public SslCertificate(
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800172 String issuedTo, String issuedBy, Date validNotBefore, Date validNotAfter) {
Brian Carlstrom4a062812011-07-05 17:28:44 -0700173 this(issuedTo, issuedBy, validNotBefore, validNotAfter, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 }
175
176 /**
177 * Creates a new SSL certificate object from an X509 certificate
178 * @param certificate X509 certificate
179 */
180 public SslCertificate(X509Certificate certificate) {
181 this(certificate.getSubjectDN().getName(),
182 certificate.getIssuerDN().getName(),
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800183 certificate.getNotBefore(),
Brian Carlstrom4a062812011-07-05 17:28:44 -0700184 certificate.getNotAfter(),
185 certificate);
186 }
187
188 private SslCertificate(
189 String issuedTo, String issuedBy,
190 Date validNotBefore, Date validNotAfter,
191 X509Certificate x509Certificate) {
192 mIssuedTo = new DName(issuedTo);
193 mIssuedBy = new DName(issuedBy);
194 mValidNotBefore = cloneDate(validNotBefore);
195 mValidNotAfter = cloneDate(validNotAfter);
196 mX509Certificate = x509Certificate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 }
198
199 /**
200 * @return Not-before date from the certificate validity period or
201 * "" if none has been set
202 */
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800203 public Date getValidNotBeforeDate() {
Brian Carlstroma5987a52010-03-02 14:51:22 -0800204 return cloneDate(mValidNotBefore);
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800205 }
206
207 /**
208 * @return Not-before date from the certificate validity period in
209 * ISO 8601 format or "" if none has been set
210 *
211 * @deprecated Use {@link #getValidNotBeforeDate()}
212 */
Jesse Wilson28c74252010-11-04 14:09:18 -0700213 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 public String getValidNotBefore() {
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800215 return formatDate(mValidNotBefore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 }
217
218 /**
219 * @return Not-after date from the certificate validity period or
220 * "" if none has been set
221 */
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800222 public Date getValidNotAfterDate() {
Brian Carlstroma5987a52010-03-02 14:51:22 -0800223 return cloneDate(mValidNotAfter);
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800224 }
225
226 /**
227 * @return Not-after date from the certificate validity period in
228 * ISO 8601 format or "" if none has been set
229 *
Brian Carlstrom9147a0e2010-03-02 11:24:39 -0800230 * @deprecated Use {@link #getValidNotAfterDate()}
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800231 */
Jesse Wilson28c74252010-11-04 14:09:18 -0700232 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 public String getValidNotAfter() {
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800234 return formatDate(mValidNotAfter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 }
236
237 /**
238 * @return Issued-to distinguished name or null if none has been set
239 */
240 public DName getIssuedTo() {
241 return mIssuedTo;
242 }
243
244 /**
245 * @return Issued-by distinguished name or null if none has been set
246 */
247 public DName getIssuedBy() {
248 return mIssuedBy;
249 }
250
251 /**
Adam Vartanian6309c612018-07-27 10:35:14 +0100252 * @return The {@code X509Certificate} used to create this {@code SslCertificate} or
253 * {@code null} if no certificate was provided.
254 */
255 public X509Certificate getX509Certificate() {
256 return mX509Certificate;
257 }
258
259 /**
Brian Carlstrom4a062812011-07-05 17:28:44 -0700260 * Convenience for UI presentation, not intended as public API.
261 */
Mathew Inwood53f089f2018-08-08 14:44:44 +0100262 @UnsupportedAppUsage
Brian Carlstrom4a062812011-07-05 17:28:44 -0700263 private static String getSerialNumber(X509Certificate x509Certificate) {
264 if (x509Certificate == null) {
265 return "";
266 }
267 BigInteger serialNumber = x509Certificate.getSerialNumber();
268 if (serialNumber == null) {
269 return "";
270 }
271 return fingerprint(serialNumber.toByteArray());
272 }
273
274 /**
275 * Convenience for UI presentation, not intended as public API.
276 */
Mathew Inwood53f089f2018-08-08 14:44:44 +0100277 @UnsupportedAppUsage
Brian Carlstrom4a062812011-07-05 17:28:44 -0700278 private static String getDigest(X509Certificate x509Certificate, String algorithm) {
279 if (x509Certificate == null) {
280 return "";
281 }
282 try {
283 byte[] bytes = x509Certificate.getEncoded();
284 MessageDigest md = MessageDigest.getInstance(algorithm);
285 byte[] digest = md.digest(bytes);
286 return fingerprint(digest);
287 } catch (CertificateEncodingException ignored) {
288 return "";
289 } catch (NoSuchAlgorithmException ignored) {
290 return "";
291 }
292 }
293
294 private static final String fingerprint(byte[] bytes) {
295 if (bytes == null) {
296 return "";
297 }
298 StringBuilder sb = new StringBuilder();
299 for (int i = 0; i < bytes.length; i++) {
300 byte b = bytes[i];
Przemyslaw Szczepaniak3f726042015-10-15 11:04:19 +0100301 HexDump.appendByteAsHex(sb, b, true);
Brian Carlstrom4a062812011-07-05 17:28:44 -0700302 if (i+1 != bytes.length) {
303 sb.append(':');
304 }
305 }
306 return sb.toString();
307 }
308
309 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 * @return A string representation of this certificate for debugging
311 */
312 public String toString() {
Brian Carlstrom6da00332011-06-26 21:08:03 -0700313 return ("Issued to: " + mIssuedTo.getDName() + ";\n"
314 + "Issued by: " + mIssuedBy.getDName() + ";\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 }
316
317 /**
Brian Carlstrom445d8f12010-03-02 10:02:19 -0800318 * Parse an ISO 8601 date converting ParseExceptions to a null result;
319 */
320 private static Date parseDate(String string) {
321 try {
322 return new SimpleDateFormat(ISO_8601_DATE_FORMAT).parse(string);
323 } catch (ParseException e) {
324 return null;
325 }
326 }
327
328 /**
329 * Format a date as an ISO 8601 string, return "" for a null date
330 */
331 private static String formatDate(Date date) {
332 if (date == null) {
333 return "";
334 }
335 return new SimpleDateFormat(ISO_8601_DATE_FORMAT).format(date);
336 }
337
338 /**
Brian Carlstroma5987a52010-03-02 14:51:22 -0800339 * Clone a possibly null Date
340 */
341 private static Date cloneDate(Date date) {
342 if (date == null) {
343 return null;
344 }
345 return (Date) date.clone();
346 }
347
348 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 * A distinguished name helper class: a 3-tuple of:
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800350 * <ul>
351 * <li>the most specific common name (CN)</li>
352 * <li>the most specific organization (O)</li>
353 * <li>the most specific organizational unit (OU)</li>
354 * <ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 */
356 public class DName {
357 /**
358 * Distinguished name (normally includes CN, O, and OU names)
359 */
360 private String mDName;
361
362 /**
363 * Common-name (CN) component of the name
364 */
365 private String mCName;
366
367 /**
368 * Organization (O) component of the name
369 */
370 private String mOName;
371
372 /**
373 * Organizational Unit (OU) component of the name
374 */
375 private String mUName;
376
377 /**
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800378 * Creates a new {@code DName} from a string. The attributes
379 * are assumed to come in most significant to least
380 * significant order which is true of human readable values
381 * returned by methods such as {@code X500Principal.getName()}.
382 * Be aware that the underlying sources of distinguished names
383 * such as instances of {@code X509Certificate} are encoded in
384 * least significant to most significant order, so make sure
385 * the value passed here has the expected ordering of
386 * attributes.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 */
388 public DName(String dName) {
389 if (dName != null) {
Brian Carlstrom65051222010-01-26 23:07:42 -0800390 mDName = dName;
391 try {
392 X509Name x509Name = new X509Name(dName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393
Brian Carlstrom65051222010-01-26 23:07:42 -0800394 Vector val = x509Name.getValues();
395 Vector oid = x509Name.getOIDs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396
Brian Carlstrom65051222010-01-26 23:07:42 -0800397 for (int i = 0; i < oid.size(); i++) {
398 if (oid.elementAt(i).equals(X509Name.CN)) {
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800399 if (mCName == null) {
400 mCName = (String) val.elementAt(i);
401 }
Brian Carlstrom65051222010-01-26 23:07:42 -0800402 continue;
403 }
404
405 if (oid.elementAt(i).equals(X509Name.O)) {
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800406 if (mOName == null) {
407 mOName = (String) val.elementAt(i);
408 continue;
409 }
Brian Carlstrom65051222010-01-26 23:07:42 -0800410 }
411
412 if (oid.elementAt(i).equals(X509Name.OU)) {
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800413 if (mUName == null) {
414 mUName = (String) val.elementAt(i);
415 continue;
416 }
Brian Carlstrom65051222010-01-26 23:07:42 -0800417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 }
Brian Carlstrom65051222010-01-26 23:07:42 -0800419 } catch (IllegalArgumentException ex) {
420 // thrown if there is an error parsing the string
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 }
422 }
423 }
424
425 /**
426 * @return The distinguished name (normally includes CN, O, and OU names)
427 */
428 public String getDName() {
429 return mDName != null ? mDName : "";
430 }
431
432 /**
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800433 * @return The most specific Common-name (CN) component of this name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 */
435 public String getCName() {
436 return mCName != null ? mCName : "";
437 }
438
439 /**
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800440 * @return The most specific Organization (O) component of this name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 */
442 public String getOName() {
443 return mOName != null ? mOName : "";
444 }
445
446 /**
Brian Carlstrom91154ce2012-12-21 17:28:04 -0800447 * @return The most specific Organizational Unit (OU) component of this name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 */
449 public String getUName() {
450 return mUName != null ? mUName : "";
451 }
452 }
Brian Carlstrom6da00332011-06-26 21:08:03 -0700453
454 /**
455 * Inflates the SSL certificate view (helper method).
456 * @return The resultant certificate view with issued-to, issued-by,
457 * issued-on, expires-on, and possibly other fields set.
Brian Carlstrom6da00332011-06-26 21:08:03 -0700458 *
459 * @hide Used by Browser and Settings
460 */
Mathew Inwood53f089f2018-08-08 14:44:44 +0100461 @UnsupportedAppUsage
Brian Carlstrom6da00332011-06-26 21:08:03 -0700462 public View inflateCertificateView(Context context) {
463 LayoutInflater factory = LayoutInflater.from(context);
464
465 View certificateView = factory.inflate(
466 com.android.internal.R.layout.ssl_certificate, null);
467
468 // issued to:
469 SslCertificate.DName issuedTo = getIssuedTo();
470 if (issuedTo != null) {
471 ((TextView) certificateView.findViewById(com.android.internal.R.id.to_common))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700472 .setText(issuedTo.getCName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700473 ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700474 .setText(issuedTo.getOName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700475 ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org_unit))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700476 .setText(issuedTo.getUName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700477 }
Brian Carlstrom4a062812011-07-05 17:28:44 -0700478 // serial number:
479 ((TextView) certificateView.findViewById(com.android.internal.R.id.serial_number))
480 .setText(getSerialNumber(mX509Certificate));
Brian Carlstrom6da00332011-06-26 21:08:03 -0700481
482 // issued by:
483 SslCertificate.DName issuedBy = getIssuedBy();
484 if (issuedBy != null) {
485 ((TextView) certificateView.findViewById(com.android.internal.R.id.by_common))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700486 .setText(issuedBy.getCName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700487 ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700488 .setText(issuedBy.getOName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700489 ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org_unit))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700490 .setText(issuedBy.getUName());
Brian Carlstrom6da00332011-06-26 21:08:03 -0700491 }
492
493 // issued on:
494 String issuedOn = formatCertificateDate(context, getValidNotBeforeDate());
495 ((TextView) certificateView.findViewById(com.android.internal.R.id.issued_on))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700496 .setText(issuedOn);
Brian Carlstrom6da00332011-06-26 21:08:03 -0700497
498 // expires on:
499 String expiresOn = formatCertificateDate(context, getValidNotAfterDate());
500 ((TextView) certificateView.findViewById(com.android.internal.R.id.expires_on))
Brian Carlstrom4a062812011-07-05 17:28:44 -0700501 .setText(expiresOn);
502
503 // fingerprints:
504 ((TextView) certificateView.findViewById(com.android.internal.R.id.sha256_fingerprint))
505 .setText(getDigest(mX509Certificate, "SHA256"));
506 ((TextView) certificateView.findViewById(com.android.internal.R.id.sha1_fingerprint))
507 .setText(getDigest(mX509Certificate, "SHA1"));
Brian Carlstrom6da00332011-06-26 21:08:03 -0700508
509 return certificateView;
510 }
511
512 /**
513 * Formats the certificate date to a properly localized date string.
514 * @return Properly localized version of the certificate date string and
515 * the "" if it fails to localize.
516 */
517 private String formatCertificateDate(Context context, Date certificateDate) {
518 if (certificateDate == null) {
519 return "";
520 }
Charles He2b47e742017-02-20 17:32:12 +0000521 return DateFormat.getMediumDateFormat(context).format(certificateDate);
Brian Carlstrom6da00332011-06-26 21:08:03 -0700522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523}