001/*
002 * Copyright 2017-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2017-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2017-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.util.ssl.cert;
037
038
039
040import java.io.ByteArrayInputStream;
041import java.io.Serializable;
042import java.math.BigInteger;
043import java.security.KeyPair;
044import java.security.KeyPairGenerator;
045import java.security.MessageDigest;
046import java.security.PrivateKey;
047import java.security.PublicKey;
048import java.security.Signature;
049import java.security.cert.Certificate;
050import java.security.cert.CertificateException;
051import java.util.ArrayList;
052import java.util.Arrays;
053import java.util.Calendar;
054import java.util.Collections;
055import java.util.Date;
056import java.util.GregorianCalendar;
057import java.util.Iterator;
058import java.util.List;
059import java.util.UUID;
060
061import com.unboundid.asn1.ASN1BigInteger;
062import com.unboundid.asn1.ASN1BitString;
063import com.unboundid.asn1.ASN1Constants;
064import com.unboundid.asn1.ASN1Element;
065import com.unboundid.asn1.ASN1Exception;
066import com.unboundid.asn1.ASN1GeneralizedTime;
067import com.unboundid.asn1.ASN1Integer;
068import com.unboundid.asn1.ASN1ObjectIdentifier;
069import com.unboundid.asn1.ASN1OctetString;
070import com.unboundid.asn1.ASN1Sequence;
071import com.unboundid.asn1.ASN1Set;
072import com.unboundid.asn1.ASN1UTCTime;
073import com.unboundid.asn1.ASN1UTF8String;
074import com.unboundid.ldap.sdk.DN;
075import com.unboundid.ldap.sdk.RDN;
076import com.unboundid.ldap.sdk.schema.AttributeTypeDefinition;
077import com.unboundid.ldap.sdk.schema.Schema;
078import com.unboundid.util.Base64;
079import com.unboundid.util.CryptoHelper;
080import com.unboundid.util.Debug;
081import com.unboundid.util.NotMutable;
082import com.unboundid.util.NotNull;
083import com.unboundid.util.Nullable;
084import com.unboundid.util.OID;
085import com.unboundid.util.ObjectPair;
086import com.unboundid.util.StaticUtils;
087import com.unboundid.util.ThreadSafety;
088import com.unboundid.util.ThreadSafetyLevel;
089
090import static com.unboundid.util.ssl.cert.CertMessages.*;
091
092
093
094/**
095 * This class provides support for decoding an X.509 certificate as defined in
096 * <A HREF="https://www.ietf.org/rfc/rfc5280.txt">RFC 5280</A>.  The certificate
097 * is encoded using the ASN.1 Distinguished Encoding Rules (DER), which is a
098 * subset of BER, and is supported by the code in the
099 * {@code com.unboundid.asn1} package.  The ASN.1 specification is as follows:
100 * <PRE>
101 *   Certificate  ::=  SEQUENCE  {
102 *        tbsCertificate       TBSCertificate,
103 *        signatureAlgorithm   AlgorithmIdentifier,
104 *        signatureValue       BIT STRING  }
105 *
106 *   TBSCertificate  ::=  SEQUENCE  {
107 *        version         [0]  EXPLICIT Version DEFAULT v1,
108 *        serialNumber         CertificateSerialNumber,
109 *        signature            AlgorithmIdentifier,
110 *        issuer               Name,
111 *        validity             Validity,
112 *        subject              Name,
113 *        subjectPublicKeyInfo SubjectPublicKeyInfo,
114 *        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
115 *                             -- If present, version MUST be v2 or v3
116 *        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
117 *                             -- If present, version MUST be v2 or v3
118 *        extensions      [3]  EXPLICIT Extensions OPTIONAL
119 *                             -- If present, version MUST be v3
120 *        }
121 *
122 *   Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
123 *
124 *   CertificateSerialNumber  ::=  INTEGER
125 *
126 *   Validity ::= SEQUENCE {
127 *        notBefore      Time,
128 *        notAfter       Time }
129 *
130 *   Time ::= CHOICE {
131 *        utcTime        UTCTime,
132 *        generalTime    GeneralizedTime }
133 *
134 *   UniqueIdentifier  ::=  BIT STRING
135 *
136 *   SubjectPublicKeyInfo  ::=  SEQUENCE  {
137 *        algorithm            AlgorithmIdentifier,
138 *        subjectPublicKey     BIT STRING  }
139 *
140 *   Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
141 *
142 *   Extension  ::=  SEQUENCE  {
143 *        extnID      OBJECT IDENTIFIER,
144 *        critical    BOOLEAN DEFAULT FALSE,
145 *        extnValue   OCTET STRING
146 *                    -- contains the DER encoding of an ASN.1 value
147 *                    -- corresponding to the extension type identified
148 *                    -- by extnID
149 *        }
150 *
151 *   AlgorithmIdentifier  ::=  SEQUENCE  {
152 *        algorithm               OBJECT IDENTIFIER,
153 *        parameters              ANY DEFINED BY algorithm OPTIONAL  }
154 *
155 *   Name ::= CHOICE { -- only one possibility for now --
156 *     rdnSequence  RDNSequence }
157 *
158 *   RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
159 *
160 *   RelativeDistinguishedName ::=
161 *     SET SIZE (1..MAX) OF AttributeTypeAndValue
162 *
163 *   AttributeTypeAndValue ::= SEQUENCE {
164 *     type     AttributeType,
165 *     value    AttributeValue }
166 *
167 *   AttributeType ::= OBJECT IDENTIFIER
168 *
169 *   AttributeValue ::= ANY -- DEFINED BY AttributeType
170 * </PRE>
171 */
172@NotMutable()
173@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
174public final class X509Certificate
175       implements Serializable
176{
177  /**
178   * The DER type for the version number element, which is explicitly typed.
179   */
180  private static final byte TYPE_EXPLICIT_VERSION = (byte) 0xA0;
181
182
183
184  /**
185   * The DER type for the issuer unique ID element, which is implicitly typed.
186   */
187  private static final byte TYPE_IMPLICIT_ISSUER_UNIQUE_ID = (byte) 0x81;
188
189
190
191  /**
192   * The DER type for the subject unique ID element, which is implicitly typed.
193   */
194  private static final byte TYPE_IMPLICIT_SUBJECT_UNIQUE_ID = (byte) 0x82;
195
196
197
198  /**
199   * The DER type for the extensions element, which is explicitly typed.
200   */
201  private static final byte TYPE_EXPLICIT_EXTENSIONS = (byte) 0xA3;
202
203
204
205  /**
206   * The serial version UID for this serializable class.
207   */
208  private static final long serialVersionUID = -4680448103099282243L;
209
210
211
212  // The issuer unique identifier for the certificate.
213  @Nullable private final ASN1BitString issuerUniqueID;
214
215  // The signature value for the certificate.
216  @NotNull private final ASN1BitString signatureValue;
217
218  // The encoded certificate public key.
219  @NotNull private final ASN1BitString encodedPublicKey;
220
221  // The subject unique identifier for the certificate.
222  @Nullable private final ASN1BitString subjectUniqueID;
223
224  // The ASN.1 element with the encoded public key algorithm parameters.
225  @Nullable private final ASN1Element publicKeyAlgorithmParameters;
226
227  // The ASN.1 element with the encoded signature algorithm parameters.
228  @Nullable private final ASN1Element signatureAlgorithmParameters;
229
230  // The certificate serial number.
231  @NotNull private final BigInteger serialNumber;
232
233  // The bytes that comprise the encoded representation of the X.509
234  // certificate.
235  @NotNull private final byte[] x509CertificateBytes;
236
237  // The decoded public key for this certificate, if available.
238  @Nullable private final DecodedPublicKey decodedPublicKey;
239
240  // The issuer DN for the certificate.
241  @NotNull private final DN issuerDN;
242
243  // The subject DN for the certificate.
244  @NotNull private final DN subjectDN;
245
246  // The list of extensions for the certificate.
247  @NotNull private final List<X509CertificateExtension> extensions;
248
249  // The time that indicates the end of the certificate validity window.
250  private final long notAfter;
251
252  // The time that indicates the beginning of the certificate validity window.
253  private final long notBefore;
254
255  // The OID for the public key algorithm.
256  @NotNull private final OID publicKeyAlgorithmOID;
257
258  // The OID for the signature algorithm.
259  @NotNull private final OID signatureAlgorithmOID;
260
261  // The public key algorithm name that corresponds with the public key
262  // algorithm OID, if available.
263  @Nullable private final String publicKeyAlgorithmName;
264
265  // The signature algorithm name that corresponds with the signature algorithm
266  // OID, if available.
267  @Nullable private final String signatureAlgorithmName;
268
269  // The X.509 certificate version.
270  @NotNull private final X509CertificateVersion version;
271
272
273
274  /**
275   * Creates a new X.509 certificate with the provided information.  This is
276   * primarily intended for unit testing and other internal use.
277   *
278   * @param  version                       The version number for the
279   *                                       certificate.
280   * @param  serialNumber                  The serial number for the
281   *                                       certificate.  This must not be
282   *                                       {@code null}.
283   * @param  signatureAlgorithmOID         The signature algorithm OID for the
284   *                                       certificate.  This must not be
285   *                                       {@code null}.
286   * @param  signatureAlgorithmParameters  The encoded signature algorithm
287   *                                       parameters for the certificate.  This
288   *                                       may be {@code null} if there are no
289   *                                       parameters.
290   * @param  signatureValue                The encoded signature for the
291   *                                       certificate.  This must not be
292   *                                       {@code null}.
293   * @param  issuerDN                      The issuer DN for the certificate.
294   *                                       This must not be {@code null}.
295   * @param  notBefore                     The validity start time for the
296   *                                       certificate.
297   * @param  notAfter                      The validity end time for the
298   *                                       certificate.
299   * @param  subjectDN                     The subject DN for the certificate.
300   *                                       This must not be {@code null}.
301   * @param  publicKeyAlgorithmOID         The OID of the public key algorithm
302   *                                       for the certificate.  This must not
303   *                                       be {@code null}.
304   * @param  publicKeyAlgorithmParameters  The encoded public key algorithm
305   *                                       parameters for the certificate.  This
306   *                                       may be {@code null} if there are no
307   *                                       parameters.
308   * @param  encodedPublicKey              The encoded public key for the
309   *                                       certificate.  This must not be
310   *                                       {@code null}.
311   * @param  decodedPublicKey              The decoded public key for the
312   *                                       certificate.  This may be
313   *                                       {@code null} if it is not available.
314   * @param  issuerUniqueID                The issuer unique ID for the
315   *                                       certificate.  This may be
316   *                                       {@code null} if the certificate does
317   *                                       not have an issuer unique ID.
318   * @param  subjectUniqueID               The subject unique ID for the
319   *                                       certificate.  This may be
320   *                                       {@code null} if the certificate does
321   *                                       not have a subject unique ID.
322   * @param  extensions                    The set of extensions to include in
323   *                                       the certificate.  This must not be
324   *                                       {@code null} but may be empty.
325   *
326   * @throws  CertException  If a problem is encountered while creating the
327   *                         certificate.
328   */
329  X509Certificate(@NotNull final X509CertificateVersion version,
330                  @NotNull final BigInteger serialNumber,
331                  @NotNull final OID signatureAlgorithmOID,
332                  @Nullable final ASN1Element signatureAlgorithmParameters,
333                  @NotNull final ASN1BitString signatureValue,
334                  @NotNull final DN issuerDN, final long notBefore,
335                  final long notAfter,
336                  @NotNull final DN subjectDN,
337                  @NotNull final OID publicKeyAlgorithmOID,
338                  @Nullable final ASN1Element publicKeyAlgorithmParameters,
339                  @NotNull final ASN1BitString encodedPublicKey,
340                  @Nullable final DecodedPublicKey decodedPublicKey,
341                  @Nullable final ASN1BitString issuerUniqueID,
342                  @Nullable final ASN1BitString subjectUniqueID,
343                  @NotNull final X509CertificateExtension... extensions)
344       throws CertException
345  {
346    this.version = version;
347    this.serialNumber = serialNumber;
348    this.signatureAlgorithmOID = signatureAlgorithmOID;
349    this.signatureAlgorithmParameters = signatureAlgorithmParameters;
350    this.signatureValue = signatureValue;
351    this.issuerDN = issuerDN;
352    this.notBefore = notBefore;
353    this.notAfter = notAfter;
354    this.subjectDN = subjectDN;
355    this.publicKeyAlgorithmOID = publicKeyAlgorithmOID;
356    this.publicKeyAlgorithmParameters = publicKeyAlgorithmParameters;
357    this.encodedPublicKey = encodedPublicKey;
358    this.decodedPublicKey = decodedPublicKey;
359    this.issuerUniqueID = issuerUniqueID;
360    this.subjectUniqueID = subjectUniqueID;
361    this.extensions = StaticUtils.toList(extensions);
362
363    final SignatureAlgorithmIdentifier signatureAlgorithmIdentifier =
364         SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID);
365    if (signatureAlgorithmIdentifier == null)
366    {
367      signatureAlgorithmName = null;
368    }
369    else
370    {
371      signatureAlgorithmName =
372           signatureAlgorithmIdentifier.getUserFriendlyName();
373    }
374
375    final PublicKeyAlgorithmIdentifier publicKeyAlgorithmIdentifier =
376         PublicKeyAlgorithmIdentifier.forOID(publicKeyAlgorithmOID);
377    if (publicKeyAlgorithmIdentifier == null)
378    {
379      publicKeyAlgorithmName = null;
380    }
381    else
382    {
383      publicKeyAlgorithmName = publicKeyAlgorithmIdentifier.getName();
384    }
385
386    x509CertificateBytes = encode().encode();
387  }
388
389
390
391  /**
392   * Decodes the contents of the provided byte array as an X.509 certificate.
393   *
394   * @param  encodedCertificate  The byte array containing the encoded X.509
395   *                             certificate.  This must not be {@code null}.
396   *
397   * @throws  CertException  If the contents of the provided byte array could
398   *                         not be decoded as a valid X.509 certificate.
399   */
400  public X509Certificate(@NotNull final byte[] encodedCertificate)
401         throws CertException
402  {
403    x509CertificateBytes = encodedCertificate;
404
405    final ASN1Element[] certificateElements;
406    try
407    {
408      certificateElements =
409           ASN1Sequence.decodeAsSequence(encodedCertificate).elements();
410    }
411    catch (final Exception e)
412    {
413      Debug.debugException(e);
414      throw new CertException(
415           ERR_CERT_DECODE_NOT_SEQUENCE.get(StaticUtils.getExceptionMessage(e)),
416           e);
417    }
418
419    if (certificateElements.length != 3)
420    {
421      throw new CertException(
422           ERR_CERT_DECODE_UNEXPECTED_SEQUENCE_ELEMENT_COUNT.get(
423                certificateElements.length));
424    }
425
426    final ASN1Element[] tbsCertificateElements;
427    try
428    {
429      tbsCertificateElements =
430           ASN1Sequence.decodeAsSequence(certificateElements[0]).elements();
431    }
432    catch (final Exception e)
433    {
434      Debug.debugException(e);
435      throw new CertException(
436           ERR_CERT_DECODE_FIRST_ELEMENT_NOT_SEQUENCE.get(
437                StaticUtils.getExceptionMessage(e)),
438           e);
439    }
440
441    int tbsCertificateElementIndex;
442    try
443    {
444      // The version element may or may not be present in a certificate.  If it
445      // is present, then it will be explicitly tagged, which means that it's a
446      // constructed element with the DER-encoded integer inside it.  If it is
447      // absent, then a default version of v1 will be used.
448      if ((tbsCertificateElements[0].getType() & 0xFF) == 0xA0)
449      {
450        final int versionIntValue = ASN1Integer.decodeAsInteger(
451             tbsCertificateElements[0].getValue()).intValue();
452        version = X509CertificateVersion.valueOf(versionIntValue);
453        if (version == null)
454        {
455          throw new CertException(
456               ERR_CERT_DECODE_UNSUPPORTED_VERSION.get(version));
457        }
458
459        tbsCertificateElementIndex = 1;
460      }
461      else
462      {
463        version = X509CertificateVersion.V1;
464        tbsCertificateElementIndex = 0;
465      }
466    }
467    catch (final CertException e)
468    {
469      Debug.debugException(e);
470      throw e;
471    }
472    catch (final Exception e)
473    {
474      Debug.debugException(e);
475      throw new CertException(
476           ERR_CERT_DECODE_CANNOT_PARSE_VERSION.get(
477                StaticUtils.getExceptionMessage(e)),
478           e);
479    }
480
481    try
482    {
483      serialNumber = tbsCertificateElements[tbsCertificateElementIndex++].
484           decodeAsBigInteger().getBigIntegerValue();
485    }
486    catch (final Exception e)
487    {
488      Debug.debugException(e);
489      throw new CertException(
490           ERR_CERT_DECODE_CANNOT_PARSE_SERIAL_NUMBER.get(
491                StaticUtils.getExceptionMessage(e)),
492           e);
493    }
494
495    try
496    {
497      final ASN1Element[] signatureAlgorithmElements =
498           tbsCertificateElements[tbsCertificateElementIndex++].
499                decodeAsSequence().elements();
500      signatureAlgorithmOID =
501           signatureAlgorithmElements[0].decodeAsObjectIdentifier().getOID();
502      if (signatureAlgorithmElements.length > 1)
503      {
504        signatureAlgorithmParameters = signatureAlgorithmElements[1];
505      }
506      else
507      {
508        signatureAlgorithmParameters = null;
509      }
510    }
511    catch (final Exception e)
512    {
513      Debug.debugException(e);
514      throw new CertException(
515           ERR_CERT_DECODE_CANNOT_PARSE_SIG_ALG.get(
516                StaticUtils.getExceptionMessage(e)),
517           e);
518    }
519
520    final SignatureAlgorithmIdentifier signatureAlgorithmIdentifier =
521         SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID);
522    if (signatureAlgorithmIdentifier == null)
523    {
524      signatureAlgorithmName = null;
525    }
526    else
527    {
528      signatureAlgorithmName =
529           signatureAlgorithmIdentifier.getUserFriendlyName();
530    }
531
532    try
533    {
534      issuerDN =
535           decodeName(tbsCertificateElements[tbsCertificateElementIndex++]);
536    }
537    catch (final Exception e)
538    {
539      Debug.debugException(e);
540      throw new CertException(
541           ERR_CERT_DECODE_CANNOT_PARSE_ISSUER_DN.get(
542                StaticUtils.getExceptionMessage(e)),
543           e);
544    }
545
546    try
547    {
548      final ASN1Element[] validityElements =
549           tbsCertificateElements[tbsCertificateElementIndex++].
550                decodeAsSequence().elements();
551      switch (validityElements[0].getType())
552      {
553        case ASN1Constants.UNIVERSAL_UTC_TIME_TYPE:
554          notBefore = decodeUTCTime(validityElements[0]);
555          break;
556        case ASN1Constants.UNIVERSAL_GENERALIZED_TIME_TYPE:
557          notBefore = validityElements[0].decodeAsGeneralizedTime().getTime();
558          break;
559        default:
560          throw new CertException(
561               ERR_CERT_DECODE_NOT_BEFORE_UNEXPECTED_TYPE.get(
562                    StaticUtils.toHex(validityElements[0].getType()),
563                    StaticUtils.toHex(ASN1Constants.UNIVERSAL_UTC_TIME_TYPE),
564                    StaticUtils.toHex(ASN1Constants.
565                         UNIVERSAL_GENERALIZED_TIME_TYPE)));
566      }
567
568      switch (validityElements[1].getType())
569      {
570        case ASN1Constants.UNIVERSAL_UTC_TIME_TYPE:
571          notAfter = decodeUTCTime(validityElements[1]);
572          break;
573        case ASN1Constants.UNIVERSAL_GENERALIZED_TIME_TYPE:
574          notAfter = validityElements[1].decodeAsGeneralizedTime().getTime();
575          break;
576        default:
577          throw new CertException(
578               ERR_CERT_DECODE_NOT_AFTER_UNEXPECTED_TYPE.get(
579                    StaticUtils.toHex(validityElements[0].getType()),
580                    StaticUtils.toHex(ASN1Constants.UNIVERSAL_UTC_TIME_TYPE),
581                    StaticUtils.toHex(ASN1Constants.
582                         UNIVERSAL_GENERALIZED_TIME_TYPE)));
583      }
584    }
585    catch (final CertException e)
586    {
587      Debug.debugException(e);
588      throw e;
589    }
590    catch (final Exception e)
591    {
592      Debug.debugException(e);
593      throw new CertException(
594           ERR_CERT_DECODE_COULD_NOT_PARSE_VALIDITY.get(
595                StaticUtils.getExceptionMessage(e)),
596           e);
597    }
598
599    try
600    {
601      subjectDN =
602           decodeName(tbsCertificateElements[tbsCertificateElementIndex++]);
603    }
604    catch (final Exception e)
605    {
606      Debug.debugException(e);
607      throw new CertException(
608           ERR_CERT_DECODE_CANNOT_PARSE_SUBJECT_DN.get(
609                StaticUtils.getExceptionMessage(e)),
610           e);
611    }
612
613    try
614    {
615      final ASN1Element[] subjectPublicKeyInfoElements =
616           tbsCertificateElements[tbsCertificateElementIndex++].
617                decodeAsSequence().elements();
618      final ASN1Element[] publicKeyAlgorithmElements =
619           subjectPublicKeyInfoElements[0].decodeAsSequence().elements();
620      publicKeyAlgorithmOID =
621           publicKeyAlgorithmElements[0].decodeAsObjectIdentifier().getOID();
622      if (publicKeyAlgorithmElements.length > 1)
623      {
624        publicKeyAlgorithmParameters = publicKeyAlgorithmElements[1];
625      }
626      else
627      {
628        publicKeyAlgorithmParameters = null;
629      }
630
631      encodedPublicKey = subjectPublicKeyInfoElements[1].decodeAsBitString();
632    }
633    catch (final Exception e)
634    {
635      Debug.debugException(e);
636      throw new CertException(
637           ERR_CERT_DECODE_CANNOT_PARSE_PUBLIC_KEY_INFO.get(
638                StaticUtils.getExceptionMessage(e)),
639           e);
640    }
641
642    final PublicKeyAlgorithmIdentifier publicKeyAlgorithmIdentifier =
643         PublicKeyAlgorithmIdentifier.forOID(publicKeyAlgorithmOID);
644    if (publicKeyAlgorithmIdentifier == null)
645    {
646      publicKeyAlgorithmName = null;
647      decodedPublicKey = null;
648    }
649    else
650    {
651      publicKeyAlgorithmName = publicKeyAlgorithmIdentifier.getName();
652
653      DecodedPublicKey pk = null;
654      switch (publicKeyAlgorithmIdentifier)
655      {
656        case RSA:
657          try
658          {
659            pk = new RSAPublicKey(encodedPublicKey);
660          }
661          catch (final Exception e)
662          {
663            Debug.debugException(e);
664          }
665          break;
666
667        case EC:
668          try
669          {
670            pk = new EllipticCurvePublicKey(encodedPublicKey);
671          }
672          catch (final Exception e)
673          {
674            Debug.debugException(e);
675          }
676          break;
677      }
678
679      decodedPublicKey = pk;
680    }
681
682    ASN1BitString issuerID = null;
683    ASN1BitString subjectID = null;
684    final ArrayList<X509CertificateExtension> extList = new ArrayList<>(10);
685    for (;
686         tbsCertificateElementIndex < tbsCertificateElements.length;
687         tbsCertificateElementIndex++)
688    {
689      switch (tbsCertificateElements[tbsCertificateElementIndex].getType())
690      {
691        case (byte) 0x81:
692          try
693          {
694            issuerID = tbsCertificateElements[tbsCertificateElementIndex].
695                 decodeAsBitString();
696          }
697          catch (final Exception e)
698          {
699            Debug.debugException(e);
700            throw new CertException(
701                 ERR_CERT_DECODE_CANNOT_PARSE_ISSUER_UNIQUE_ID.get(
702                      StaticUtils.getExceptionMessage(e)),
703                 e);
704          }
705          break;
706        case (byte) 0x82:
707          try
708          {
709            subjectID = tbsCertificateElements[tbsCertificateElementIndex].
710                 decodeAsBitString();
711          }
712          catch (final Exception e)
713          {
714            Debug.debugException(e);
715            throw new CertException(
716                 ERR_CERT_DECODE_CANNOT_PARSE_SUBJECT_UNIQUE_ID.get(
717                      StaticUtils.getExceptionMessage(e)),
718                 e);
719          }
720          break;
721        case (byte) 0xA3:
722          try
723          {
724            // This element is explicitly tagged.
725            final ASN1Element[] extensionElements = ASN1Sequence.
726                 decodeAsSequence(tbsCertificateElements[
727                      tbsCertificateElementIndex].getValue()).elements();
728            for (final ASN1Element extensionElement : extensionElements)
729            {
730              extList.add(X509CertificateExtension.decode(extensionElement));
731            }
732          }
733          catch (final Exception e)
734          {
735            Debug.debugException(e);
736            throw new CertException(
737                 ERR_CERT_DECODE_CANNOT_PARSE_EXTENSION.get(
738                      StaticUtils.getExceptionMessage(e)),
739                 e);
740          }
741          break;
742      }
743    }
744
745    issuerUniqueID = issuerID;
746    subjectUniqueID = subjectID;
747    extensions = Collections.unmodifiableList(extList);
748
749    try
750    {
751      final ASN1Element[] signatureAlgorithmElements =
752           certificateElements[1].decodeAsSequence().elements();
753      final OID oid =
754           signatureAlgorithmElements[0].decodeAsObjectIdentifier().getOID();
755      if (! oid.equals(signatureAlgorithmOID))
756      {
757        throw new CertException(
758             ERR_CERT_DECODE_SIG_ALG_MISMATCH.get(
759                  signatureAlgorithmOID.toString(), oid.toString()));
760      }
761    }
762    catch (final CertException e)
763    {
764      Debug.debugException(e);
765      throw e;
766    }
767    catch (final Exception e)
768    {
769      Debug.debugException(e);
770      throw new CertException(
771           ERR_CERT_DECODE_CANNOT_PARSE_SIG_ALG.get(
772                StaticUtils.getExceptionMessage(e)),
773           e);
774    }
775
776    try
777    {
778      signatureValue = certificateElements[2].decodeAsBitString();
779    }
780    catch (final Exception e)
781    {
782      Debug.debugException(e);
783      throw new CertException(
784           ERR_CERT_DECODE_CANNOT_PARSE_SIG_VALUE.get(
785                StaticUtils.getExceptionMessage(e)),
786           e);
787    }
788  }
789
790
791
792  /**
793   * Decodes the provided ASN.1 element as an X.509 name.
794   *
795   * @param  element  The ASN.1 element to decode.
796   *
797   * @return  The DN created from the decoded X.509 name.
798   *
799   * @throws  CertException  If a problem is encountered while trying to decode
800   *                         the X.509 name.
801   */
802  @NotNull()
803  static DN decodeName(@NotNull final ASN1Element element)
804         throws CertException
805  {
806    Schema schema;
807    try
808    {
809      schema = Schema.getDefaultStandardSchema();
810    }
811    catch (final Exception e)
812    {
813      Debug.debugException(e);
814      schema = null;
815    }
816
817    final ASN1Element[] rdnElements;
818    try
819    {
820      rdnElements = ASN1Sequence.decodeAsSequence(element).elements();
821    }
822    catch (final Exception e)
823    {
824      Debug.debugException(e);
825      throw new CertException(
826           ERR_CERT_DECODE_NAME_NOT_SEQUENCE.get(
827                StaticUtils.getExceptionMessage(e)),
828           e);
829    }
830
831    final ArrayList<RDN> rdns = new ArrayList<>(rdnElements.length);
832    for (int i=0; i < rdnElements.length; i++)
833    {
834      try
835      {
836        final ASN1Element[] attributeSetElements =
837             rdnElements[i].decodeAsSet().elements();
838        final String[] attributeNames = new String[attributeSetElements.length];
839        final byte[][] attributeValues =
840             new byte[attributeSetElements.length][];
841        for (int j=0; j < attributeSetElements.length; j++)
842        {
843          final ASN1Element[] attributeTypeAndValueElements =
844               ASN1Sequence.decodeAsSequence(attributeSetElements[j]).
845                    elements();
846
847          final OID attributeTypeOID = attributeTypeAndValueElements[0].
848               decodeAsObjectIdentifier().getOID();
849          final AttributeTypeDefinition attributeType =
850               schema.getAttributeType(attributeTypeOID.toString());
851          if (attributeType == null)
852          {
853            attributeNames[j] = attributeTypeOID.toString();
854          }
855          else
856          {
857            attributeNames[j] = attributeType.getNameOrOID().toUpperCase();
858          }
859
860          attributeValues[j] = attributeTypeAndValueElements[1].
861               decodeAsOctetString().getValue();
862        }
863
864        rdns.add(new RDN(attributeNames, attributeValues, schema));
865      }
866      catch (final Exception e)
867      {
868        Debug.debugException(e);
869        throw new CertException(
870             ERR_CERT_DECODE_CANNOT_PARSE_NAME_SEQUENCE_ELEMENT.get(i,
871                  StaticUtils.getExceptionMessage(e)),
872             e);
873      }
874    }
875
876    Collections.reverse(rdns);
877    return new DN(rdns);
878  }
879
880
881
882  /**
883   * Decodes the provided ASN.1 element as a UTC time element and retrieves the
884   * corresponding time.  As per the X.509 specification, the resulting value
885   * will be guaranteed to fall between the years 1950 and 2049.
886   *
887   * @param  element  The ASN.1 element to decode as a UTC time value.
888   *
889   * @return  The decoded time value.
890   *
891   * @throws  ASN1Exception  If the provided element cannot be decoded as a UTC
892   *                         time element.
893   */
894  private static long decodeUTCTime(@NotNull final ASN1Element element)
895          throws ASN1Exception
896  {
897    final long timeValue = ASN1UTCTime.decodeAsUTCTime(element).getTime();
898
899    final GregorianCalendar calendar = new GregorianCalendar();
900    calendar.setTimeInMillis(timeValue);
901
902    final int year = calendar.get(Calendar.YEAR);
903    if (year < 1949)
904    {
905      calendar.set(Calendar.YEAR, (year + 100));
906    }
907    else if (year > 2050)
908    {
909      calendar.set(Calendar.YEAR, (year - 100));
910    }
911
912    return calendar.getTimeInMillis();
913  }
914
915
916
917  /**
918   * Encodes this X.509 certificate to an ASN.1 element.
919   *
920   * @return  The encoded X.509 certificate.
921   *
922   * @throws  CertException  If a problem is encountered while trying to encode
923   *                         the X.509 certificate.
924   */
925  @NotNull()
926  ASN1Element encode()
927       throws CertException
928  {
929    try
930    {
931      final ArrayList<ASN1Element> tbsCertificateElements = new ArrayList<>(10);
932
933      if (version != X509CertificateVersion.V1)
934      {
935        tbsCertificateElements.add(new ASN1Element(TYPE_EXPLICIT_VERSION,
936             new ASN1Integer(version.getIntValue()).encode()));
937      }
938
939      tbsCertificateElements.add(new ASN1BigInteger(serialNumber));
940
941      if (signatureAlgorithmParameters == null)
942      {
943        tbsCertificateElements.add(new ASN1Sequence(
944             new ASN1ObjectIdentifier(signatureAlgorithmOID)));
945      }
946      else
947      {
948        tbsCertificateElements.add(new ASN1Sequence(
949             new ASN1ObjectIdentifier(signatureAlgorithmOID),
950             signatureAlgorithmParameters));
951      }
952
953
954      tbsCertificateElements.add(encodeName(issuerDN));
955      tbsCertificateElements.add(encodeValiditySequence(notBefore, notAfter));
956      tbsCertificateElements.add(encodeName(subjectDN));
957
958      if (publicKeyAlgorithmParameters == null)
959      {
960        tbsCertificateElements.add(new ASN1Sequence(
961             new ASN1Sequence(
962                  new ASN1ObjectIdentifier(publicKeyAlgorithmOID)),
963             encodedPublicKey));
964      }
965      else
966      {
967        tbsCertificateElements.add(new ASN1Sequence(
968             new ASN1Sequence(
969                  new ASN1ObjectIdentifier(publicKeyAlgorithmOID),
970                  publicKeyAlgorithmParameters),
971             encodedPublicKey));
972      }
973
974      if (issuerUniqueID != null)
975      {
976        tbsCertificateElements.add(new ASN1BitString(
977             TYPE_IMPLICIT_ISSUER_UNIQUE_ID, issuerUniqueID.getBits()));
978      }
979
980      if (subjectUniqueID != null)
981      {
982        tbsCertificateElements.add(new ASN1BitString(
983             TYPE_IMPLICIT_SUBJECT_UNIQUE_ID, subjectUniqueID.getBits()));
984      }
985
986      if (! extensions.isEmpty())
987      {
988        final ArrayList<ASN1Element> extensionElements =
989             new ArrayList<>(extensions.size());
990        for (final X509CertificateExtension e : extensions)
991        {
992          extensionElements.add(e.encode());
993        }
994        tbsCertificateElements.add(new ASN1Element(TYPE_EXPLICIT_EXTENSIONS,
995             new ASN1Sequence(extensionElements).encode()));
996      }
997
998      final ArrayList<ASN1Element> certificateElements = new ArrayList<>(3);
999      certificateElements.add(new ASN1Sequence(tbsCertificateElements));
1000
1001      if (signatureAlgorithmParameters == null)
1002      {
1003        certificateElements.add(new ASN1Sequence(
1004             new ASN1ObjectIdentifier(signatureAlgorithmOID)));
1005      }
1006      else
1007      {
1008        certificateElements.add(new ASN1Sequence(
1009             new ASN1ObjectIdentifier(signatureAlgorithmOID),
1010             signatureAlgorithmParameters));
1011      }
1012
1013      certificateElements.add(signatureValue);
1014
1015      return new ASN1Sequence(certificateElements);
1016    }
1017    catch (final Exception e)
1018    {
1019      Debug.debugException(e);
1020      throw new CertException(
1021           ERR_CERT_ENCODE_ERROR.get(toString(),
1022                StaticUtils.getExceptionMessage(e)),
1023           e);
1024    }
1025  }
1026
1027
1028
1029  /**
1030   * Encodes the provided DN as an X.509 name for inclusion in an encoded
1031   * certificate.
1032   *
1033   * @param  dn  The DN to encode.
1034   *
1035   * @return  The encoded X.509 name.
1036   *
1037   * @throws  CertException  If a problem is encountered while encoding the
1038   *                         provided DN as an X.509 name.
1039   */
1040  @NotNull()
1041  static ASN1Element encodeName(@NotNull final DN dn)
1042         throws CertException
1043  {
1044    final Schema schema;
1045    try
1046    {
1047      schema = Schema.getDefaultStandardSchema();
1048    }
1049    catch (final Exception e)
1050    {
1051      Debug.debugException(e);
1052      throw new CertException(
1053           ERR_CERT_ENCODE_NAME_CANNOT_GET_SCHEMA.get(String.valueOf(dn),
1054                StaticUtils.getExceptionMessage(e)),
1055           e);
1056    }
1057
1058    final RDN[] rdns = dn.getRDNs();
1059    final ArrayList<ASN1Element> rdnSequenceElements =
1060         new ArrayList<>(rdns.length);
1061    for (int i=rdns.length - 1; i >= 0; i--)
1062    {
1063      final RDN rdn =rdns[i];
1064      final String[] names = rdn.getAttributeNames();
1065      final String[] values = rdn.getAttributeValues();
1066
1067      final ArrayList<ASN1Element> rdnElements = new ArrayList<>(names.length);
1068      for (int j=0; j < names.length; j++)
1069      {
1070        final AttributeTypeDefinition at = schema.getAttributeType(names[j]);
1071        if (at == null)
1072        {
1073          throw new CertException(ERR_CERT_ENCODE_NAME_UNKNOWN_ATTR_TYPE.get(
1074               String.valueOf(dn), names[j]));
1075        }
1076
1077        try
1078        {
1079          rdnElements.add(new ASN1Sequence(
1080               new ASN1ObjectIdentifier(at.getOID()),
1081               new ASN1UTF8String(values[j])));
1082        }
1083        catch (final Exception e)
1084        {
1085          Debug.debugException(e);
1086          throw new CertException(
1087               ERR_CERT_ENCODE_NAME_ERROR.get(String.valueOf(dn),
1088                    StaticUtils.getExceptionMessage(e)),
1089               e);
1090        }
1091      }
1092
1093      rdnSequenceElements.add(new ASN1Set(rdnElements));
1094    }
1095
1096    return new ASN1Sequence(rdnSequenceElements);
1097  }
1098
1099
1100
1101  /**
1102   * Encodes the certificate validity sequence, using a UTC time encoding if
1103   * both notBefore and notAfter values fall within the range 1950-2049, and
1104   * using generalized time if either value falls outside that range.
1105   *
1106   * @param  notBefore  The notBefore value to include in the sequence.
1107   * @param  notAfter   The notAfter value to include in the sequence.
1108   *
1109   * @return  The encoded validity sequence.
1110   */
1111  @NotNull()
1112  static ASN1Sequence encodeValiditySequence(final long notBefore,
1113                                             final long notAfter)
1114  {
1115    final GregorianCalendar notBeforeCalendar = new GregorianCalendar();
1116    notBeforeCalendar.setTimeInMillis(notBefore);
1117    final int notBeforeYear = notBeforeCalendar.get(Calendar.YEAR);
1118
1119    final GregorianCalendar notAfterCalendar = new GregorianCalendar();
1120    notAfterCalendar.setTimeInMillis(notAfter);
1121    final int notAfterYear = notAfterCalendar.get(Calendar.YEAR);
1122
1123    if ((notBeforeYear >= 1950) && (notBeforeYear <= 2049) &&
1124        (notAfterYear >= 1950) && (notAfterYear <= 2049))
1125    {
1126      return new ASN1Sequence(
1127           new ASN1UTCTime(notBefore),
1128           new ASN1UTCTime(notAfter));
1129    }
1130    else
1131    {
1132      return new ASN1Sequence(
1133           new ASN1GeneralizedTime(notBefore),
1134           new ASN1GeneralizedTime(notAfter));
1135    }
1136  }
1137
1138
1139
1140  /**
1141   * Generates a self-signed X.509 certificate with the provided information.
1142   *
1143   * @param  signatureAlgorithm  The algorithm to use to generate the signature.
1144   *                             This must not be {@code null}.
1145   * @param  publicKeyAlgorithm  The algorithm to use to generate the key pair.
1146   *                             This must not be {@code null}.
1147   * @param  keySizeBits         The size of the key to generate, in bits.
1148   * @param  subjectDN           The subject DN for the certificate.  This must
1149   *                             not be {@code null}.
1150   * @param  notBefore           The validity start time for the certificate.
1151   * @param  notAfter            The validity end time for the certificate.
1152   * @param  extensions          The set of extensions to include in the
1153   *                             certificate.  This may be {@code null} or empty
1154   *                             if the certificate should not include any
1155   *                             custom extensions.  Note that the generated
1156   *                             certificate will automatically include a
1157   *                             {@link SubjectKeyIdentifierExtension}, so that
1158   *                             should not be provided.
1159   *
1160   * @return  An {@code ObjectPair} that contains both the self-signed
1161   *          certificate and its corresponding key pair.
1162   *
1163   * @throws  CertException  If a problem is encountered while creating the
1164   *                         certificate.
1165   */
1166  @NotNull()
1167  public static ObjectPair<X509Certificate,KeyPair>
1168                     generateSelfSignedCertificate(
1169              @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm,
1170              @NotNull final PublicKeyAlgorithmIdentifier publicKeyAlgorithm,
1171              final int keySizeBits,
1172              @NotNull final DN subjectDN,
1173              final long notBefore, final long notAfter,
1174              @Nullable final X509CertificateExtension... extensions)
1175         throws CertException
1176  {
1177    // Generate the key pair for the certificate.
1178    final KeyPairGenerator keyPairGenerator;
1179    try
1180    {
1181      keyPairGenerator =
1182           CryptoHelper.getKeyPairGenerator(publicKeyAlgorithm.getName());
1183    }
1184    catch (final Exception e)
1185    {
1186      Debug.debugException(e);
1187      throw new CertException(
1188           ERR_CERT_GEN_SELF_SIGNED_CANNOT_GET_KEY_GENERATOR.get(
1189                publicKeyAlgorithm.getName(),
1190                StaticUtils.getExceptionMessage(e)),
1191           e);
1192    }
1193
1194    try
1195    {
1196      keyPairGenerator.initialize(keySizeBits);
1197    }
1198    catch (final Exception e)
1199    {
1200      Debug.debugException(e);
1201      throw new CertException(
1202           ERR_CERT_GEN_SELF_SIGNED_INVALID_KEY_SIZE.get(keySizeBits,
1203                publicKeyAlgorithm.getName(),
1204                StaticUtils.getExceptionMessage(e)),
1205           e);
1206    }
1207
1208    final KeyPair keyPair;
1209    try
1210    {
1211      keyPair = keyPairGenerator.generateKeyPair();
1212    }
1213    catch (final Exception e)
1214    {
1215      Debug.debugException(e);
1216      throw new CertException(
1217           ERR_CERT_GEN_SELF_SIGNED_CANNOT_GENERATE_KEY_PAIR.get(
1218                keySizeBits, publicKeyAlgorithm.getName(),
1219                StaticUtils.getExceptionMessage(e)),
1220           e);
1221    }
1222
1223
1224    // Generate the certificate and return it along with the key pair.
1225    final X509Certificate certificate = generateSelfSignedCertificate(
1226         signatureAlgorithm, keyPair, subjectDN, notBefore, notAfter,
1227         extensions);
1228    return new ObjectPair<>(certificate, keyPair);
1229  }
1230
1231
1232
1233  /**
1234   * Generates a self-signed X.509 certificate with the provided information.
1235   *
1236   * @param  signatureAlgorithm  The algorithm to use to generate the signature.
1237   *                             This must not be {@code null}.
1238   * @param  keyPair             The key pair for the certificate.  This must
1239   *                             not be {@code null}.
1240   * @param  subjectDN           The subject DN for the certificate.  This must
1241   *                             not be {@code null}.
1242   * @param  notBefore           The validity start time for the certificate.
1243   * @param  notAfter            The validity end time for the certificate.
1244   * @param  extensions          The set of extensions to include in the
1245   *                             certificate.  This may be {@code null} or empty
1246   *                             if the certificate should not include any
1247   *                             custom extensions.  Note that the generated
1248   *                             certificate will automatically include a
1249   *                             {@link SubjectKeyIdentifierExtension}, so that
1250   *                             should not be provided.
1251   *
1252   * @return  An {@code ObjectPair} that contains both the self-signed
1253   *          certificate and its corresponding key pair.
1254   *
1255   * @throws  CertException  If a problem is encountered while creating the
1256   *                         certificate.
1257   */
1258  @NotNull()
1259  public static X509Certificate generateSelfSignedCertificate(
1260              @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm,
1261              @NotNull final KeyPair keyPair, @NotNull final DN subjectDN,
1262              final long notBefore, final long notAfter,
1263              @Nullable final X509CertificateExtension... extensions)
1264         throws CertException
1265  {
1266    // Extract the parameters and encoded public key from the generated key
1267    // pair.  And while we're at it, generate a subject key identifier from
1268    // the encoded public key.
1269    DecodedPublicKey decodedPublicKey = null;
1270    final ASN1BitString encodedPublicKey;
1271    final ASN1Element publicKeyAlgorithmParameters;
1272    final byte[] subjectKeyIdentifier;
1273    final OID publicKeyAlgorithmOID;
1274    try
1275    {
1276      final ASN1Element[] pkElements = ASN1Sequence.decodeAsSequence(
1277           keyPair.getPublic().getEncoded()).elements();
1278      final ASN1Element[] pkAlgIDElements = ASN1Sequence.decodeAsSequence(
1279           pkElements[0]).elements();
1280      publicKeyAlgorithmOID =
1281           pkAlgIDElements[0].decodeAsObjectIdentifier().getOID();
1282      if (pkAlgIDElements.length == 1)
1283      {
1284        publicKeyAlgorithmParameters = null;
1285      }
1286      else
1287      {
1288        publicKeyAlgorithmParameters = pkAlgIDElements[1];
1289      }
1290
1291      encodedPublicKey = pkElements[1].decodeAsBitString();
1292
1293      try
1294      {
1295        if (publicKeyAlgorithmOID.equals(
1296             PublicKeyAlgorithmIdentifier.RSA.getOID()))
1297        {
1298          decodedPublicKey = new RSAPublicKey(encodedPublicKey);
1299        }
1300        else if (publicKeyAlgorithmOID.equals(
1301             PublicKeyAlgorithmIdentifier.EC.getOID()))
1302        {
1303          decodedPublicKey = new EllipticCurvePublicKey(encodedPublicKey);
1304        }
1305      }
1306      catch (final Exception e)
1307      {
1308        Debug.debugException(e);
1309      }
1310
1311      final MessageDigest sha256 = CryptoHelper.getMessageDigest(
1312           SubjectKeyIdentifierExtension.
1313                SUBJECT_KEY_IDENTIFIER_DIGEST_ALGORITHM);
1314      subjectKeyIdentifier = sha256.digest(encodedPublicKey.getBytes());
1315    }
1316    catch (final Exception e)
1317    {
1318      Debug.debugException(e);
1319      throw new CertException(
1320           ERR_CERT_GEN_SELF_SIGNED_CANNOT_PARSE_KEY_PAIR.get(
1321                StaticUtils.getExceptionMessage(e)),
1322           e);
1323    }
1324
1325
1326    // Construct the set of all extensions for the certificate.
1327    final ArrayList<X509CertificateExtension> extensionList =
1328         new ArrayList<>(10);
1329    extensionList.add(new SubjectKeyIdentifierExtension(false,
1330         new ASN1OctetString(subjectKeyIdentifier)));
1331    if (extensions != null)
1332    {
1333      for (final X509CertificateExtension e : extensions)
1334      {
1335        if (! e.getOID().equals(SubjectKeyIdentifierExtension.
1336             SUBJECT_KEY_IDENTIFIER_OID))
1337        {
1338          extensionList.add(e);
1339        }
1340      }
1341    }
1342
1343    final X509CertificateExtension[] allExtensions =
1344         new X509CertificateExtension[extensionList.size()];
1345    extensionList.toArray(allExtensions);
1346
1347
1348    // Encode the tbsCertificate sequence for the certificate and use it to
1349    // generate the certificate's signature.
1350    final BigInteger serialNumber = generateSerialNumber();
1351    final ASN1BitString encodedSignature = generateSignature(signatureAlgorithm,
1352         keyPair.getPrivate(), serialNumber, subjectDN, notBefore, notAfter,
1353         subjectDN, publicKeyAlgorithmOID, publicKeyAlgorithmParameters,
1354         encodedPublicKey, allExtensions);
1355
1356
1357    // Construct and return the signed certificate and the private key.
1358    return new X509Certificate(X509CertificateVersion.V3, serialNumber,
1359         signatureAlgorithm.getOID(), null, encodedSignature, subjectDN,
1360         notBefore, notAfter, subjectDN, publicKeyAlgorithmOID,
1361         publicKeyAlgorithmParameters, encodedPublicKey, decodedPublicKey, null,
1362         null, allExtensions);
1363  }
1364
1365
1366
1367  /**
1368   * Generates an issuer-signed X.509 certificate with the provided information.
1369   *
1370   * @param  signatureAlgorithm
1371   *              The algorithm to use to generate the signature.  This must not
1372   *              be {@code null}.
1373   * @param  issuerCertificate
1374   *              The certificate for the issuer.  This must not be
1375   *              {@code null}.
1376   * @param  issuerPrivateKey
1377   *              The private key for the issuer.  This  must not be
1378   *              {@code null}.
1379   * @param  publicKeyAlgorithmOID
1380   *              The OID for the certificate's public key algorithm.  This must
1381   *              not be {@code null}.
1382   * @param  publicKeyAlgorithmParameters
1383   *              The encoded public key algorithm parameters for the
1384   *              certificate.  This may be {@code null} if there are no
1385   *              parameters.
1386   * @param  encodedPublicKey
1387   *              The encoded public key for the certificate.  This must not be
1388   *              {@code null}.
1389   * @param  decodedPublicKey
1390   *              The decoded public key for the certificate.  This may be
1391   *              {@code null} if it is not available.
1392   * @param  subjectDN
1393   *              The subject DN for the certificate.  This must not be
1394   *              {@code null}.
1395   * @param  notBefore
1396   *              The validity start time for the certificate.
1397   * @param  notAfter
1398   *              The validity end time for the certificate.
1399   * @param  extensions
1400   *              The set of extensions to include in the certificate.  This
1401   *              may be {@code null} or empty if the certificate should not
1402   *              include any custom extensions.  Note that the generated
1403   *              certificate will automatically include a
1404   *              {@link SubjectKeyIdentifierExtension}, so that should not be
1405   *              provided.  In addition, if the issuer certificate includes its
1406   *              own {@code SubjectKeyIdentifierExtension}, then its value will
1407   *              be used to generate an
1408   *              {@link AuthorityKeyIdentifierExtension}.
1409   *
1410   * @return  The issuer-signed certificate.
1411   *
1412   * @throws  CertException  If a problem is encountered while creating the
1413   *                         certificate.
1414   */
1415  @NotNull()
1416  public static X509Certificate generateIssuerSignedCertificate(
1417              @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm,
1418              @NotNull final X509Certificate issuerCertificate,
1419              @NotNull final PrivateKey issuerPrivateKey,
1420              @NotNull final OID publicKeyAlgorithmOID,
1421              @Nullable final ASN1Element publicKeyAlgorithmParameters,
1422              @NotNull final ASN1BitString encodedPublicKey,
1423              @Nullable final DecodedPublicKey decodedPublicKey,
1424              @NotNull final DN subjectDN,
1425              final long notBefore, final long notAfter,
1426              @NotNull final X509CertificateExtension... extensions)
1427         throws CertException
1428  {
1429    // Generate a subject key identifier from the encoded public key.
1430    final byte[] subjectKeyIdentifier;
1431    try
1432    {
1433      final MessageDigest sha256 = CryptoHelper.getMessageDigest(
1434           SubjectKeyIdentifierExtension.
1435                SUBJECT_KEY_IDENTIFIER_DIGEST_ALGORITHM);
1436      subjectKeyIdentifier = sha256.digest(encodedPublicKey.getBytes());
1437    }
1438    catch (final Exception e)
1439    {
1440      Debug.debugException(e);
1441      throw new CertException(
1442           ERR_CERT_GEN_ISSUER_SIGNED_CANNOT_GENERATE_KEY_ID.get(
1443                StaticUtils.getExceptionMessage(e)),
1444           e);
1445    }
1446
1447
1448    // If the issuer certificate contains a subject key identifier, then
1449    // extract it to use as the authority key identifier.
1450    ASN1OctetString authorityKeyIdentifier = null;
1451    for (final X509CertificateExtension e : issuerCertificate.extensions)
1452    {
1453      if (e instanceof SubjectKeyIdentifierExtension)
1454      {
1455        authorityKeyIdentifier =
1456             ((SubjectKeyIdentifierExtension) e).getKeyIdentifier();
1457      }
1458    }
1459
1460
1461    // Construct the set of all extensions for the certificate.
1462    final ArrayList<X509CertificateExtension> extensionList =
1463         new ArrayList<>(10);
1464    extensionList.add(new SubjectKeyIdentifierExtension(false,
1465         new ASN1OctetString(subjectKeyIdentifier)));
1466
1467    if (authorityKeyIdentifier == null)
1468    {
1469      extensionList.add(new AuthorityKeyIdentifierExtension(false, null,
1470           new GeneralNamesBuilder().addDirectoryName(
1471                issuerCertificate.subjectDN).build(),
1472           issuerCertificate.serialNumber));
1473    }
1474    else
1475    {
1476      extensionList.add(new AuthorityKeyIdentifierExtension(false,
1477           authorityKeyIdentifier, null, null));
1478    }
1479
1480    if (extensions != null)
1481    {
1482      for (final X509CertificateExtension e : extensions)
1483      {
1484        if (e.getOID().equals(
1485             SubjectKeyIdentifierExtension.SUBJECT_KEY_IDENTIFIER_OID) ||
1486            e.getOID().equals(
1487                 AuthorityKeyIdentifierExtension.AUTHORITY_KEY_IDENTIFIER_OID))
1488        {
1489          continue;
1490        }
1491
1492        extensionList.add(e);
1493      }
1494    }
1495
1496    final X509CertificateExtension[] allExtensions =
1497         new X509CertificateExtension[extensionList.size()];
1498    extensionList.toArray(allExtensions);
1499
1500
1501    // Encode the tbsCertificate sequence for the certificate and use it to
1502    // generate the certificate's signature.
1503    final BigInteger serialNumber = generateSerialNumber();
1504    final ASN1BitString encodedSignature = generateSignature(signatureAlgorithm,
1505         issuerPrivateKey, serialNumber, issuerCertificate.subjectDN, notBefore,
1506         notAfter, subjectDN, publicKeyAlgorithmOID,
1507         publicKeyAlgorithmParameters, encodedPublicKey, allExtensions);
1508
1509
1510    // Construct and return the signed certificate.
1511    return new X509Certificate(X509CertificateVersion.V3, serialNumber,
1512         signatureAlgorithm.getOID(), null, encodedSignature,
1513         issuerCertificate.subjectDN, notBefore, notAfter, subjectDN,
1514         publicKeyAlgorithmOID, publicKeyAlgorithmParameters, encodedPublicKey,
1515         decodedPublicKey, null, null, allExtensions);
1516  }
1517
1518
1519
1520  /**
1521   * Generates a serial number for the certificate.
1522   *
1523   * @return  The generated serial number.
1524   */
1525  @NotNull()
1526  private static BigInteger generateSerialNumber()
1527  {
1528    final UUID uuid = CryptoHelper.getRandomUUID();
1529    final long msb = uuid.getMostSignificantBits() & 0x7FFF_FFFF_FFFF_FFFFL;
1530    final long lsb = uuid.getLeastSignificantBits() & 0x7FFF_FFFF_FFFF_FFFFL;
1531    return BigInteger.valueOf(msb).shiftLeft(64).add(BigInteger.valueOf(lsb));
1532  }
1533
1534
1535
1536  /**
1537   * Generates a signature for the certificate with the provided information.
1538   *
1539   * @param  signatureAlgorithm            The signature algorithm to use to
1540   *                                       generate the signature.  This must
1541   *                                       not be {@code null}.
1542   * @param  privateKey                    The private key to use to sign the
1543   *                                       certificate.  This must not be
1544   *                                       {@code null}.
1545   * @param  serialNumber                  The serial number for the
1546   *                                       certificate.  This must not be
1547   *                                       {@code null}.
1548   * @param  issuerDN                      The issuer DN for the certificate.
1549   *                                       This must not be {@code null}.
1550   * @param  notBefore                     The validity start time for the
1551   *                                       certificate.
1552   * @param  notAfter                      The validity end time for the
1553   *                                       certificate.
1554   * @param  subjectDN                     The subject DN for the certificate.
1555   *                                       This must not be {@code null}.
1556   * @param  publicKeyAlgorithmOID         The OID for the public key algorithm.
1557   *                                       This must not be {@code null}.
1558   * @param  publicKeyAlgorithmParameters  The encoded public key algorithm
1559   *                                       parameters.  This may be
1560   *                                       {@code null} if no parameters are
1561   *                                       needed.
1562   * @param  encodedPublicKey              The encoded representation of the
1563   *                                       public key.  This must not be
1564   *                                       {@code null}.
1565   * @param  extensions                    The set of extensions to include in
1566   *                                       the certificate.  This must not be
1567   *                                       {@code null} but may be empty.
1568   *
1569   * @return  An encoded representation of the generated signature.
1570   *
1571   * @throws  CertException  If a problem is encountered while generating the
1572   *                         certificate.
1573   */
1574  @NotNull()
1575  private static ASN1BitString generateSignature(
1576               @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm,
1577               @NotNull final PrivateKey privateKey,
1578               @NotNull final BigInteger serialNumber,
1579               @NotNull final DN issuerDN, final long notBefore,
1580               final long notAfter, @NotNull final DN subjectDN,
1581               @NotNull final OID publicKeyAlgorithmOID,
1582               @Nullable final ASN1Element publicKeyAlgorithmParameters,
1583               @NotNull final ASN1BitString encodedPublicKey,
1584               @NotNull final X509CertificateExtension... extensions)
1585          throws CertException
1586  {
1587    // Get and initialize the signature generator.
1588    final Signature signature;
1589    try
1590    {
1591      signature = CryptoHelper.getSignature(signatureAlgorithm.getJavaName());
1592    }
1593    catch (final Exception e)
1594    {
1595      Debug.debugException(e);
1596      throw new CertException(
1597           ERR_CERT_GEN_SIGNATURE_CANNOT_GET_SIGNATURE_GENERATOR.get(
1598                signatureAlgorithm.getJavaName(),
1599                StaticUtils.getExceptionMessage(e)),
1600           e);
1601    }
1602
1603    try
1604    {
1605      signature.initSign(privateKey);
1606    }
1607    catch (final Exception e)
1608    {
1609      Debug.debugException(e);
1610      throw new CertException(
1611           ERR_CERT_GEN_SIGNATURE_CANNOT_INIT_SIGNATURE_GENERATOR.get(
1612                signatureAlgorithm.getJavaName(),
1613                StaticUtils.getExceptionMessage(e)),
1614           e);
1615    }
1616
1617
1618    // Construct the tbsCertificate element of the certificate and compute its
1619    // signature.
1620    try
1621    {
1622      final ArrayList<ASN1Element> tbsCertificateElements = new ArrayList<>(8);
1623      tbsCertificateElements.add(new ASN1Element(TYPE_EXPLICIT_VERSION,
1624           new ASN1Integer(X509CertificateVersion.V3.getIntValue()).encode()));
1625      tbsCertificateElements.add(new ASN1BigInteger(serialNumber));
1626      tbsCertificateElements.add(new ASN1Sequence(
1627           new ASN1ObjectIdentifier(signatureAlgorithm.getOID())));
1628      tbsCertificateElements.add(encodeName(issuerDN));
1629      tbsCertificateElements.add(encodeValiditySequence(notBefore, notAfter));
1630      tbsCertificateElements.add(encodeName(subjectDN));
1631
1632      if (publicKeyAlgorithmParameters == null)
1633      {
1634        tbsCertificateElements.add(new ASN1Sequence(
1635             new ASN1Sequence(
1636                  new ASN1ObjectIdentifier(publicKeyAlgorithmOID)),
1637             encodedPublicKey));
1638      }
1639      else
1640      {
1641        tbsCertificateElements.add(new ASN1Sequence(
1642             new ASN1Sequence(
1643                  new ASN1ObjectIdentifier(publicKeyAlgorithmOID),
1644                  publicKeyAlgorithmParameters),
1645             encodedPublicKey));
1646      }
1647
1648      final ArrayList<ASN1Element> extensionElements =
1649           new ArrayList<>(extensions.length);
1650      for (final X509CertificateExtension e : extensions)
1651      {
1652        extensionElements.add(e.encode());
1653      }
1654      tbsCertificateElements.add(new ASN1Element(TYPE_EXPLICIT_EXTENSIONS,
1655           new ASN1Sequence(extensionElements).encode()));
1656
1657      final byte[] tbsCertificateBytes =
1658           new ASN1Sequence(tbsCertificateElements).encode();
1659      signature.update(tbsCertificateBytes);
1660      final byte[] signatureBytes = signature.sign();
1661
1662      return new ASN1BitString(ASN1BitString.getBitsForBytes(signatureBytes));
1663    }
1664    catch (final Exception e)
1665    {
1666      Debug.debugException(e);
1667      throw new CertException(
1668           ERR_CERT_GEN_SIGNATURE_CANNOT_COMPUTE.get(
1669                signatureAlgorithm.getJavaName(),
1670                StaticUtils.getExceptionMessage(e)),
1671           e);
1672    }
1673  }
1674
1675
1676
1677  /**
1678   * Retrieves the bytes that comprise the encoded representation of this X.509
1679   * certificate.
1680   *
1681   * @return  The bytes that comprise the encoded representation of this X.509
1682   *          certificate.
1683   */
1684  @NotNull()
1685  public byte[] getX509CertificateBytes()
1686  {
1687    return x509CertificateBytes;
1688  }
1689
1690
1691
1692  /**
1693   * Retrieves the certificate version.
1694   *
1695   * @return  The certificate version.
1696   */
1697  @NotNull()
1698  public X509CertificateVersion getVersion()
1699  {
1700    return version;
1701  }
1702
1703
1704
1705  /**
1706   * Retrieves the certificate serial number.
1707   *
1708   * @return  The certificate serial number.
1709   */
1710  @NotNull()
1711  public BigInteger getSerialNumber()
1712  {
1713    return serialNumber;
1714  }
1715
1716
1717
1718  /**
1719   * Retrieves the certificate signature algorithm OID.
1720   *
1721   * @return  The certificate signature algorithm OID.
1722   */
1723  @NotNull()
1724  public OID getSignatureAlgorithmOID()
1725  {
1726    return signatureAlgorithmOID;
1727  }
1728
1729
1730
1731  /**
1732   * Retrieves the certificate signature algorithm name, if available.
1733   *
1734   * @return  The certificate signature algorithm name, or {@code null} if the
1735   *          signature algorithm OID does not correspond to any known algorithm
1736   *          name.
1737   */
1738  @Nullable()
1739  public String getSignatureAlgorithmName()
1740  {
1741    return signatureAlgorithmName;
1742  }
1743
1744
1745
1746  /**
1747   * Retrieves the signature algorithm name if it is available, or the string
1748   * representation of the signature algorithm OID if not.
1749   *
1750   * @return  The signature algorithm name or OID.
1751   */
1752  @NotNull()
1753  public String getSignatureAlgorithmNameOrOID()
1754  {
1755    if (signatureAlgorithmName != null)
1756    {
1757      return signatureAlgorithmName;
1758    }
1759    else
1760    {
1761      return signatureAlgorithmOID.toString();
1762    }
1763  }
1764
1765
1766
1767  /**
1768   * Retrieves the encoded signature algorithm parameters, if present.
1769   *
1770   * @return  The encoded signature algorithm parameters, or {@code null} if
1771   *          there are no signature algorithm parameters.
1772   */
1773  @Nullable()
1774  public ASN1Element getSignatureAlgorithmParameters()
1775  {
1776    return signatureAlgorithmParameters;
1777  }
1778
1779
1780
1781  /**
1782   * Retrieves the certificate issuer DN.
1783   *
1784   * @return  The certificate issuer DN.
1785   */
1786  @NotNull()
1787  public DN getIssuerDN()
1788  {
1789    return issuerDN;
1790  }
1791
1792
1793
1794  /**
1795   * Retrieves the certificate validity start time as the number of milliseconds
1796   * since the epoch (January 1, 1970 UTC).
1797   *
1798   * @return  The certificate validity start time as the number of milliseconds
1799   *          since the epoch.
1800   */
1801  public long getNotBeforeTime()
1802  {
1803    return notBefore;
1804  }
1805
1806
1807
1808  /**
1809   * Retrieves the certificate validity start time as a {@code Date}.
1810   *
1811   * @return  The certificate validity start time as a {@code Date}.
1812   */
1813  @NotNull()
1814  public Date getNotBeforeDate()
1815  {
1816    return new Date(notBefore);
1817  }
1818
1819
1820
1821  /**
1822   * Retrieves the certificate validity end time as the number of milliseconds
1823   * since the epoch (January 1, 1970 UTC).
1824   *
1825   * @return  The certificate validity end time as the number of milliseconds
1826   *          since the epoch.
1827   */
1828  public long getNotAfterTime()
1829  {
1830    return notAfter;
1831  }
1832
1833
1834
1835  /**
1836   * Retrieves the certificate validity end time as a {@code Date}.
1837   *
1838   * @return  The certificate validity end time as a {@code Date}.
1839   */
1840  @NotNull()
1841  public Date getNotAfterDate()
1842  {
1843    return new Date(notAfter);
1844  }
1845
1846
1847
1848  /**
1849   * Indicates whether the current time is within the certificate's validity
1850   * window.
1851   *
1852   * @return  {@code true} if the current time is within the certificate's
1853   *          validity window, or {@code false} if not.
1854   */
1855  public boolean isWithinValidityWindow()
1856  {
1857    return isWithinValidityWindow(System.currentTimeMillis());
1858  }
1859
1860
1861
1862  /**
1863   * Indicates whether the provided {@code Date} represents a time within the
1864   * certificate's validity window.
1865   *
1866   * @param  date  The {@code Date} for which to make the determination.  It
1867   *               must not be {@code null}.
1868   *
1869   * @return  {@code true} if the provided {@code Date} is within the
1870   *          certificate's validity window, or {@code false} if not.
1871   */
1872  public boolean isWithinValidityWindow(@NotNull final Date date)
1873  {
1874    return isWithinValidityWindow(date.getTime());
1875  }
1876
1877
1878
1879  /**
1880   * Indicates whether the specified time is within the certificate's validity
1881   * window.
1882   *
1883   * @param  time  The time to for which to make the determination.
1884   *
1885   * @return  {@code true} if the specified time is within the certificate's
1886   *          validity window, or {@code false} if not.
1887   */
1888  public boolean isWithinValidityWindow(final long time)
1889  {
1890    return ((time >= notBefore) && (time <= notAfter));
1891  }
1892
1893
1894
1895  /**
1896   * Retrieves the certificate subject DN.
1897   *
1898   * @return  The certificate subject DN.
1899   */
1900  @NotNull()
1901  public DN getSubjectDN()
1902  {
1903    return subjectDN;
1904  }
1905
1906
1907
1908  /**
1909   * Retrieves the certificate public key algorithm OID.
1910   *
1911   * @return  The certificate public key algorithm OID.
1912   */
1913  @NotNull()
1914  public OID getPublicKeyAlgorithmOID()
1915  {
1916    return publicKeyAlgorithmOID;
1917  }
1918
1919
1920
1921  /**
1922   * Retrieves the certificate public key algorithm name, if available.
1923   *
1924   * @return  The certificate public key algorithm name, or {@code null} if the
1925   *          public key algorithm OID does not correspond to any known
1926   *          algorithm name.
1927   */
1928  @Nullable()
1929  public String getPublicKeyAlgorithmName()
1930  {
1931    return publicKeyAlgorithmName;
1932  }
1933
1934
1935
1936  /**
1937   * Retrieves the public key algorithm name if it is available, or the string
1938   * representation of the public key algorithm OID if not.
1939   *
1940   * @return  The signature algorithm name or OID.
1941   */
1942  @NotNull()
1943  public String getPublicKeyAlgorithmNameOrOID()
1944  {
1945    if (publicKeyAlgorithmName != null)
1946    {
1947      return publicKeyAlgorithmName;
1948    }
1949    else
1950    {
1951      return publicKeyAlgorithmOID.toString();
1952    }
1953  }
1954
1955
1956
1957  /**
1958   * Retrieves the encoded public key algorithm parameters, if present.
1959   *
1960   * @return  The encoded public key algorithm parameters, or {@code null} if
1961   *          there are no public key algorithm parameters.
1962   */
1963  @Nullable()
1964  public ASN1Element getPublicKeyAlgorithmParameters()
1965  {
1966    return publicKeyAlgorithmParameters;
1967  }
1968
1969
1970
1971  /**
1972   * Retrieves the encoded public key as a bit string.
1973   *
1974   * @return  The encoded public key as a bit string.
1975   */
1976  @NotNull()
1977  public ASN1BitString getEncodedPublicKey()
1978  {
1979    return encodedPublicKey;
1980  }
1981
1982
1983
1984  /**
1985   * Retrieves a decoded representation of the public key, if available.
1986   *
1987   * @return  A decoded representation of the public key, or {@code null} if the
1988   *          public key could not be decoded.
1989   */
1990  @Nullable()
1991  public DecodedPublicKey getDecodedPublicKey()
1992  {
1993    return decodedPublicKey;
1994  }
1995
1996
1997
1998  /**
1999   * Retrieves the issuer unique identifier for the certificate, if any.
2000   *
2001   * @return  The issuer unique identifier for the certificate, or {@code null}
2002   *          if there is none.
2003   */
2004  @Nullable()
2005  public ASN1BitString getIssuerUniqueID()
2006  {
2007    return issuerUniqueID;
2008  }
2009
2010
2011
2012  /**
2013   * Retrieves the subject unique identifier for the certificate, if any.
2014   *
2015   * @return  The subject unique identifier for the certificate, or {@code null}
2016   *          if there is none.
2017   */
2018  @Nullable()
2019  public ASN1BitString getSubjectUniqueID()
2020  {
2021    return subjectUniqueID;
2022  }
2023
2024
2025
2026  /**
2027   * Retrieves the list of certificate extensions.
2028   *
2029   * @return  The list of certificate extensions.
2030   */
2031  @NotNull()
2032  public List<X509CertificateExtension> getExtensions()
2033  {
2034    return extensions;
2035  }
2036
2037
2038
2039  /**
2040   * Retrieves the signature value for the certificate.
2041   *
2042   * @return  The signature value for the certificate.
2043   */
2044  @NotNull()
2045  public ASN1BitString getSignatureValue()
2046  {
2047    return signatureValue;
2048  }
2049
2050
2051
2052  /**
2053   * Verifies the signature for this certificate.
2054   *
2055   * @param  issuerCertificate  The issuer certificate for this certificate.  It
2056   *                            may be {@code null} if this is a self-signed
2057   *                            certificate.  It must not be {@code null} if it
2058   *                            is not a self-signed certificate.
2059   *
2060   * @throws  CertException  If the certificate signature could not be verified.
2061   */
2062  public void verifySignature(@Nullable final X509Certificate issuerCertificate)
2063         throws CertException
2064  {
2065    // Get the issuer certificate.  If the certificate is self-signed, then it
2066    // might be the current certificate.
2067    final X509Certificate issuer;
2068    if (issuerCertificate == null)
2069    {
2070      if (isSelfSigned())
2071      {
2072        issuer = this;
2073      }
2074      else
2075      {
2076        throw new CertException(
2077             ERR_CERT_VERIFY_SIGNATURE_ISSUER_CERT_NOT_PROVIDED.get());
2078      }
2079    }
2080    else
2081    {
2082      issuer = issuerCertificate;
2083    }
2084
2085
2086    // Get the public key from the issuer certificate.
2087    final PublicKey publicKey;
2088    try
2089    {
2090      publicKey = issuer.toCertificate().getPublicKey();
2091    }
2092    catch (final Exception e)
2093    {
2094      Debug.debugException(e);
2095      throw new CertException(
2096           ERR_CERT_VERIFY_SIGNATURE_CANNOT_GET_PUBLIC_KEY.get(
2097                StaticUtils.getExceptionMessage(e)),
2098           e);
2099    }
2100
2101
2102    // Get and initialize the signature generator.
2103    final Signature signature;
2104    final SignatureAlgorithmIdentifier signatureAlgorithm;
2105    try
2106    {
2107      signatureAlgorithm =
2108           SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID);
2109      signature = CryptoHelper.getSignature(signatureAlgorithm.getJavaName());
2110    }
2111    catch (final Exception e)
2112    {
2113      Debug.debugException(e);
2114      throw new CertException(
2115           ERR_CERT_VERIFY_SIGNATURE_CANNOT_GET_SIGNATURE_VERIFIER.get(
2116                getSignatureAlgorithmNameOrOID(),
2117                StaticUtils.getExceptionMessage(e)),
2118           e);
2119    }
2120
2121    try
2122    {
2123      signature.initVerify(publicKey);
2124    }
2125    catch (final Exception e)
2126    {
2127      Debug.debugException(e);
2128      throw new CertException(
2129           ERR_CERT_VERIFY_SIGNATURE_CANNOT_INIT_SIGNATURE_VERIFIER.get(
2130                signatureAlgorithm.getJavaName(),
2131                StaticUtils.getExceptionMessage(e)),
2132           e);
2133    }
2134
2135
2136    // Construct the tbsCertificate element of the certificate and compute its
2137    // signature.
2138    try
2139    {
2140      final ASN1Element[] x509CertificateElements =
2141           ASN1Sequence.decodeAsSequence(x509CertificateBytes).elements();
2142      final byte[] tbsCertificateBytes = x509CertificateElements[0].encode();
2143      signature.update(tbsCertificateBytes);
2144    }
2145    catch (final Exception e)
2146    {
2147      Debug.debugException(e);
2148      throw new CertException(
2149           ERR_CERT_GEN_SIGNATURE_CANNOT_COMPUTE.get(
2150                signatureAlgorithm.getJavaName(),
2151                StaticUtils.getExceptionMessage(e)),
2152           e);
2153    }
2154
2155
2156    try
2157    {
2158      if (! signature.verify(signatureValue.getBytes()))
2159      {
2160        throw new CertException(
2161             ERR_CERT_VERIFY_SIGNATURE_NOT_VALID.get(subjectDN));
2162      }
2163    }
2164    catch (final CertException ce)
2165    {
2166      Debug.debugException(ce);
2167      throw ce;
2168    }
2169    catch (final Exception e)
2170    {
2171      Debug.debugException(e);
2172      throw new CertException(
2173           ERR_CERT_VERIFY_SIGNATURE_ERROR.get(subjectDN,
2174                StaticUtils.getExceptionMessage(e)),
2175           e);
2176    }
2177  }
2178
2179
2180
2181  /**
2182   * Retrieves the bytes that comprise a SHA-1 fingerprint of this certificate.
2183   *
2184   * @return  The bytes that comprise a SHA-1 fingerprint of this certificate.
2185   *
2186   * @throws  CertException  If a problem is encountered while computing the
2187   *                         fingerprint.
2188   */
2189  @NotNull()
2190  public byte[] getSHA1Fingerprint()
2191         throws CertException
2192  {
2193    return getFingerprint("SHA-1");
2194  }
2195
2196
2197
2198  /**
2199   * Retrieves the bytes that comprise a 256-bit SHA-2 fingerprint of this
2200   * certificate.
2201   *
2202   * @return  The bytes that comprise a 256-bit SHA-2 fingerprint of this
2203   *          certificate.
2204   *
2205   * @throws  CertException  If a problem is encountered while computing the
2206   *                         fingerprint.
2207   */
2208  @NotNull()
2209  public byte[] getSHA256Fingerprint()
2210         throws CertException
2211  {
2212    return getFingerprint("SHA-256");
2213  }
2214
2215
2216
2217  /**
2218   * Retrieves the bytes that comprise a fingerprint of this certificate.
2219   *
2220   * @param  digestAlgorithm  The digest algorithm to use to generate the
2221   *                          fingerprint.
2222   *
2223   * @return  The bytes that comprise a fingerprint of this certificate.
2224   *
2225   * @throws  CertException  If a problem is encountered while computing the
2226   *                         fingerprint.
2227   */
2228  @NotNull()
2229  private byte[] getFingerprint(@NotNull final String digestAlgorithm)
2230          throws CertException
2231  {
2232    try
2233    {
2234      final MessageDigest digest =
2235           CryptoHelper.getMessageDigest(digestAlgorithm);
2236      return digest.digest(x509CertificateBytes);
2237    }
2238    catch (final Exception e)
2239    {
2240      // This should never happen.
2241      Debug.debugException(e);
2242      throw new CertException(
2243           ERR_CERT_CANNOT_COMPUTE_FINGERPRINT.get(digestAlgorithm,
2244                StaticUtils.getExceptionMessage(e)),
2245           e);
2246    }
2247  }
2248
2249
2250
2251  /**
2252   * Indicates whether this certificate is self-signed.  The following criteria
2253   * will be used to make the determination:
2254   * <OL>
2255   *   <LI>
2256   *     If the certificate has both subject key identifier and authority
2257   *     key identifier extensions, then it will be considered self-signed if
2258   *     and only if the subject key identifier matches the authority key
2259   *     identifier.
2260   *   </LI>
2261   *   <LI>
2262   *     If the certificate does not have both a subject key identifier and an
2263   *     authority key identifier, then it will be considered self-signed if and
2264   *     only if its subject DN matches its issuer DN.
2265   *   </LI>
2266   * </OL>
2267   *
2268   * @return  {@code true} if this certificate is self-signed, or {@code false}
2269   *          if it is not.
2270   */
2271  public boolean isSelfSigned()
2272  {
2273    AuthorityKeyIdentifierExtension akie = null;
2274    SubjectKeyIdentifierExtension skie = null;
2275    for (final X509CertificateExtension e : extensions)
2276    {
2277      if (e instanceof AuthorityKeyIdentifierExtension)
2278      {
2279        akie = (AuthorityKeyIdentifierExtension) e;
2280      }
2281      else if (e instanceof SubjectKeyIdentifierExtension)
2282      {
2283        skie = (SubjectKeyIdentifierExtension) e;
2284      }
2285    }
2286
2287    if ((akie != null) && (skie != null))
2288    {
2289      return ((akie.getKeyIdentifier() != null) &&
2290           Arrays.equals(akie.getKeyIdentifier().getValue(),
2291                skie.getKeyIdentifier().getValue()));
2292    }
2293    else
2294    {
2295      return subjectDN.equals(issuerDN);
2296    }
2297  }
2298
2299
2300
2301  /**
2302   * Indicates whether this certificate is the issuer for the provided
2303   * certificate.  In order for this to be true, the following conditions must
2304   * be met:
2305   * <OL>
2306   *   <LI>
2307   *     The subject DN of this certificate must match the issuer DN for the
2308   *     provided certificate.
2309   *   </LI>
2310   *   <LI>
2311   *     If the provided certificate has an authority key identifier extension,
2312   *     then this certificate must have a subject key identifier extension with
2313   *     a matching identifier value.
2314   *   </LI>
2315   * </OL>
2316   *
2317   * @param  c  The certificate for which to make the determination.  This must
2318   *            not be {@code null}.
2319   *
2320   * @return  {@code true} if this certificate is considered the issuer for the
2321   *          provided certificate, or {@code } false if not.
2322   */
2323  public boolean isIssuerFor(@NotNull final X509Certificate c)
2324  {
2325    return isIssuerFor(c, null);
2326  }
2327
2328
2329
2330  /**
2331   * Indicates whether this certificate is the issuer for the provided
2332   * certificate.  In order for this to be true, the following conditions must
2333   * be met:
2334   * <OL>
2335   *   <LI>
2336   *     The subject DN of this certificate must match the issuer DN for the
2337   *     provided certificate.
2338   *   </LI>
2339   *   <LI>
2340   *     If the provided certificate has an authority key identifier extension,
2341   *     then this certificate must have a subject key identifier extension with
2342   *     a matching identifier value.
2343   *   </LI>
2344   * </OL>
2345   *
2346   * @param  c               The certificate for which to make the
2347   *                         determination.  This must not be {@code null}.
2348   * @param  nonMatchReason  An optional buffer that may be updated with the
2349   *                         reason that this certificate is not considered the
2350   *                         issuer for the provided certificate.  This may be
2351   *                         {@code null} if the caller does not require a
2352   *                         reason.
2353   *
2354   * @return  {@code true} if this certificate is considered the issuer for the
2355   *          provided certificate, or {@code } false if not.
2356   */
2357  public boolean isIssuerFor(@NotNull final X509Certificate c,
2358                             @Nullable final StringBuilder nonMatchReason)
2359  {
2360    if (! c.issuerDN.equals(subjectDN))
2361    {
2362      if (nonMatchReason != null)
2363      {
2364        nonMatchReason.append(INFO_CERT_IS_ISSUER_FOR_DN_MISMATCH.get(
2365             subjectDN, c.subjectDN, issuerDN));
2366      }
2367
2368      return false;
2369    }
2370
2371
2372    byte[] authorityKeyIdentifier = null;
2373    for (final X509CertificateExtension extension : c.extensions)
2374    {
2375      if (extension instanceof AuthorityKeyIdentifierExtension)
2376      {
2377        final AuthorityKeyIdentifierExtension akie =
2378             (AuthorityKeyIdentifierExtension) extension;
2379        if (akie.getKeyIdentifier() != null)
2380        {
2381          authorityKeyIdentifier = akie.getKeyIdentifier().getValue();
2382          break;
2383        }
2384      }
2385    }
2386
2387    if (authorityKeyIdentifier != null)
2388    {
2389      boolean matchFound = false;
2390      for (final X509CertificateExtension extension : extensions)
2391      {
2392        if (extension instanceof SubjectKeyIdentifierExtension)
2393        {
2394          final SubjectKeyIdentifierExtension skie =
2395               (SubjectKeyIdentifierExtension) extension;
2396          matchFound = Arrays.equals(authorityKeyIdentifier,
2397               skie.getKeyIdentifier().getValue());
2398          break;
2399        }
2400      }
2401
2402      if (! matchFound)
2403      {
2404        if (nonMatchReason != null)
2405        {
2406          nonMatchReason.append(INFO_CERT_IS_ISSUER_FOR_KEY_ID_MISMATCH.get(
2407               subjectDN, c.subjectDN));
2408        }
2409
2410        return false;
2411      }
2412    }
2413
2414
2415    return true;
2416  }
2417
2418
2419
2420  /**
2421   * Converts this X.509 certificate object to a Java {@code Certificate}
2422   * object.
2423   *
2424   * @return  The Java {@code Certificate} object that corresponds to this
2425   *          X.509 certificate.
2426   *
2427   * @throws  CertificateException  If a problem is encountered while performing
2428   *                                the conversion.
2429   */
2430  @NotNull()
2431  public Certificate toCertificate()
2432         throws CertificateException
2433  {
2434    return CryptoHelper.getCertificateFactory("X.509").generateCertificate(
2435         new ByteArrayInputStream(x509CertificateBytes));
2436  }
2437
2438
2439
2440  /**
2441   * Retrieves a hash code for this certificate.
2442   *
2443   * @return  A hash code for this certificate.
2444   */
2445  @Override()
2446  public int hashCode()
2447  {
2448    return Arrays.hashCode(x509CertificateBytes);
2449  }
2450
2451
2452
2453  /**
2454   * Indicates whether the provided object is considered equal to this X.509
2455   * certificate.
2456   *
2457   * @param  o  The object for which to make the determination.
2458   *
2459   * @return  {@code true} if the provided object is considered equal to this
2460   *          X.509 certificate, or {@code false} if not.
2461   */
2462  @Override()
2463  public boolean equals(@Nullable final Object o)
2464  {
2465    if (o == null)
2466    {
2467      return false;
2468    }
2469
2470    if (o == this)
2471    {
2472      return true;
2473    }
2474
2475    if (! (o instanceof X509Certificate))
2476    {
2477      return false;
2478    }
2479
2480    final X509Certificate c = (X509Certificate) o;
2481    return Arrays.equals(x509CertificateBytes, c.x509CertificateBytes);
2482  }
2483
2484
2485
2486  /**
2487   * Retrieves a string representation of the decoded X.509 certificate.
2488   *
2489   * @return  A string representation of the decoded X.509 certificate.
2490   */
2491  @Override()
2492  @NotNull()
2493  public String toString()
2494  {
2495    final StringBuilder buffer = new StringBuilder();
2496    toString(buffer);
2497    return buffer.toString();
2498  }
2499
2500
2501
2502  /**
2503   * Appends a string representation of the decoded X.509 certificate to the
2504   * provided buffer.
2505   *
2506   * @param  buffer  The buffer to which the information should be appended.
2507   */
2508  public void toString(@NotNull final StringBuilder buffer)
2509  {
2510    buffer.append("X509Certificate(version='");
2511    buffer.append(version.getName());
2512    buffer.append("', serialNumber='");
2513    StaticUtils.toHex(serialNumber.toByteArray(), ":", buffer);
2514    buffer.append("', signatureAlgorithmOID='");
2515    buffer.append(signatureAlgorithmOID.toString());
2516    buffer.append('\'');
2517
2518    if (signatureAlgorithmName != null)
2519    {
2520      buffer.append(", signatureAlgorithmName='");
2521      buffer.append(signatureAlgorithmName);
2522      buffer.append('\'');
2523    }
2524
2525    buffer.append(", issuerDN='");
2526    buffer.append(issuerDN.toString());
2527    buffer.append("', notBefore='");
2528    buffer.append(StaticUtils.encodeGeneralizedTime(notBefore));
2529    buffer.append("', notAfter='");
2530    buffer.append(StaticUtils.encodeGeneralizedTime(notAfter));
2531    buffer.append("', subjectDN='");
2532    buffer.append(subjectDN.toString());
2533    buffer.append("', publicKeyAlgorithmOID='");
2534    buffer.append(publicKeyAlgorithmOID.toString());
2535    buffer.append('\'');
2536
2537    if (publicKeyAlgorithmName != null)
2538    {
2539      buffer.append(", publicKeyAlgorithmName='");
2540      buffer.append(publicKeyAlgorithmName);
2541      buffer.append('\'');
2542    }
2543
2544    buffer.append(", subjectPublicKey=");
2545    if (decodedPublicKey == null)
2546    {
2547      buffer.append('\'');
2548
2549      try
2550      {
2551        StaticUtils.toHex(encodedPublicKey.getBytes(), ":", buffer);
2552      }
2553      catch (final Exception e)
2554      {
2555        Debug.debugException(e);
2556        encodedPublicKey.toString(buffer);
2557      }
2558
2559      buffer.append('\'');
2560    }
2561    else
2562    {
2563      decodedPublicKey.toString(buffer);
2564
2565      if (decodedPublicKey instanceof EllipticCurvePublicKey)
2566      {
2567        try
2568        {
2569          final OID namedCurveOID =
2570               publicKeyAlgorithmParameters.decodeAsObjectIdentifier().getOID();
2571          buffer.append(", ellipticCurvePublicKeyParameters=namedCurve='");
2572          buffer.append(NamedCurve.getNameOrOID(namedCurveOID));
2573          buffer.append('\'');
2574        }
2575        catch (final Exception e)
2576        {
2577          Debug.debugException(e);
2578        }
2579      }
2580    }
2581
2582    if (issuerUniqueID != null)
2583    {
2584      buffer.append(", issuerUniqueID='");
2585      buffer.append(issuerUniqueID.toString());
2586      buffer.append('\'');
2587    }
2588
2589    if (subjectUniqueID != null)
2590    {
2591      buffer.append(", subjectUniqueID='");
2592      buffer.append(subjectUniqueID.toString());
2593      buffer.append('\'');
2594    }
2595
2596    if (! extensions.isEmpty())
2597    {
2598      buffer.append(", extensions={");
2599
2600      final Iterator<X509CertificateExtension> iterator = extensions.iterator();
2601      while (iterator.hasNext())
2602      {
2603        iterator.next().toString(buffer);
2604        if (iterator.hasNext())
2605        {
2606          buffer.append(", ");
2607        }
2608      }
2609
2610      buffer.append('}');
2611    }
2612
2613    buffer.append(", signatureValue='");
2614
2615    try
2616    {
2617      StaticUtils.toHex(signatureValue.getBytes(), ":", buffer);
2618    }
2619    catch (final Exception e)
2620    {
2621      Debug.debugException(e);
2622      buffer.append(signatureValue.toString());
2623    }
2624
2625    buffer.append("')");
2626  }
2627
2628
2629
2630  /**
2631   * Retrieves a list of the lines that comprise a PEM representation of this
2632   * X.509 certificate.
2633   *
2634   * @return  A list of the lines that comprise a PEM representation of this
2635   *          X.509 certificate.
2636   */
2637  @NotNull()
2638  public List<String> toPEM()
2639  {
2640    final ArrayList<String> lines = new ArrayList<>(10);
2641    lines.add("-----BEGIN CERTIFICATE-----");
2642
2643    final String certBase64 = Base64.encode(x509CertificateBytes);
2644    lines.addAll(StaticUtils.wrapLine(certBase64, 64));
2645
2646    lines.add("-----END CERTIFICATE-----");
2647
2648    return Collections.unmodifiableList(lines);
2649  }
2650
2651
2652
2653  /**
2654   * Retrieves a multi-line string containing a PEM representation of this X.509
2655   * certificate.
2656   *
2657   * @return  A multi-line string containing a PEM representation of this X.509
2658   *          certificate.
2659   */
2660  @NotNull()
2661  public String toPEMString()
2662  {
2663    final StringBuilder buffer = new StringBuilder();
2664    buffer.append("-----BEGIN CERTIFICATE-----");
2665    buffer.append(StaticUtils.EOL);
2666
2667    final String certBase64 = Base64.encode(x509CertificateBytes);
2668    for (final String line : StaticUtils.wrapLine(certBase64, 64))
2669    {
2670      buffer.append(line);
2671      buffer.append(StaticUtils.EOL);
2672    }
2673    buffer.append("-----END CERTIFICATE-----");
2674    buffer.append(StaticUtils.EOL);
2675
2676    return buffer.toString();
2677  }
2678}