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