001/*
002 * Copyright 2017-2025 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2017-2025 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-2025 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  static long decodeUTCTime(@NotNull final ASN1Element element)
895         throws ASN1Exception
896  {
897    // Unfortunately, UTC time values only include a 2-digit year, and there's
898    // no official way of identifying the century to which a given UTC time year
899    // belongs.  The LDAP SDK's handling of UTC time values uses a more
900    // future-proof sliding window approach, whereas the X.509 specification
901    // states that timestamp values should be interpreted as within the years
902    // 1950 through 2049.
903    //
904    // To ensure that we handle years correctly within this constraint, we will
905    // extract the first two digits from the string representation of the UTC
906    // time timestamp and convert it to an appropriate four-year timestamp based
907    // on the first (tens) digit.
908    final ASN1UTCTime utcTimeElement = ASN1UTCTime.decodeAsUTCTime(element);
909    final String lastTwoDigitsOfYear =
910         utcTimeElement.getStringRepresentation().substring(0, 2);
911
912    final String fullYearStr;
913    switch (lastTwoDigitsOfYear.charAt(0))
914    {
915      case '0':
916      case '1':
917      case '2':
918      case '3':
919      case '4':
920        fullYearStr = "20" + lastTwoDigitsOfYear;
921        break;
922      default:
923        fullYearStr = "19" + lastTwoDigitsOfYear;
924        break;
925    }
926
927
928    // Use a Calendar to force the timestamp to be between 1950 and 2049.
929    final long timeValue = utcTimeElement.getTime();
930
931    final GregorianCalendar calendar = new GregorianCalendar();
932    calendar.setTimeZone(StaticUtils.getUTCTimeZone());
933    calendar.setTimeInMillis(timeValue);
934    calendar.set(Calendar.YEAR, Integer.parseInt(fullYearStr));
935    return calendar.getTimeInMillis();
936  }
937
938
939
940  /**
941   * Encodes this X.509 certificate to an ASN.1 element.
942   *
943   * @return  The encoded X.509 certificate.
944   *
945   * @throws  CertException  If a problem is encountered while trying to encode
946   *                         the X.509 certificate.
947   */
948  @NotNull()
949  ASN1Element encode()
950       throws CertException
951  {
952    try
953    {
954      final ArrayList<ASN1Element> tbsCertificateElements = new ArrayList<>(10);
955
956      if (version != X509CertificateVersion.V1)
957      {
958        tbsCertificateElements.add(new ASN1Element(TYPE_EXPLICIT_VERSION,
959             new ASN1Integer(version.getIntValue()).encode()));
960      }
961
962      tbsCertificateElements.add(new ASN1BigInteger(serialNumber));
963
964      if (signatureAlgorithmParameters == null)
965      {
966        tbsCertificateElements.add(new ASN1Sequence(
967             new ASN1ObjectIdentifier(signatureAlgorithmOID)));
968      }
969      else
970      {
971        tbsCertificateElements.add(new ASN1Sequence(
972             new ASN1ObjectIdentifier(signatureAlgorithmOID),
973             signatureAlgorithmParameters));
974      }
975
976
977      tbsCertificateElements.add(encodeName(issuerDN));
978      tbsCertificateElements.add(encodeValiditySequence(notBefore, notAfter));
979      tbsCertificateElements.add(encodeName(subjectDN));
980
981      if (publicKeyAlgorithmParameters == null)
982      {
983        tbsCertificateElements.add(new ASN1Sequence(
984             new ASN1Sequence(
985                  new ASN1ObjectIdentifier(publicKeyAlgorithmOID)),
986             encodedPublicKey));
987      }
988      else
989      {
990        tbsCertificateElements.add(new ASN1Sequence(
991             new ASN1Sequence(
992                  new ASN1ObjectIdentifier(publicKeyAlgorithmOID),
993                  publicKeyAlgorithmParameters),
994             encodedPublicKey));
995      }
996
997      if (issuerUniqueID != null)
998      {
999        tbsCertificateElements.add(new ASN1BitString(
1000             TYPE_IMPLICIT_ISSUER_UNIQUE_ID, issuerUniqueID.getBits()));
1001      }
1002
1003      if (subjectUniqueID != null)
1004      {
1005        tbsCertificateElements.add(new ASN1BitString(
1006             TYPE_IMPLICIT_SUBJECT_UNIQUE_ID, subjectUniqueID.getBits()));
1007      }
1008
1009      if (! extensions.isEmpty())
1010      {
1011        final ArrayList<ASN1Element> extensionElements =
1012             new ArrayList<>(extensions.size());
1013        for (final X509CertificateExtension e : extensions)
1014        {
1015          extensionElements.add(e.encode());
1016        }
1017        tbsCertificateElements.add(new ASN1Element(TYPE_EXPLICIT_EXTENSIONS,
1018             new ASN1Sequence(extensionElements).encode()));
1019      }
1020
1021      final ArrayList<ASN1Element> certificateElements = new ArrayList<>(3);
1022      certificateElements.add(new ASN1Sequence(tbsCertificateElements));
1023
1024      if (signatureAlgorithmParameters == null)
1025      {
1026        certificateElements.add(new ASN1Sequence(
1027             new ASN1ObjectIdentifier(signatureAlgorithmOID)));
1028      }
1029      else
1030      {
1031        certificateElements.add(new ASN1Sequence(
1032             new ASN1ObjectIdentifier(signatureAlgorithmOID),
1033             signatureAlgorithmParameters));
1034      }
1035
1036      certificateElements.add(signatureValue);
1037
1038      return new ASN1Sequence(certificateElements);
1039    }
1040    catch (final Exception e)
1041    {
1042      Debug.debugException(e);
1043      throw new CertException(
1044           ERR_CERT_ENCODE_ERROR.get(toString(),
1045                StaticUtils.getExceptionMessage(e)),
1046           e);
1047    }
1048  }
1049
1050
1051
1052  /**
1053   * Encodes the provided DN as an X.509 name for inclusion in an encoded
1054   * certificate.
1055   *
1056   * @param  dn  The DN to encode.
1057   *
1058   * @return  The encoded X.509 name.
1059   *
1060   * @throws  CertException  If a problem is encountered while encoding the
1061   *                         provided DN as an X.509 name.
1062   */
1063  @NotNull()
1064  static ASN1Element encodeName(@NotNull final DN dn)
1065         throws CertException
1066  {
1067    final Schema schema;
1068    try
1069    {
1070      schema = Schema.getDefaultStandardSchema();
1071    }
1072    catch (final Exception e)
1073    {
1074      Debug.debugException(e);
1075      throw new CertException(
1076           ERR_CERT_ENCODE_NAME_CANNOT_GET_SCHEMA.get(String.valueOf(dn),
1077                StaticUtils.getExceptionMessage(e)),
1078           e);
1079    }
1080
1081    final RDN[] rdns = dn.getRDNs();
1082    final ArrayList<ASN1Element> rdnSequenceElements =
1083         new ArrayList<>(rdns.length);
1084    for (int i=rdns.length - 1; i >= 0; i--)
1085    {
1086      final RDN rdn =rdns[i];
1087      final String[] names = rdn.getAttributeNames();
1088      final String[] values = rdn.getAttributeValues();
1089
1090      final ArrayList<ASN1Element> rdnElements = new ArrayList<>(names.length);
1091      for (int j=0; j < names.length; j++)
1092      {
1093        final AttributeTypeDefinition at = schema.getAttributeType(names[j]);
1094        if (at == null)
1095        {
1096          throw new CertException(ERR_CERT_ENCODE_NAME_UNKNOWN_ATTR_TYPE.get(
1097               String.valueOf(dn), names[j]));
1098        }
1099
1100        try
1101        {
1102          rdnElements.add(new ASN1Sequence(
1103               new ASN1ObjectIdentifier(at.getOID()),
1104               new ASN1UTF8String(values[j])));
1105        }
1106        catch (final Exception e)
1107        {
1108          Debug.debugException(e);
1109          throw new CertException(
1110               ERR_CERT_ENCODE_NAME_ERROR.get(String.valueOf(dn),
1111                    StaticUtils.getExceptionMessage(e)),
1112               e);
1113        }
1114      }
1115
1116      rdnSequenceElements.add(new ASN1Set(rdnElements));
1117    }
1118
1119    return new ASN1Sequence(rdnSequenceElements);
1120  }
1121
1122
1123
1124  /**
1125   * Encodes the certificate validity sequence, using a UTC time encoding if
1126   * both notBefore and notAfter values fall within the range 1950-2049, and
1127   * using generalized time if either value falls outside that range.
1128   *
1129   * @param  notBefore  The notBefore value to include in the sequence.
1130   * @param  notAfter   The notAfter value to include in the sequence.
1131   *
1132   * @return  The encoded validity sequence.
1133   */
1134  @NotNull()
1135  static ASN1Sequence encodeValiditySequence(final long notBefore,
1136                                             final long notAfter)
1137  {
1138    final GregorianCalendar notBeforeCalendar = new GregorianCalendar();
1139    notBeforeCalendar.setTimeInMillis(notBefore);
1140    final int notBeforeYear = notBeforeCalendar.get(Calendar.YEAR);
1141
1142    final GregorianCalendar notAfterCalendar = new GregorianCalendar();
1143    notAfterCalendar.setTimeInMillis(notAfter);
1144    final int notAfterYear = notAfterCalendar.get(Calendar.YEAR);
1145
1146    if ((notBeforeYear >= 1950) && (notBeforeYear <= 2049) &&
1147        (notAfterYear >= 1950) && (notAfterYear <= 2049))
1148    {
1149      return new ASN1Sequence(
1150           new ASN1UTCTime(notBefore),
1151           new ASN1UTCTime(notAfter));
1152    }
1153    else
1154    {
1155      return new ASN1Sequence(
1156           new ASN1GeneralizedTime(notBefore),
1157           new ASN1GeneralizedTime(notAfter));
1158    }
1159  }
1160
1161
1162
1163  /**
1164   * Generates a self-signed X.509 certificate with the provided information.
1165   *
1166   * @param  signatureAlgorithm  The algorithm to use to generate the signature.
1167   *                             This must not be {@code null}.
1168   * @param  publicKeyAlgorithm  The algorithm to use to generate the key pair.
1169   *                             This must not be {@code null}.
1170   * @param  keySizeBits         The size of the key to generate, in bits.
1171   * @param  subjectDN           The subject DN for the certificate.  This must
1172   *                             not be {@code null}.
1173   * @param  notBefore           The validity start time for the certificate.
1174   * @param  notAfter            The validity end time for the certificate.
1175   * @param  extensions          The set of extensions to include in the
1176   *                             certificate.  This may be {@code null} or empty
1177   *                             if the certificate should not include any
1178   *                             custom extensions.  Note that the generated
1179   *                             certificate will automatically include a
1180   *                             {@link SubjectKeyIdentifierExtension}, so that
1181   *                             should not be provided.
1182   *
1183   * @return  An {@code ObjectPair} that contains both the self-signed
1184   *          certificate and its corresponding key pair.
1185   *
1186   * @throws  CertException  If a problem is encountered while creating the
1187   *                         certificate.
1188   */
1189  @NotNull()
1190  public static ObjectPair<X509Certificate,KeyPair>
1191                     generateSelfSignedCertificate(
1192              @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm,
1193              @NotNull final PublicKeyAlgorithmIdentifier publicKeyAlgorithm,
1194              final int keySizeBits,
1195              @NotNull final DN subjectDN,
1196              final long notBefore, final long notAfter,
1197              @Nullable final X509CertificateExtension... extensions)
1198         throws CertException
1199  {
1200    // Generate the key pair for the certificate.
1201    final KeyPairGenerator keyPairGenerator;
1202    try
1203    {
1204      keyPairGenerator =
1205           CryptoHelper.getKeyPairGenerator(publicKeyAlgorithm.getName());
1206    }
1207    catch (final Exception e)
1208    {
1209      Debug.debugException(e);
1210      throw new CertException(
1211           ERR_CERT_GEN_SELF_SIGNED_CANNOT_GET_KEY_GENERATOR.get(
1212                publicKeyAlgorithm.getName(),
1213                StaticUtils.getExceptionMessage(e)),
1214           e);
1215    }
1216
1217    try
1218    {
1219      keyPairGenerator.initialize(keySizeBits);
1220    }
1221    catch (final Exception e)
1222    {
1223      Debug.debugException(e);
1224      throw new CertException(
1225           ERR_CERT_GEN_SELF_SIGNED_INVALID_KEY_SIZE.get(keySizeBits,
1226                publicKeyAlgorithm.getName(),
1227                StaticUtils.getExceptionMessage(e)),
1228           e);
1229    }
1230
1231    final KeyPair keyPair;
1232    try
1233    {
1234      keyPair = keyPairGenerator.generateKeyPair();
1235    }
1236    catch (final Exception e)
1237    {
1238      Debug.debugException(e);
1239      throw new CertException(
1240           ERR_CERT_GEN_SELF_SIGNED_CANNOT_GENERATE_KEY_PAIR.get(
1241                keySizeBits, publicKeyAlgorithm.getName(),
1242                StaticUtils.getExceptionMessage(e)),
1243           e);
1244    }
1245
1246
1247    // Generate the certificate and return it along with the key pair.
1248    final X509Certificate certificate = generateSelfSignedCertificate(
1249         signatureAlgorithm, keyPair, subjectDN, notBefore, notAfter,
1250         extensions);
1251    return new ObjectPair<>(certificate, keyPair);
1252  }
1253
1254
1255
1256  /**
1257   * Generates a self-signed X.509 certificate with the provided information.
1258   *
1259   * @param  signatureAlgorithm  The algorithm to use to generate the signature.
1260   *                             This must not be {@code null}.
1261   * @param  keyPair             The key pair for the certificate.  This must
1262   *                             not be {@code null}.
1263   * @param  subjectDN           The subject DN for the certificate.  This must
1264   *                             not be {@code null}.
1265   * @param  notBefore           The validity start time for the certificate.
1266   * @param  notAfter            The validity end time for the certificate.
1267   * @param  extensions          The set of extensions to include in the
1268   *                             certificate.  This may be {@code null} or empty
1269   *                             if the certificate should not include any
1270   *                             custom extensions.  Note that the generated
1271   *                             certificate will automatically include a
1272   *                             {@link SubjectKeyIdentifierExtension}, so that
1273   *                             should not be provided.
1274   *
1275   * @return  An {@code ObjectPair} that contains both the self-signed
1276   *          certificate and its corresponding key pair.
1277   *
1278   * @throws  CertException  If a problem is encountered while creating the
1279   *                         certificate.
1280   */
1281  @NotNull()
1282  public static X509Certificate generateSelfSignedCertificate(
1283              @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm,
1284              @NotNull final KeyPair keyPair, @NotNull final DN subjectDN,
1285              final long notBefore, final long notAfter,
1286              @Nullable final X509CertificateExtension... extensions)
1287         throws CertException
1288  {
1289    // Extract the parameters and encoded public key from the generated key
1290    // pair.  And while we're at it, generate a subject key identifier from
1291    // the encoded public key.
1292    DecodedPublicKey decodedPublicKey = null;
1293    final ASN1BitString encodedPublicKey;
1294    final ASN1Element publicKeyAlgorithmParameters;
1295    final byte[] subjectKeyIdentifier;
1296    final OID publicKeyAlgorithmOID;
1297    try
1298    {
1299      final ASN1Element[] pkElements = ASN1Sequence.decodeAsSequence(
1300           keyPair.getPublic().getEncoded()).elements();
1301      final ASN1Element[] pkAlgIDElements = ASN1Sequence.decodeAsSequence(
1302           pkElements[0]).elements();
1303      publicKeyAlgorithmOID =
1304           pkAlgIDElements[0].decodeAsObjectIdentifier().getOID();
1305      if (pkAlgIDElements.length == 1)
1306      {
1307        publicKeyAlgorithmParameters = null;
1308      }
1309      else
1310      {
1311        publicKeyAlgorithmParameters = pkAlgIDElements[1];
1312      }
1313
1314      encodedPublicKey = pkElements[1].decodeAsBitString();
1315
1316      try
1317      {
1318        if (publicKeyAlgorithmOID.equals(
1319             PublicKeyAlgorithmIdentifier.RSA.getOID()))
1320        {
1321          decodedPublicKey = new RSAPublicKey(encodedPublicKey);
1322        }
1323        else if (publicKeyAlgorithmOID.equals(
1324             PublicKeyAlgorithmIdentifier.EC.getOID()))
1325        {
1326          decodedPublicKey = new EllipticCurvePublicKey(encodedPublicKey);
1327        }
1328      }
1329      catch (final Exception e)
1330      {
1331        Debug.debugException(e);
1332      }
1333
1334      final MessageDigest sha256 = CryptoHelper.getMessageDigest(
1335           SubjectKeyIdentifierExtension.
1336                SUBJECT_KEY_IDENTIFIER_DIGEST_ALGORITHM);
1337      subjectKeyIdentifier = sha256.digest(encodedPublicKey.getBytes());
1338    }
1339    catch (final Exception e)
1340    {
1341      Debug.debugException(e);
1342      throw new CertException(
1343           ERR_CERT_GEN_SELF_SIGNED_CANNOT_PARSE_KEY_PAIR.get(
1344                StaticUtils.getExceptionMessage(e)),
1345           e);
1346    }
1347
1348
1349    // Construct the set of all extensions for the certificate.
1350    final ArrayList<X509CertificateExtension> extensionList =
1351         new ArrayList<>(10);
1352    extensionList.add(new SubjectKeyIdentifierExtension(false,
1353         new ASN1OctetString(subjectKeyIdentifier)));
1354    if (extensions != null)
1355    {
1356      for (final X509CertificateExtension e : extensions)
1357      {
1358        if (! e.getOID().equals(SubjectKeyIdentifierExtension.
1359             SUBJECT_KEY_IDENTIFIER_OID))
1360        {
1361          extensionList.add(e);
1362        }
1363      }
1364    }
1365
1366    final X509CertificateExtension[] allExtensions =
1367         new X509CertificateExtension[extensionList.size()];
1368    extensionList.toArray(allExtensions);
1369
1370
1371    // Encode the tbsCertificate sequence for the certificate and use it to
1372    // generate the certificate's signature.
1373    final BigInteger serialNumber = generateSerialNumber();
1374    final ASN1BitString encodedSignature = generateSignature(signatureAlgorithm,
1375         keyPair.getPrivate(), serialNumber, subjectDN, notBefore, notAfter,
1376         subjectDN, publicKeyAlgorithmOID, publicKeyAlgorithmParameters,
1377         encodedPublicKey, allExtensions);
1378
1379
1380    // Construct and return the signed certificate and the private key.
1381    return new X509Certificate(X509CertificateVersion.V3, serialNumber,
1382         signatureAlgorithm.getOID(), null, encodedSignature, subjectDN,
1383         notBefore, notAfter, subjectDN, publicKeyAlgorithmOID,
1384         publicKeyAlgorithmParameters, encodedPublicKey, decodedPublicKey, null,
1385         null, allExtensions);
1386  }
1387
1388
1389
1390  /**
1391   * Generates an issuer-signed X.509 certificate with the provided information.
1392   *
1393   * @param  signatureAlgorithm
1394   *              The algorithm to use to generate the signature.  This must not
1395   *              be {@code null}.
1396   * @param  issuerCertificate
1397   *              The certificate for the issuer.  This must not be
1398   *              {@code null}.
1399   * @param  issuerPrivateKey
1400   *              The private key for the issuer.  This  must not be
1401   *              {@code null}.
1402   * @param  publicKeyAlgorithmOID
1403   *              The OID for the certificate's public key algorithm.  This must
1404   *              not be {@code null}.
1405   * @param  publicKeyAlgorithmParameters
1406   *              The encoded public key algorithm parameters for the
1407   *              certificate.  This may be {@code null} if there are no
1408   *              parameters.
1409   * @param  encodedPublicKey
1410   *              The encoded public key for the certificate.  This must not be
1411   *              {@code null}.
1412   * @param  decodedPublicKey
1413   *              The decoded public key for the certificate.  This may be
1414   *              {@code null} if it is not available.
1415   * @param  subjectDN
1416   *              The subject DN for the certificate.  This must not be
1417   *              {@code null}.
1418   * @param  notBefore
1419   *              The validity start time for the certificate.
1420   * @param  notAfter
1421   *              The validity end time for the certificate.
1422   * @param  extensions
1423   *              The set of extensions to include in the certificate.  This
1424   *              may be {@code null} or empty if the certificate should not
1425   *              include any custom extensions.  Note that the generated
1426   *              certificate will automatically include a
1427   *              {@link SubjectKeyIdentifierExtension}, so that should not be
1428   *              provided.  In addition, if the issuer certificate includes its
1429   *              own {@code SubjectKeyIdentifierExtension}, then its value will
1430   *              be used to generate an
1431   *              {@link AuthorityKeyIdentifierExtension}.
1432   *
1433   * @return  The issuer-signed certificate.
1434   *
1435   * @throws  CertException  If a problem is encountered while creating the
1436   *                         certificate.
1437   */
1438  @NotNull()
1439  public static X509Certificate generateIssuerSignedCertificate(
1440              @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm,
1441              @NotNull final X509Certificate issuerCertificate,
1442              @NotNull final PrivateKey issuerPrivateKey,
1443              @NotNull final OID publicKeyAlgorithmOID,
1444              @Nullable final ASN1Element publicKeyAlgorithmParameters,
1445              @NotNull final ASN1BitString encodedPublicKey,
1446              @Nullable final DecodedPublicKey decodedPublicKey,
1447              @NotNull final DN subjectDN,
1448              final long notBefore, final long notAfter,
1449              @NotNull final X509CertificateExtension... extensions)
1450         throws CertException
1451  {
1452    // Generate a subject key identifier from the encoded public key.
1453    final byte[] subjectKeyIdentifier;
1454    try
1455    {
1456      final MessageDigest sha256 = CryptoHelper.getMessageDigest(
1457           SubjectKeyIdentifierExtension.
1458                SUBJECT_KEY_IDENTIFIER_DIGEST_ALGORITHM);
1459      subjectKeyIdentifier = sha256.digest(encodedPublicKey.getBytes());
1460    }
1461    catch (final Exception e)
1462    {
1463      Debug.debugException(e);
1464      throw new CertException(
1465           ERR_CERT_GEN_ISSUER_SIGNED_CANNOT_GENERATE_KEY_ID.get(
1466                StaticUtils.getExceptionMessage(e)),
1467           e);
1468    }
1469
1470
1471    // If the issuer certificate contains a subject key identifier, then
1472    // extract it to use as the authority key identifier.
1473    ASN1OctetString authorityKeyIdentifier = null;
1474    for (final X509CertificateExtension e : issuerCertificate.extensions)
1475    {
1476      if (e instanceof SubjectKeyIdentifierExtension)
1477      {
1478        authorityKeyIdentifier =
1479             ((SubjectKeyIdentifierExtension) e).getKeyIdentifier();
1480      }
1481    }
1482
1483
1484    // Construct the set of all extensions for the certificate.
1485    final ArrayList<X509CertificateExtension> extensionList =
1486         new ArrayList<>(10);
1487    extensionList.add(new SubjectKeyIdentifierExtension(false,
1488         new ASN1OctetString(subjectKeyIdentifier)));
1489
1490    if (authorityKeyIdentifier == null)
1491    {
1492      extensionList.add(new AuthorityKeyIdentifierExtension(false, null,
1493           new GeneralNamesBuilder().addDirectoryName(
1494                issuerCertificate.subjectDN).build(),
1495           issuerCertificate.serialNumber));
1496    }
1497    else
1498    {
1499      extensionList.add(new AuthorityKeyIdentifierExtension(false,
1500           authorityKeyIdentifier, null, null));
1501    }
1502
1503    if (extensions != null)
1504    {
1505      for (final X509CertificateExtension e : extensions)
1506      {
1507        if (e.getOID().equals(
1508             SubjectKeyIdentifierExtension.SUBJECT_KEY_IDENTIFIER_OID) ||
1509            e.getOID().equals(
1510                 AuthorityKeyIdentifierExtension.AUTHORITY_KEY_IDENTIFIER_OID))
1511        {
1512          continue;
1513        }
1514
1515        extensionList.add(e);
1516      }
1517    }
1518
1519    final X509CertificateExtension[] allExtensions =
1520         new X509CertificateExtension[extensionList.size()];
1521    extensionList.toArray(allExtensions);
1522
1523
1524    // Encode the tbsCertificate sequence for the certificate and use it to
1525    // generate the certificate's signature.
1526    final BigInteger serialNumber = generateSerialNumber();
1527    final ASN1BitString encodedSignature = generateSignature(signatureAlgorithm,
1528         issuerPrivateKey, serialNumber, issuerCertificate.subjectDN, notBefore,
1529         notAfter, subjectDN, publicKeyAlgorithmOID,
1530         publicKeyAlgorithmParameters, encodedPublicKey, allExtensions);
1531
1532
1533    // Construct and return the signed certificate.
1534    return new X509Certificate(X509CertificateVersion.V3, serialNumber,
1535         signatureAlgorithm.getOID(), null, encodedSignature,
1536         issuerCertificate.subjectDN, notBefore, notAfter, subjectDN,
1537         publicKeyAlgorithmOID, publicKeyAlgorithmParameters, encodedPublicKey,
1538         decodedPublicKey, null, null, allExtensions);
1539  }
1540
1541
1542
1543  /**
1544   * Generates a serial number for the certificate.
1545   *
1546   * @return  The generated serial number.
1547   */
1548  @NotNull()
1549  private static BigInteger generateSerialNumber()
1550  {
1551    final UUID uuid = CryptoHelper.getRandomUUID();
1552    final long msb = uuid.getMostSignificantBits() & 0x7FFF_FFFF_FFFF_FFFFL;
1553    final long lsb = uuid.getLeastSignificantBits() & 0x7FFF_FFFF_FFFF_FFFFL;
1554    return BigInteger.valueOf(msb).shiftLeft(64).add(BigInteger.valueOf(lsb));
1555  }
1556
1557
1558
1559  /**
1560   * Generates a signature for the certificate with the provided information.
1561   *
1562   * @param  signatureAlgorithm            The signature algorithm to use to
1563   *                                       generate the signature.  This must
1564   *                                       not be {@code null}.
1565   * @param  privateKey                    The private key to use to sign the
1566   *                                       certificate.  This must not be
1567   *                                       {@code null}.
1568   * @param  serialNumber                  The serial number for the
1569   *                                       certificate.  This must not be
1570   *                                       {@code null}.
1571   * @param  issuerDN                      The issuer DN for the certificate.
1572   *                                       This must not be {@code null}.
1573   * @param  notBefore                     The validity start time for the
1574   *                                       certificate.
1575   * @param  notAfter                      The validity end time for the
1576   *                                       certificate.
1577   * @param  subjectDN                     The subject DN for the certificate.
1578   *                                       This must not be {@code null}.
1579   * @param  publicKeyAlgorithmOID         The OID for the public key algorithm.
1580   *                                       This must not be {@code null}.
1581   * @param  publicKeyAlgorithmParameters  The encoded public key algorithm
1582   *                                       parameters.  This may be
1583   *                                       {@code null} if no parameters are
1584   *                                       needed.
1585   * @param  encodedPublicKey              The encoded representation of the
1586   *                                       public key.  This must not be
1587   *                                       {@code null}.
1588   * @param  extensions                    The set of extensions to include in
1589   *                                       the certificate.  This must not be
1590   *                                       {@code null} but may be empty.
1591   *
1592   * @return  An encoded representation of the generated signature.
1593   *
1594   * @throws  CertException  If a problem is encountered while generating the
1595   *                         certificate.
1596   */
1597  @NotNull()
1598  private static ASN1BitString generateSignature(
1599               @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm,
1600               @NotNull final PrivateKey privateKey,
1601               @NotNull final BigInteger serialNumber,
1602               @NotNull final DN issuerDN, final long notBefore,
1603               final long notAfter, @NotNull final DN subjectDN,
1604               @NotNull final OID publicKeyAlgorithmOID,
1605               @Nullable final ASN1Element publicKeyAlgorithmParameters,
1606               @NotNull final ASN1BitString encodedPublicKey,
1607               @NotNull final X509CertificateExtension... extensions)
1608          throws CertException
1609  {
1610    // Get and initialize the signature generator.
1611    final Signature signature;
1612    try
1613    {
1614      signature = CryptoHelper.getSignature(signatureAlgorithm.getJavaName());
1615    }
1616    catch (final Exception e)
1617    {
1618      Debug.debugException(e);
1619      throw new CertException(
1620           ERR_CERT_GEN_SIGNATURE_CANNOT_GET_SIGNATURE_GENERATOR.get(
1621                signatureAlgorithm.getJavaName(),
1622                StaticUtils.getExceptionMessage(e)),
1623           e);
1624    }
1625
1626    try
1627    {
1628      signature.initSign(privateKey);
1629    }
1630    catch (final Exception e)
1631    {
1632      Debug.debugException(e);
1633      throw new CertException(
1634           ERR_CERT_GEN_SIGNATURE_CANNOT_INIT_SIGNATURE_GENERATOR.get(
1635                signatureAlgorithm.getJavaName(),
1636                StaticUtils.getExceptionMessage(e)),
1637           e);
1638    }
1639
1640
1641    // Construct the tbsCertificate element of the certificate and compute its
1642    // signature.
1643    try
1644    {
1645      final ArrayList<ASN1Element> tbsCertificateElements = new ArrayList<>(8);
1646      tbsCertificateElements.add(new ASN1Element(TYPE_EXPLICIT_VERSION,
1647           new ASN1Integer(X509CertificateVersion.V3.getIntValue()).encode()));
1648      tbsCertificateElements.add(new ASN1BigInteger(serialNumber));
1649      tbsCertificateElements.add(new ASN1Sequence(
1650           new ASN1ObjectIdentifier(signatureAlgorithm.getOID())));
1651      tbsCertificateElements.add(encodeName(issuerDN));
1652      tbsCertificateElements.add(encodeValiditySequence(notBefore, notAfter));
1653      tbsCertificateElements.add(encodeName(subjectDN));
1654
1655      if (publicKeyAlgorithmParameters == null)
1656      {
1657        tbsCertificateElements.add(new ASN1Sequence(
1658             new ASN1Sequence(
1659                  new ASN1ObjectIdentifier(publicKeyAlgorithmOID)),
1660             encodedPublicKey));
1661      }
1662      else
1663      {
1664        tbsCertificateElements.add(new ASN1Sequence(
1665             new ASN1Sequence(
1666                  new ASN1ObjectIdentifier(publicKeyAlgorithmOID),
1667                  publicKeyAlgorithmParameters),
1668             encodedPublicKey));
1669      }
1670
1671      final ArrayList<ASN1Element> extensionElements =
1672           new ArrayList<>(extensions.length);
1673      for (final X509CertificateExtension e : extensions)
1674      {
1675        extensionElements.add(e.encode());
1676      }
1677      tbsCertificateElements.add(new ASN1Element(TYPE_EXPLICIT_EXTENSIONS,
1678           new ASN1Sequence(extensionElements).encode()));
1679
1680      final byte[] tbsCertificateBytes =
1681           new ASN1Sequence(tbsCertificateElements).encode();
1682      signature.update(tbsCertificateBytes);
1683      final byte[] signatureBytes = signature.sign();
1684
1685      return new ASN1BitString(ASN1BitString.getBitsForBytes(signatureBytes));
1686    }
1687    catch (final Exception e)
1688    {
1689      Debug.debugException(e);
1690      throw new CertException(
1691           ERR_CERT_GEN_SIGNATURE_CANNOT_COMPUTE.get(
1692                signatureAlgorithm.getJavaName(),
1693                StaticUtils.getExceptionMessage(e)),
1694           e);
1695    }
1696  }
1697
1698
1699
1700  /**
1701   * Retrieves the bytes that comprise the encoded representation of this X.509
1702   * certificate.
1703   *
1704   * @return  The bytes that comprise the encoded representation of this X.509
1705   *          certificate.
1706   */
1707  @NotNull()
1708  public byte[] getX509CertificateBytes()
1709  {
1710    return x509CertificateBytes;
1711  }
1712
1713
1714
1715  /**
1716   * Retrieves the certificate version.
1717   *
1718   * @return  The certificate version.
1719   */
1720  @NotNull()
1721  public X509CertificateVersion getVersion()
1722  {
1723    return version;
1724  }
1725
1726
1727
1728  /**
1729   * Retrieves the certificate serial number.
1730   *
1731   * @return  The certificate serial number.
1732   */
1733  @NotNull()
1734  public BigInteger getSerialNumber()
1735  {
1736    return serialNumber;
1737  }
1738
1739
1740
1741  /**
1742   * Retrieves the certificate signature algorithm OID.
1743   *
1744   * @return  The certificate signature algorithm OID.
1745   */
1746  @NotNull()
1747  public OID getSignatureAlgorithmOID()
1748  {
1749    return signatureAlgorithmOID;
1750  }
1751
1752
1753
1754  /**
1755   * Retrieves the certificate signature algorithm name, if available.
1756   *
1757   * @return  The certificate signature algorithm name, or {@code null} if the
1758   *          signature algorithm OID does not correspond to any known algorithm
1759   *          name.
1760   */
1761  @Nullable()
1762  public String getSignatureAlgorithmName()
1763  {
1764    return signatureAlgorithmName;
1765  }
1766
1767
1768
1769  /**
1770   * Retrieves the signature algorithm name if it is available, or the string
1771   * representation of the signature algorithm OID if not.
1772   *
1773   * @return  The signature algorithm name or OID.
1774   */
1775  @NotNull()
1776  public String getSignatureAlgorithmNameOrOID()
1777  {
1778    if (signatureAlgorithmName != null)
1779    {
1780      return signatureAlgorithmName;
1781    }
1782    else
1783    {
1784      return signatureAlgorithmOID.toString();
1785    }
1786  }
1787
1788
1789
1790  /**
1791   * Retrieves the encoded signature algorithm parameters, if present.
1792   *
1793   * @return  The encoded signature algorithm parameters, or {@code null} if
1794   *          there are no signature algorithm parameters.
1795   */
1796  @Nullable()
1797  public ASN1Element getSignatureAlgorithmParameters()
1798  {
1799    return signatureAlgorithmParameters;
1800  }
1801
1802
1803
1804  /**
1805   * Retrieves the certificate issuer DN.
1806   *
1807   * @return  The certificate issuer DN.
1808   */
1809  @NotNull()
1810  public DN getIssuerDN()
1811  {
1812    return issuerDN;
1813  }
1814
1815
1816
1817  /**
1818   * Retrieves the certificate validity start time as the number of milliseconds
1819   * since the epoch (January 1, 1970 UTC).
1820   *
1821   * @return  The certificate validity start time as the number of milliseconds
1822   *          since the epoch.
1823   */
1824  public long getNotBeforeTime()
1825  {
1826    return notBefore;
1827  }
1828
1829
1830
1831  /**
1832   * Retrieves the certificate validity start time as a {@code Date}.
1833   *
1834   * @return  The certificate validity start time as a {@code Date}.
1835   */
1836  @NotNull()
1837  public Date getNotBeforeDate()
1838  {
1839    return new Date(notBefore);
1840  }
1841
1842
1843
1844  /**
1845   * Retrieves the certificate validity end time as the number of milliseconds
1846   * since the epoch (January 1, 1970 UTC).
1847   *
1848   * @return  The certificate validity end time as the number of milliseconds
1849   *          since the epoch.
1850   */
1851  public long getNotAfterTime()
1852  {
1853    return notAfter;
1854  }
1855
1856
1857
1858  /**
1859   * Retrieves the certificate validity end time as a {@code Date}.
1860   *
1861   * @return  The certificate validity end time as a {@code Date}.
1862   */
1863  @NotNull()
1864  public Date getNotAfterDate()
1865  {
1866    return new Date(notAfter);
1867  }
1868
1869
1870
1871  /**
1872   * Indicates whether the current time is within the certificate's validity
1873   * window.
1874   *
1875   * @return  {@code true} if the current time is within the certificate's
1876   *          validity window, or {@code false} if not.
1877   */
1878  public boolean isWithinValidityWindow()
1879  {
1880    return isWithinValidityWindow(System.currentTimeMillis());
1881  }
1882
1883
1884
1885  /**
1886   * Indicates whether the provided {@code Date} represents a time within the
1887   * certificate's validity window.
1888   *
1889   * @param  date  The {@code Date} for which to make the determination.  It
1890   *               must not be {@code null}.
1891   *
1892   * @return  {@code true} if the provided {@code Date} is within the
1893   *          certificate's validity window, or {@code false} if not.
1894   */
1895  public boolean isWithinValidityWindow(@NotNull final Date date)
1896  {
1897    return isWithinValidityWindow(date.getTime());
1898  }
1899
1900
1901
1902  /**
1903   * Indicates whether the specified time is within the certificate's validity
1904   * window.
1905   *
1906   * @param  time  The time to for which to make the determination.
1907   *
1908   * @return  {@code true} if the specified time is within the certificate's
1909   *          validity window, or {@code false} if not.
1910   */
1911  public boolean isWithinValidityWindow(final long time)
1912  {
1913    return ((time >= notBefore) && (time <= notAfter));
1914  }
1915
1916
1917
1918  /**
1919   * Retrieves the certificate subject DN.
1920   *
1921   * @return  The certificate subject DN.
1922   */
1923  @NotNull()
1924  public DN getSubjectDN()
1925  {
1926    return subjectDN;
1927  }
1928
1929
1930
1931  /**
1932   * Retrieves the certificate public key algorithm OID.
1933   *
1934   * @return  The certificate public key algorithm OID.
1935   */
1936  @NotNull()
1937  public OID getPublicKeyAlgorithmOID()
1938  {
1939    return publicKeyAlgorithmOID;
1940  }
1941
1942
1943
1944  /**
1945   * Retrieves the certificate public key algorithm name, if available.
1946   *
1947   * @return  The certificate public key algorithm name, or {@code null} if the
1948   *          public key algorithm OID does not correspond to any known
1949   *          algorithm name.
1950   */
1951  @Nullable()
1952  public String getPublicKeyAlgorithmName()
1953  {
1954    return publicKeyAlgorithmName;
1955  }
1956
1957
1958
1959  /**
1960   * Retrieves the public key algorithm name if it is available, or the string
1961   * representation of the public key algorithm OID if not.
1962   *
1963   * @return  The signature algorithm name or OID.
1964   */
1965  @NotNull()
1966  public String getPublicKeyAlgorithmNameOrOID()
1967  {
1968    if (publicKeyAlgorithmName != null)
1969    {
1970      return publicKeyAlgorithmName;
1971    }
1972    else
1973    {
1974      return publicKeyAlgorithmOID.toString();
1975    }
1976  }
1977
1978
1979
1980  /**
1981   * Retrieves the encoded public key algorithm parameters, if present.
1982   *
1983   * @return  The encoded public key algorithm parameters, or {@code null} if
1984   *          there are no public key algorithm parameters.
1985   */
1986  @Nullable()
1987  public ASN1Element getPublicKeyAlgorithmParameters()
1988  {
1989    return publicKeyAlgorithmParameters;
1990  }
1991
1992
1993
1994  /**
1995   * Retrieves the encoded public key as a bit string.
1996   *
1997   * @return  The encoded public key as a bit string.
1998   */
1999  @NotNull()
2000  public ASN1BitString getEncodedPublicKey()
2001  {
2002    return encodedPublicKey;
2003  }
2004
2005
2006
2007  /**
2008   * Retrieves a decoded representation of the public key, if available.
2009   *
2010   * @return  A decoded representation of the public key, or {@code null} if the
2011   *          public key could not be decoded.
2012   */
2013  @Nullable()
2014  public DecodedPublicKey getDecodedPublicKey()
2015  {
2016    return decodedPublicKey;
2017  }
2018
2019
2020
2021  /**
2022   * Retrieves the issuer unique identifier for the certificate, if any.
2023   *
2024   * @return  The issuer unique identifier for the certificate, or {@code null}
2025   *          if there is none.
2026   */
2027  @Nullable()
2028  public ASN1BitString getIssuerUniqueID()
2029  {
2030    return issuerUniqueID;
2031  }
2032
2033
2034
2035  /**
2036   * Retrieves the subject unique identifier for the certificate, if any.
2037   *
2038   * @return  The subject unique identifier for the certificate, or {@code null}
2039   *          if there is none.
2040   */
2041  @Nullable()
2042  public ASN1BitString getSubjectUniqueID()
2043  {
2044    return subjectUniqueID;
2045  }
2046
2047
2048
2049  /**
2050   * Retrieves the list of certificate extensions.
2051   *
2052   * @return  The list of certificate extensions.
2053   */
2054  @NotNull()
2055  public List<X509CertificateExtension> getExtensions()
2056  {
2057    return extensions;
2058  }
2059
2060
2061
2062  /**
2063   * Retrieves the signature value for the certificate.
2064   *
2065   * @return  The signature value for the certificate.
2066   */
2067  @NotNull()
2068  public ASN1BitString getSignatureValue()
2069  {
2070    return signatureValue;
2071  }
2072
2073
2074
2075  /**
2076   * Verifies the signature for this certificate.
2077   *
2078   * @param  issuerCertificate  The issuer certificate for this certificate.  It
2079   *                            may be {@code null} if this is a self-signed
2080   *                            certificate.  It must not be {@code null} if it
2081   *                            is not a self-signed certificate.
2082   *
2083   * @throws  CertException  If the certificate signature could not be verified.
2084   */
2085  public void verifySignature(@Nullable final X509Certificate issuerCertificate)
2086         throws CertException
2087  {
2088    // Get the issuer certificate.  If the certificate is self-signed, then it
2089    // might be the current certificate.
2090    final X509Certificate issuer;
2091    if (issuerCertificate == null)
2092    {
2093      if (isSelfSigned())
2094      {
2095        issuer = this;
2096      }
2097      else
2098      {
2099        throw new CertException(
2100             ERR_CERT_VERIFY_SIGNATURE_ISSUER_CERT_NOT_PROVIDED.get());
2101      }
2102    }
2103    else
2104    {
2105      issuer = issuerCertificate;
2106    }
2107
2108
2109    // Get the public key from the issuer certificate.
2110    final PublicKey publicKey;
2111    try
2112    {
2113      publicKey = issuer.toCertificate().getPublicKey();
2114    }
2115    catch (final Exception e)
2116    {
2117      Debug.debugException(e);
2118      throw new CertException(
2119           ERR_CERT_VERIFY_SIGNATURE_CANNOT_GET_PUBLIC_KEY.get(
2120                StaticUtils.getExceptionMessage(e)),
2121           e);
2122    }
2123
2124
2125    // Get and initialize the signature generator.
2126    final Signature signature;
2127    final SignatureAlgorithmIdentifier signatureAlgorithm;
2128    try
2129    {
2130      signatureAlgorithm =
2131           SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID);
2132      signature = CryptoHelper.getSignature(signatureAlgorithm.getJavaName());
2133    }
2134    catch (final Exception e)
2135    {
2136      Debug.debugException(e);
2137      throw new CertException(
2138           ERR_CERT_VERIFY_SIGNATURE_CANNOT_GET_SIGNATURE_VERIFIER.get(
2139                getSignatureAlgorithmNameOrOID(),
2140                StaticUtils.getExceptionMessage(e)),
2141           e);
2142    }
2143
2144    try
2145    {
2146      signature.initVerify(publicKey);
2147    }
2148    catch (final Exception e)
2149    {
2150      Debug.debugException(e);
2151      throw new CertException(
2152           ERR_CERT_VERIFY_SIGNATURE_CANNOT_INIT_SIGNATURE_VERIFIER.get(
2153                signatureAlgorithm.getJavaName(),
2154                StaticUtils.getExceptionMessage(e)),
2155           e);
2156    }
2157
2158
2159    // Construct the tbsCertificate element of the certificate and compute its
2160    // signature.
2161    try
2162    {
2163      final ASN1Element[] x509CertificateElements =
2164           ASN1Sequence.decodeAsSequence(x509CertificateBytes).elements();
2165      final byte[] tbsCertificateBytes = x509CertificateElements[0].encode();
2166      signature.update(tbsCertificateBytes);
2167    }
2168    catch (final Exception e)
2169    {
2170      Debug.debugException(e);
2171      throw new CertException(
2172           ERR_CERT_GEN_SIGNATURE_CANNOT_COMPUTE.get(
2173                signatureAlgorithm.getJavaName(),
2174                StaticUtils.getExceptionMessage(e)),
2175           e);
2176    }
2177
2178
2179    try
2180    {
2181      if (! signature.verify(signatureValue.getBytes()))
2182      {
2183        throw new CertException(
2184             ERR_CERT_VERIFY_SIGNATURE_NOT_VALID.get(subjectDN));
2185      }
2186    }
2187    catch (final CertException ce)
2188    {
2189      Debug.debugException(ce);
2190      throw ce;
2191    }
2192    catch (final Exception e)
2193    {
2194      Debug.debugException(e);
2195      throw new CertException(
2196           ERR_CERT_VERIFY_SIGNATURE_ERROR.get(subjectDN,
2197                StaticUtils.getExceptionMessage(e)),
2198           e);
2199    }
2200  }
2201
2202
2203
2204  /**
2205   * Retrieves the bytes that comprise a SHA-1 fingerprint of this certificate.
2206   *
2207   * @return  The bytes that comprise a SHA-1 fingerprint of this certificate.
2208   *
2209   * @throws  CertException  If a problem is encountered while computing the
2210   *                         fingerprint.
2211   */
2212  @NotNull()
2213  public byte[] getSHA1Fingerprint()
2214         throws CertException
2215  {
2216    return getFingerprint("SHA-1");
2217  }
2218
2219
2220
2221  /**
2222   * Retrieves the bytes that comprise a 256-bit SHA-2 fingerprint of this
2223   * certificate.
2224   *
2225   * @return  The bytes that comprise a 256-bit SHA-2 fingerprint of this
2226   *          certificate.
2227   *
2228   * @throws  CertException  If a problem is encountered while computing the
2229   *                         fingerprint.
2230   */
2231  @NotNull()
2232  public byte[] getSHA256Fingerprint()
2233         throws CertException
2234  {
2235    return getFingerprint("SHA-256");
2236  }
2237
2238
2239
2240  /**
2241   * Retrieves the bytes that comprise a fingerprint of this certificate.
2242   *
2243   * @param  digestAlgorithm  The digest algorithm to use to generate the
2244   *                          fingerprint.
2245   *
2246   * @return  The bytes that comprise a fingerprint of this certificate.
2247   *
2248   * @throws  CertException  If a problem is encountered while computing the
2249   *                         fingerprint.
2250   */
2251  @NotNull()
2252  private byte[] getFingerprint(@NotNull final String digestAlgorithm)
2253          throws CertException
2254  {
2255    try
2256    {
2257      final MessageDigest digest =
2258           CryptoHelper.getMessageDigest(digestAlgorithm);
2259      return digest.digest(x509CertificateBytes);
2260    }
2261    catch (final Exception e)
2262    {
2263      // This should never happen.
2264      Debug.debugException(e);
2265      throw new CertException(
2266           ERR_CERT_CANNOT_COMPUTE_FINGERPRINT.get(digestAlgorithm,
2267                StaticUtils.getExceptionMessage(e)),
2268           e);
2269    }
2270  }
2271
2272
2273
2274  /**
2275   * Indicates whether this certificate is self-signed.  The following criteria
2276   * will be used to make the determination:
2277   * <OL>
2278   *   <LI>
2279   *     If the certificate has both subject key identifier and authority
2280   *     key identifier extensions, then it will be considered self-signed if
2281   *     and only if the subject key identifier matches the authority key
2282   *     identifier.
2283   *   </LI>
2284   *   <LI>
2285   *     If the certificate does not have both a subject key identifier and an
2286   *     authority key identifier, then it will be considered self-signed if and
2287   *     only if its subject DN matches its issuer DN.
2288   *   </LI>
2289   * </OL>
2290   *
2291   * @return  {@code true} if this certificate is self-signed, or {@code false}
2292   *          if it is not.
2293   */
2294  public boolean isSelfSigned()
2295  {
2296    AuthorityKeyIdentifierExtension akie = null;
2297    SubjectKeyIdentifierExtension skie = null;
2298    for (final X509CertificateExtension e : extensions)
2299    {
2300      if (e instanceof AuthorityKeyIdentifierExtension)
2301      {
2302        akie = (AuthorityKeyIdentifierExtension) e;
2303      }
2304      else if (e instanceof SubjectKeyIdentifierExtension)
2305      {
2306        skie = (SubjectKeyIdentifierExtension) e;
2307      }
2308    }
2309
2310    if ((akie != null) && (skie != null))
2311    {
2312      return ((akie.getKeyIdentifier() != null) &&
2313           Arrays.equals(akie.getKeyIdentifier().getValue(),
2314                skie.getKeyIdentifier().getValue()));
2315    }
2316    else
2317    {
2318      return subjectDN.equals(issuerDN);
2319    }
2320  }
2321
2322
2323
2324  /**
2325   * Indicates whether this certificate is the issuer for the provided
2326   * certificate.  In order for this to be true, the following conditions must
2327   * be met:
2328   * <OL>
2329   *   <LI>
2330   *     The subject DN of this certificate must match the issuer DN for the
2331   *     provided certificate.
2332   *   </LI>
2333   *   <LI>
2334   *     If the provided certificate has an authority key identifier extension,
2335   *     then this certificate must have a subject key identifier extension with
2336   *     a matching identifier value.
2337   *   </LI>
2338   * </OL>
2339   *
2340   * @param  c  The certificate for which to make the determination.  This must
2341   *            not be {@code null}.
2342   *
2343   * @return  {@code true} if this certificate is considered the issuer for the
2344   *          provided certificate, or {@code } false if not.
2345   */
2346  public boolean isIssuerFor(@NotNull final X509Certificate c)
2347  {
2348    return isIssuerFor(c, null);
2349  }
2350
2351
2352
2353  /**
2354   * Indicates whether this certificate is the issuer for the provided
2355   * certificate.  In order for this to be true, the following conditions must
2356   * be met:
2357   * <OL>
2358   *   <LI>
2359   *     The subject DN of this certificate must match the issuer DN for the
2360   *     provided certificate.
2361   *   </LI>
2362   *   <LI>
2363   *     If the provided certificate has an authority key identifier extension,
2364   *     then this certificate must have a subject key identifier extension with
2365   *     a matching identifier value.
2366   *   </LI>
2367   * </OL>
2368   *
2369   * @param  c               The certificate for which to make the
2370   *                         determination.  This must not be {@code null}.
2371   * @param  nonMatchReason  An optional buffer that may be updated with the
2372   *                         reason that this certificate is not considered the
2373   *                         issuer for the provided certificate.  This may be
2374   *                         {@code null} if the caller does not require a
2375   *                         reason.
2376   *
2377   * @return  {@code true} if this certificate is considered the issuer for the
2378   *          provided certificate, or {@code } false if not.
2379   */
2380  public boolean isIssuerFor(@NotNull final X509Certificate c,
2381                             @Nullable final StringBuilder nonMatchReason)
2382  {
2383    if (! c.issuerDN.equals(subjectDN))
2384    {
2385      if (nonMatchReason != null)
2386      {
2387        nonMatchReason.append(INFO_CERT_IS_ISSUER_FOR_DN_MISMATCH.get(
2388             subjectDN, c.subjectDN, issuerDN));
2389      }
2390
2391      return false;
2392    }
2393
2394
2395    byte[] authorityKeyIdentifier = null;
2396    for (final X509CertificateExtension extension : c.extensions)
2397    {
2398      if (extension instanceof AuthorityKeyIdentifierExtension)
2399      {
2400        final AuthorityKeyIdentifierExtension akie =
2401             (AuthorityKeyIdentifierExtension) extension;
2402        if (akie.getKeyIdentifier() != null)
2403        {
2404          authorityKeyIdentifier = akie.getKeyIdentifier().getValue();
2405          break;
2406        }
2407      }
2408    }
2409
2410    if (authorityKeyIdentifier != null)
2411    {
2412      boolean matchFound = false;
2413      for (final X509CertificateExtension extension : extensions)
2414      {
2415        if (extension instanceof SubjectKeyIdentifierExtension)
2416        {
2417          final SubjectKeyIdentifierExtension skie =
2418               (SubjectKeyIdentifierExtension) extension;
2419          matchFound = Arrays.equals(authorityKeyIdentifier,
2420               skie.getKeyIdentifier().getValue());
2421          break;
2422        }
2423      }
2424
2425      if (! matchFound)
2426      {
2427        if (nonMatchReason != null)
2428        {
2429          nonMatchReason.append(INFO_CERT_IS_ISSUER_FOR_KEY_ID_MISMATCH.get(
2430               subjectDN, c.subjectDN));
2431        }
2432
2433        return false;
2434      }
2435    }
2436
2437
2438    return true;
2439  }
2440
2441
2442
2443  /**
2444   * Converts this X.509 certificate object to a Java {@code Certificate}
2445   * object.
2446   *
2447   * @return  The Java {@code Certificate} object that corresponds to this
2448   *          X.509 certificate.
2449   *
2450   * @throws  CertificateException  If a problem is encountered while performing
2451   *                                the conversion.
2452   */
2453  @NotNull()
2454  public Certificate toCertificate()
2455         throws CertificateException
2456  {
2457    return CryptoHelper.getCertificateFactory("X.509").generateCertificate(
2458         new ByteArrayInputStream(x509CertificateBytes));
2459  }
2460
2461
2462
2463  /**
2464   * Retrieves a hash code for this certificate.
2465   *
2466   * @return  A hash code for this certificate.
2467   */
2468  @Override()
2469  public int hashCode()
2470  {
2471    return Arrays.hashCode(x509CertificateBytes);
2472  }
2473
2474
2475
2476  /**
2477   * Indicates whether the provided object is considered equal to this X.509
2478   * certificate.
2479   *
2480   * @param  o  The object for which to make the determination.
2481   *
2482   * @return  {@code true} if the provided object is considered equal to this
2483   *          X.509 certificate, or {@code false} if not.
2484   */
2485  @Override()
2486  public boolean equals(@Nullable final Object o)
2487  {
2488    if (o == null)
2489    {
2490      return false;
2491    }
2492
2493    if (o == this)
2494    {
2495      return true;
2496    }
2497
2498    if (! (o instanceof X509Certificate))
2499    {
2500      return false;
2501    }
2502
2503    final X509Certificate c = (X509Certificate) o;
2504    return Arrays.equals(x509CertificateBytes, c.x509CertificateBytes);
2505  }
2506
2507
2508
2509  /**
2510   * Retrieves a string representation of the decoded X.509 certificate.
2511   *
2512   * @return  A string representation of the decoded X.509 certificate.
2513   */
2514  @Override()
2515  @NotNull()
2516  public String toString()
2517  {
2518    final StringBuilder buffer = new StringBuilder();
2519    toString(buffer);
2520    return buffer.toString();
2521  }
2522
2523
2524
2525  /**
2526   * Appends a string representation of the decoded X.509 certificate to the
2527   * provided buffer.
2528   *
2529   * @param  buffer  The buffer to which the information should be appended.
2530   */
2531  public void toString(@NotNull final StringBuilder buffer)
2532  {
2533    buffer.append("X509Certificate(version='");
2534    buffer.append(version.getName());
2535    buffer.append("', serialNumber='");
2536    StaticUtils.toHex(serialNumber.toByteArray(), ":", buffer);
2537    buffer.append("', signatureAlgorithmOID='");
2538    buffer.append(signatureAlgorithmOID.toString());
2539    buffer.append('\'');
2540
2541    if (signatureAlgorithmName != null)
2542    {
2543      buffer.append(", signatureAlgorithmName='");
2544      buffer.append(signatureAlgorithmName);
2545      buffer.append('\'');
2546    }
2547
2548    buffer.append(", issuerDN='");
2549    buffer.append(issuerDN.toString());
2550    buffer.append("', notBefore='");
2551    buffer.append(StaticUtils.encodeGeneralizedTime(notBefore));
2552    buffer.append("', notAfter='");
2553    buffer.append(StaticUtils.encodeGeneralizedTime(notAfter));
2554    buffer.append("', subjectDN='");
2555    buffer.append(subjectDN.toString());
2556    buffer.append("', publicKeyAlgorithmOID='");
2557    buffer.append(publicKeyAlgorithmOID.toString());
2558    buffer.append('\'');
2559
2560    if (publicKeyAlgorithmName != null)
2561    {
2562      buffer.append(", publicKeyAlgorithmName='");
2563      buffer.append(publicKeyAlgorithmName);
2564      buffer.append('\'');
2565    }
2566
2567    buffer.append(", subjectPublicKey=");
2568    if (decodedPublicKey == null)
2569    {
2570      buffer.append('\'');
2571
2572      try
2573      {
2574        StaticUtils.toHex(encodedPublicKey.getBytes(), ":", buffer);
2575      }
2576      catch (final Exception e)
2577      {
2578        Debug.debugException(e);
2579        encodedPublicKey.toString(buffer);
2580      }
2581
2582      buffer.append('\'');
2583    }
2584    else
2585    {
2586      decodedPublicKey.toString(buffer);
2587
2588      if (decodedPublicKey instanceof EllipticCurvePublicKey)
2589      {
2590        try
2591        {
2592          final OID namedCurveOID =
2593               publicKeyAlgorithmParameters.decodeAsObjectIdentifier().getOID();
2594          buffer.append(", ellipticCurvePublicKeyParameters=namedCurve='");
2595          buffer.append(NamedCurve.getNameOrOID(namedCurveOID));
2596          buffer.append('\'');
2597        }
2598        catch (final Exception e)
2599        {
2600          Debug.debugException(e);
2601        }
2602      }
2603    }
2604
2605    if (issuerUniqueID != null)
2606    {
2607      buffer.append(", issuerUniqueID='");
2608      buffer.append(issuerUniqueID.toString());
2609      buffer.append('\'');
2610    }
2611
2612    if (subjectUniqueID != null)
2613    {
2614      buffer.append(", subjectUniqueID='");
2615      buffer.append(subjectUniqueID.toString());
2616      buffer.append('\'');
2617    }
2618
2619    if (! extensions.isEmpty())
2620    {
2621      buffer.append(", extensions={");
2622
2623      final Iterator<X509CertificateExtension> iterator = extensions.iterator();
2624      while (iterator.hasNext())
2625      {
2626        iterator.next().toString(buffer);
2627        if (iterator.hasNext())
2628        {
2629          buffer.append(", ");
2630        }
2631      }
2632
2633      buffer.append('}');
2634    }
2635
2636    buffer.append(", signatureValue='");
2637
2638    try
2639    {
2640      StaticUtils.toHex(signatureValue.getBytes(), ":", buffer);
2641    }
2642    catch (final Exception e)
2643    {
2644      Debug.debugException(e);
2645      buffer.append(signatureValue.toString());
2646    }
2647
2648    buffer.append("')");
2649  }
2650
2651
2652
2653  /**
2654   * Retrieves a list of the lines that comprise a PEM representation of this
2655   * X.509 certificate.
2656   *
2657   * @return  A list of the lines that comprise a PEM representation of this
2658   *          X.509 certificate.
2659   */
2660  @NotNull()
2661  public List<String> toPEM()
2662  {
2663    final ArrayList<String> lines = new ArrayList<>(10);
2664    lines.add("-----BEGIN CERTIFICATE-----");
2665
2666    final String certBase64 = Base64.encode(x509CertificateBytes);
2667    lines.addAll(StaticUtils.wrapLine(certBase64, 64));
2668
2669    lines.add("-----END CERTIFICATE-----");
2670
2671    return Collections.unmodifiableList(lines);
2672  }
2673
2674
2675
2676  /**
2677   * Retrieves a multi-line string containing a PEM representation of this X.509
2678   * certificate.
2679   *
2680   * @return  A multi-line string containing a PEM representation of this X.509
2681   *          certificate.
2682   */
2683  @NotNull()
2684  public String toPEMString()
2685  {
2686    final StringBuilder buffer = new StringBuilder();
2687    buffer.append("-----BEGIN CERTIFICATE-----");
2688    buffer.append(StaticUtils.EOL);
2689
2690    final String certBase64 = Base64.encode(x509CertificateBytes);
2691    for (final String line : StaticUtils.wrapLine(certBase64, 64))
2692    {
2693      buffer.append(line);
2694      buffer.append(StaticUtils.EOL);
2695    }
2696    buffer.append("-----END CERTIFICATE-----");
2697    buffer.append(StaticUtils.EOL);
2698
2699    return buffer.toString();
2700  }
2701}