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}