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.Serializable; 041import java.security.KeyFactory; 042import java.security.KeyPair; 043import java.security.MessageDigest; 044import java.security.PrivateKey; 045import java.security.PublicKey; 046import java.security.Signature; 047import java.security.spec.X509EncodedKeySpec; 048import java.util.ArrayList; 049import java.util.Collections; 050import java.util.Iterator; 051import java.util.List; 052 053import com.unboundid.asn1.ASN1BitString; 054import com.unboundid.asn1.ASN1Element; 055import com.unboundid.asn1.ASN1Integer; 056import com.unboundid.asn1.ASN1ObjectIdentifier; 057import com.unboundid.asn1.ASN1OctetString; 058import com.unboundid.asn1.ASN1Sequence; 059import com.unboundid.asn1.ASN1Set; 060import com.unboundid.ldap.sdk.DN; 061import com.unboundid.util.Base64; 062import com.unboundid.util.CryptoHelper; 063import com.unboundid.util.Debug; 064import com.unboundid.util.NotMutable; 065import com.unboundid.util.NotNull; 066import com.unboundid.util.Nullable; 067import com.unboundid.util.ObjectPair; 068import com.unboundid.util.OID; 069import com.unboundid.util.StaticUtils; 070import com.unboundid.util.ThreadSafety; 071import com.unboundid.util.ThreadSafetyLevel; 072 073import static com.unboundid.util.ssl.cert.CertMessages.*; 074 075 076 077/** 078 * This class provides support for decoding a PKCS #10 certificate signing 079 * request (aka certification request or CSR) as defined in 080 * <A HREF="https://www.ietf.org/rfc/rfc2986.txt">RFC 2986</A>. The certificate 081 * signing request is encoded using the ASN.1 Distinguished Encoding Rules 082 * (DER), which is a subset of BER, and is supported by the code in the 083 * {@code com.unboundid.asn1} package. The ASN.1 specification is as follows: 084 * <PRE> 085 * CertificationRequest ::= SEQUENCE { 086 * certificationRequestInfo CertificationRequestInfo, 087 * signatureAlgorithm AlgorithmIdentifier, 088 * signature BIT STRING 089 * } 090 * 091 * CertificationRequestInfo ::= SEQUENCE { 092 * version INTEGER { v1(0) } (v1,...), 093 * subject Name, 094 * subjectPKInfo SubjectPublicKeyInfo, 095 * attributes [0] Attributes 096 * } 097 * 098 * SubjectPublicKeyInfo ::= SEQUENCE { 099 * algorithm AlgorithmIdentifier, 100 * subjectPublicKey BIT STRING 101 * } 102 * 103 * PKInfoAlgorithms ALGORITHM ::= { 104 * ... -- add any locally defined algorithms here -- } 105 * 106 * Attributes ::= SET OF Attribute 107 * 108 * CRIAttributes ATTRIBUTE ::= { 109 * ... -- add any locally defined attributes here -- } 110 * 111 * Attribute ::= SEQUENCE { 112 * type OBJECT IDENTIFIER, 113 * values SET SIZE(1..MAX) 114 * } 115 * 116 * AlgorithmIdentifier ::= SEQUENCE { 117 * algorithm OBJECT IDENTIFIER, 118 * parameters ANY OPTIONAL 119 * } 120 * 121 * SignatureAlgorithms ALGORITHM ::= { 122 * ... -- add any locally defined algorithms here -- } 123 * </PRE> 124 */ 125@NotMutable() 126@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 127public final class PKCS10CertificateSigningRequest 128 implements Serializable 129{ 130 /** 131 * The DER type for the attributes element. 132 */ 133 private static final byte TYPE_ATTRIBUTES = (byte) 0xA0; 134 135 136 137 /** 138 * The OID for the request attribute that holds the set of requested 139 * certificate extensions. 140 */ 141 @NotNull private static final OID ATTRIBUTE_OID_EXTENSIONS = 142 new OID("1.2.840.113549.1.9.14"); 143 144 145 146 /** 147 * The serial version UID for this serializable class. 148 */ 149 private static final long serialVersionUID = -1665446530589389194L; 150 151 152 153 // The signature value for the request. 154 @NotNull private final ASN1BitString signatureValue; 155 156 // The encoded public key for the request. 157 @NotNull private final ASN1BitString encodedPublicKey; 158 159 // The ASN.1 element with the encoded public key algorithm parameters. 160 @Nullable private final ASN1Element publicKeyAlgorithmParameters; 161 162 // The ASN.1 element with the encoded signature algorithm parameters. 163 @Nullable private final ASN1Element signatureAlgorithmParameters; 164 165 // The bytes that comprise the encoded representation of the PKCS #10 166 // certificate signing request. 167 @NotNull private final byte[] pkcs10CertificateSigningRequestBytes; 168 169 // The decoded public key for this request, if available. 170 @Nullable private final DecodedPublicKey decodedPublicKey; 171 172 // The subject DN for the request. 173 @NotNull private final DN subjectDN; 174 175 // The list of attributes for the request. 176 @NotNull private final List<ObjectPair<OID,ASN1Set>> requestAttributes; 177 178 // The list of extensions for the request. 179 @NotNull private final List<X509CertificateExtension> extensions; 180 181 // The OID for the public key algorithm. 182 @NotNull private final OID publicKeyAlgorithmOID; 183 184 // The OID for the signature algorithm. 185 @NotNull private final OID signatureAlgorithmOID; 186 187 // The PKCS #10 certificate signing request version. 188 @NotNull private final PKCS10CertificateSigningRequestVersion version; 189 190 // The public key algorithm name that corresponds with the public key 191 // algorithm OID, if available. 192 @Nullable private final String publicKeyAlgorithmName; 193 194 // The signature algorithm name that corresponds with the signature algorithm 195 // OID, if available. 196 @Nullable private final String signatureAlgorithmName; 197 198 199 200 /** 201 * Creates a new PKCS #10 certificate signing request with the provided 202 * information. This is primarily intended for unit testing and other 203 * internal use. 204 * 205 * @param version The version number for the 206 * certificate signing request. 207 * @param signatureAlgorithmOID The signature algorithm OID for the 208 * request. This must not be 209 * {@code null}. 210 * @param signatureAlgorithmParameters The encoded signature algorithm 211 * parameters for the request. This 212 * may be {@code null} if there are no 213 * parameters. 214 * @param signatureValue The encoded signature for the 215 * request. This must not be 216 * {@code null}. 217 * @param subjectDN The subject DN for the request. This 218 * This must not be {@code null}. 219 * @param publicKeyAlgorithmOID The OID of the public key algorithm 220 * for the request. This must not be 221 * {@code null}. 222 * @param publicKeyAlgorithmParameters The encoded public key algorithm 223 * parameters for the request. This may 224 * be {@code null} if there are no 225 * parameters. 226 * @param encodedPublicKey The encoded public key for the 227 * request. This must not be 228 * {@code null}. 229 * @param decodedPublicKey The decoded public key for the 230 * request. This may be {@code null} if 231 * it is not available. 232 * @param nonExtensionAttributes Any attributes to include in the 233 * request other than the set of 234 * extensions. This may be {@code null} 235 * or empty if no additional attributes 236 * are needed. 237 * @param extensions The set of extensions included in the 238 * request. This must not be 239 * {@code null} but may be empty. 240 * 241 * @throws CertException If a problem is encountered while creating the 242 * certificate signing request. 243 */ 244 PKCS10CertificateSigningRequest( 245 @NotNull final PKCS10CertificateSigningRequestVersion version, 246 @NotNull final OID signatureAlgorithmOID, 247 @Nullable final ASN1Element signatureAlgorithmParameters, 248 @NotNull final ASN1BitString signatureValue, 249 @NotNull final DN subjectDN, @NotNull final OID publicKeyAlgorithmOID, 250 @Nullable final ASN1Element publicKeyAlgorithmParameters, 251 @NotNull final ASN1BitString encodedPublicKey, 252 @Nullable final DecodedPublicKey decodedPublicKey, 253 @Nullable final List<ObjectPair<OID,ASN1Set>> nonExtensionAttributes, 254 @NotNull final X509CertificateExtension... extensions) 255 throws CertException 256 { 257 this.version = version; 258 this.signatureAlgorithmOID = signatureAlgorithmOID; 259 this.signatureAlgorithmParameters = signatureAlgorithmParameters; 260 this.signatureValue = signatureValue; 261 this.subjectDN = subjectDN; 262 this.publicKeyAlgorithmOID = publicKeyAlgorithmOID; 263 this.publicKeyAlgorithmParameters = publicKeyAlgorithmParameters; 264 this.encodedPublicKey = encodedPublicKey; 265 this.decodedPublicKey = decodedPublicKey; 266 this.extensions = StaticUtils.toList(extensions); 267 268 final SignatureAlgorithmIdentifier signatureAlgorithmIdentifier = 269 SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID); 270 if (signatureAlgorithmIdentifier == null) 271 { 272 signatureAlgorithmName = null; 273 } 274 else 275 { 276 signatureAlgorithmName = 277 signatureAlgorithmIdentifier.getUserFriendlyName(); 278 } 279 280 final PublicKeyAlgorithmIdentifier publicKeyAlgorithmIdentifier = 281 PublicKeyAlgorithmIdentifier.forOID(publicKeyAlgorithmOID); 282 if (publicKeyAlgorithmIdentifier == null) 283 { 284 publicKeyAlgorithmName = null; 285 } 286 else 287 { 288 publicKeyAlgorithmName = publicKeyAlgorithmIdentifier.getName(); 289 } 290 291 final ArrayList<ObjectPair<OID, ASN1Set>> attrs = new ArrayList<>(10); 292 if (nonExtensionAttributes != null) 293 { 294 attrs.addAll(nonExtensionAttributes); 295 } 296 297 if (extensions.length > 0) 298 { 299 final ArrayList<ASN1Element> extensionElements = 300 new ArrayList<>(extensions.length); 301 for (final X509CertificateExtension e : extensions) 302 { 303 extensionElements.add(e.encode()); 304 } 305 306 attrs.add(new ObjectPair<>(ATTRIBUTE_OID_EXTENSIONS, 307 new ASN1Set(new ASN1Sequence(extensionElements)))); 308 } 309 310 requestAttributes = Collections.unmodifiableList(attrs); 311 312 pkcs10CertificateSigningRequestBytes = encode().encode(); 313 } 314 315 316 317 /** 318 * Decodes the contents of the provided byte array as a PKCS #10 certificate 319 * signing request. 320 * 321 * @param encodedRequest The byte array containing the encoded PKCS #10 322 * certificate signing request. This must not be 323 * {@code null}. 324 * 325 * @throws CertException If the contents of the provided byte array could 326 * not be decoded as a valid PKCS #10 certificate 327 * signing request. 328 */ 329 public PKCS10CertificateSigningRequest( 330 @NotNull final byte[] encodedRequest) 331 throws CertException 332 { 333 pkcs10CertificateSigningRequestBytes = encodedRequest; 334 335 final ASN1Element[] requestElements; 336 try 337 { 338 requestElements = 339 ASN1Sequence.decodeAsSequence(encodedRequest).elements(); 340 } 341 catch (final Exception e) 342 { 343 Debug.debugException(e); 344 throw new CertException( 345 ERR_CSR_DECODE_NOT_SEQUENCE.get(StaticUtils.getExceptionMessage(e)), 346 e); 347 } 348 349 if (requestElements.length != 3) 350 { 351 throw new CertException( 352 ERR_CSR_DECODE_UNEXPECTED_SEQUENCE_ELEMENT_COUNT.get( 353 requestElements.length)); 354 } 355 356 final ASN1Element[] requestInfoElements; 357 try 358 { 359 requestInfoElements = 360 ASN1Sequence.decodeAsSequence(requestElements[0]).elements(); 361 } 362 catch (final Exception e) 363 { 364 Debug.debugException(e); 365 throw new CertException( 366 ERR_CSR_DECODE_FIRST_ELEMENT_NOT_SEQUENCE.get( 367 StaticUtils.getExceptionMessage(e)), 368 e); 369 } 370 371 try 372 { 373 final int versionIntValue = 374 requestInfoElements[0].decodeAsInteger().intValue(); 375 version = PKCS10CertificateSigningRequestVersion.valueOf(versionIntValue); 376 if (version == null) 377 { 378 throw new CertException( 379 ERR_CSR_DECODE_UNSUPPORTED_VERSION.get(version)); 380 } 381 } 382 catch (final CertException e) 383 { 384 Debug.debugException(e); 385 throw e; 386 } 387 catch (final Exception e) 388 { 389 Debug.debugException(e); 390 throw new CertException( 391 ERR_CSR_DECODE_CANNOT_PARSE_VERSION.get( 392 StaticUtils.getExceptionMessage(e)), 393 e); 394 } 395 396 try 397 { 398 subjectDN = X509Certificate.decodeName(requestInfoElements[1]); 399 } 400 catch (final Exception e) 401 { 402 Debug.debugException(e); 403 throw new CertException( 404 ERR_CSR_DECODE_CANNOT_PARSE_SUBJECT_DN.get( 405 StaticUtils.getExceptionMessage(e)), 406 e); 407 } 408 409 try 410 { 411 final ASN1Element[] subjectPublicKeyInfoElements = 412 requestInfoElements[2].decodeAsSequence().elements(); 413 final ASN1Element[] publicKeyAlgorithmElements = 414 subjectPublicKeyInfoElements[0].decodeAsSequence().elements(); 415 publicKeyAlgorithmOID = 416 publicKeyAlgorithmElements[0].decodeAsObjectIdentifier().getOID(); 417 if (publicKeyAlgorithmElements.length > 1) 418 { 419 publicKeyAlgorithmParameters = publicKeyAlgorithmElements[1]; 420 } 421 else 422 { 423 publicKeyAlgorithmParameters = null; 424 } 425 426 encodedPublicKey = subjectPublicKeyInfoElements[1].decodeAsBitString(); 427 } 428 catch (final Exception e) 429 { 430 Debug.debugException(e); 431 throw new CertException( 432 ERR_CSR_DECODE_CANNOT_PARSE_PUBLIC_KEY_INFO.get( 433 StaticUtils.getExceptionMessage(e)), 434 e); 435 } 436 437 final PublicKeyAlgorithmIdentifier publicKeyAlgorithmIdentifier = 438 PublicKeyAlgorithmIdentifier.forOID(publicKeyAlgorithmOID); 439 if (publicKeyAlgorithmIdentifier == null) 440 { 441 publicKeyAlgorithmName = null; 442 decodedPublicKey = null; 443 } 444 else 445 { 446 publicKeyAlgorithmName = publicKeyAlgorithmIdentifier.getName(); 447 448 DecodedPublicKey pk = null; 449 switch (publicKeyAlgorithmIdentifier) 450 { 451 case RSA: 452 try 453 { 454 pk = new RSAPublicKey(encodedPublicKey); 455 } 456 catch (final Exception e) 457 { 458 Debug.debugException(e); 459 } 460 break; 461 462 case EC: 463 try 464 { 465 pk = new EllipticCurvePublicKey(encodedPublicKey); 466 } 467 catch (final Exception e) 468 { 469 Debug.debugException(e); 470 } 471 break; 472 } 473 474 decodedPublicKey = pk; 475 } 476 477 final ArrayList<ObjectPair<OID,ASN1Set>> attrList = new ArrayList<>(10); 478 final ArrayList<X509CertificateExtension> extList = new ArrayList<>(10); 479 if (requestInfoElements.length > 3) 480 { 481 for (int i=3; i < requestInfoElements.length; i++) 482 { 483 final ASN1Element element = requestInfoElements[i]; 484 if (element.getType() == TYPE_ATTRIBUTES) 485 { 486 try 487 { 488 for (final ASN1Element attrSetElement : 489 element.decodeAsSet().elements()) 490 { 491 final ASN1Element[] attrElements = 492 attrSetElement.decodeAsSequence().elements(); 493 final OID attrOID = 494 attrElements[0].decodeAsObjectIdentifier().getOID(); 495 final ASN1Set attrValues = attrElements[1].decodeAsSet(); 496 attrList.add(new ObjectPair<>(attrOID, attrValues)); 497 } 498 } 499 catch (final Exception e) 500 { 501 Debug.debugException(e); 502 throw new CertException( 503 ERR_CSR_DECODE_CANNOT_PARSE_ATTRS.get( 504 StaticUtils.getExceptionMessage(e)), 505 e); 506 } 507 508 for (final ObjectPair<OID,ASN1Set> p : attrList) 509 { 510 if (p.getFirst().equals(ATTRIBUTE_OID_EXTENSIONS)) 511 { 512 try 513 { 514 for (final ASN1Element extElement : 515 p.getSecond().elements()[0].decodeAsSequence().elements()) 516 { 517 extList.add(X509CertificateExtension.decode(extElement)); 518 } 519 } 520 catch (final Exception e) 521 { 522 Debug.debugException(e); 523 throw new CertException( 524 ERR_CSR_DECODE_CANNOT_PARSE_EXT_ATTR.get( 525 p.getFirst(), StaticUtils.getExceptionMessage(e)), 526 e); 527 } 528 } 529 } 530 } 531 } 532 } 533 534 requestAttributes = Collections.unmodifiableList(attrList); 535 extensions = Collections.unmodifiableList(extList); 536 537 538 try 539 { 540 final ASN1Element[] signatureAlgorithmElements = 541 requestElements[1].decodeAsSequence().elements(); 542 signatureAlgorithmOID = 543 signatureAlgorithmElements[0].decodeAsObjectIdentifier().getOID(); 544 if (signatureAlgorithmElements.length > 1) 545 { 546 signatureAlgorithmParameters = signatureAlgorithmElements[1]; 547 } 548 else 549 { 550 signatureAlgorithmParameters = null; 551 } 552 } 553 catch (final Exception e) 554 { 555 Debug.debugException(e); 556 throw new CertException( 557 ERR_CSR_DECODE_CANNOT_PARSE_SIG_ALG.get( 558 StaticUtils.getExceptionMessage(e)), 559 e); 560 } 561 562 final SignatureAlgorithmIdentifier signatureAlgorithmIdentifier = 563 SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID); 564 if (signatureAlgorithmIdentifier == null) 565 { 566 signatureAlgorithmName = null; 567 } 568 else 569 { 570 signatureAlgorithmName = 571 signatureAlgorithmIdentifier.getUserFriendlyName(); 572 } 573 574 try 575 { 576 signatureValue = requestElements[2].decodeAsBitString(); 577 } 578 catch (final Exception e) 579 { 580 Debug.debugException(e); 581 throw new CertException( 582 ERR_CSR_DECODE_CANNOT_PARSE_SIG_VALUE.get( 583 StaticUtils.getExceptionMessage(e)), 584 e); 585 } 586 } 587 588 589 590 /** 591 * Encodes this PKCS #10 certificate signing request to an ASN.1 element. 592 * 593 * @return The encoded PKCS #10 certificate signing request. 594 * 595 * @throws CertException If a problem is encountered while trying to encode 596 * the PKCS #10 certificate signing request. 597 */ 598 @NotNull() 599 private ASN1Element encode() 600 throws CertException 601 { 602 try 603 { 604 final ArrayList<ASN1Element> requestInfoElements = new ArrayList<>(4); 605 requestInfoElements.add(new ASN1Integer(version.getIntValue())); 606 requestInfoElements.add(X509Certificate.encodeName(subjectDN)); 607 608 if (publicKeyAlgorithmParameters == null) 609 { 610 requestInfoElements.add(new ASN1Sequence( 611 new ASN1Sequence( 612 new ASN1ObjectIdentifier(publicKeyAlgorithmOID)), 613 encodedPublicKey)); 614 } 615 else 616 { 617 requestInfoElements.add(new ASN1Sequence( 618 new ASN1Sequence( 619 new ASN1ObjectIdentifier(publicKeyAlgorithmOID), 620 publicKeyAlgorithmParameters), 621 encodedPublicKey)); 622 } 623 624 final ArrayList<ASN1Element> attrElements = 625 new ArrayList<>(requestAttributes.size()); 626 for (final ObjectPair<OID,ASN1Set> attr : requestAttributes) 627 { 628 attrElements.add( 629 new ASN1Sequence( 630 new ASN1ObjectIdentifier(attr.getFirst()), 631 attr.getSecond())); 632 } 633 634 requestInfoElements.add(new ASN1Set(TYPE_ATTRIBUTES, attrElements)); 635 636 637 final ArrayList<ASN1Element> certificationRequestElements = 638 new ArrayList<>(3); 639 certificationRequestElements.add(new ASN1Sequence(requestInfoElements)); 640 641 if (signatureAlgorithmParameters == null) 642 { 643 certificationRequestElements.add(new ASN1Sequence( 644 new ASN1ObjectIdentifier(signatureAlgorithmOID))); 645 } 646 else 647 { 648 certificationRequestElements.add(new ASN1Sequence( 649 new ASN1ObjectIdentifier(signatureAlgorithmOID), 650 signatureAlgorithmParameters)); 651 } 652 653 certificationRequestElements.add(signatureValue); 654 655 return new ASN1Sequence(certificationRequestElements); 656 } 657 catch (final Exception e) 658 { 659 Debug.debugException(e); 660 throw new CertException( 661 ERR_CSR_ENCODE_ERROR.get(toString(), 662 StaticUtils.getExceptionMessage(e)), 663 e); 664 } 665 } 666 667 668 669 /** 670 * Generates a PKCS #10 certificate signing request with the provided 671 * information. 672 * 673 * @param signatureAlgorithm The algorithm to use to generate the signature. 674 * This must not be {@code null}. 675 * @param keyPair The key pair to use for the certificate signing 676 * request. This must not be {@code null}. 677 * @param subjectDN The subject DN for the certificate signing 678 * request. This must not be {@code null}. 679 * @param extensions The set of extensions to include in the 680 * certificate signing request. This may be 681 * {@code null} or empty if the request should not 682 * include any custom extensions. 683 * 684 * @return The generated PKCS #10 certificate signing request. 685 * 686 * @throws CertException If a problem is encountered while creating the 687 * certificate signing request. 688 */ 689 @NotNull() 690 public static PKCS10CertificateSigningRequest 691 generateCertificateSigningRequest( 692 @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm, 693 @NotNull final KeyPair keyPair, @NotNull final DN subjectDN, 694 @Nullable final X509CertificateExtension... extensions) 695 throws CertException 696 { 697 // Extract the parameters and encoded public key from the generated key 698 // pair. And while we're at it, generate a subject key identifier from 699 // the encoded public key. 700 DecodedPublicKey decodedPublicKey = null; 701 final ASN1BitString encodedPublicKey; 702 final ASN1Element publicKeyAlgorithmParameters; 703 final byte[] subjectKeyIdentifier; 704 final OID publicKeyAlgorithmOID; 705 try 706 { 707 final ASN1Element[] pkElements = ASN1Sequence.decodeAsSequence( 708 keyPair.getPublic().getEncoded()).elements(); 709 final ASN1Element[] pkAlgIDElements = ASN1Sequence.decodeAsSequence( 710 pkElements[0]).elements(); 711 publicKeyAlgorithmOID = 712 pkAlgIDElements[0].decodeAsObjectIdentifier().getOID(); 713 if (pkAlgIDElements.length == 1) 714 { 715 publicKeyAlgorithmParameters = null; 716 } 717 else 718 { 719 publicKeyAlgorithmParameters = pkAlgIDElements[1]; 720 } 721 722 encodedPublicKey = pkElements[1].decodeAsBitString(); 723 724 try 725 { 726 if (publicKeyAlgorithmOID.equals( 727 PublicKeyAlgorithmIdentifier.RSA.getOID())) 728 { 729 decodedPublicKey = new RSAPublicKey(encodedPublicKey); 730 } 731 else if (publicKeyAlgorithmOID.equals( 732 PublicKeyAlgorithmIdentifier.EC.getOID())) 733 { 734 decodedPublicKey = new EllipticCurvePublicKey(encodedPublicKey); 735 } 736 } 737 catch (final Exception e) 738 { 739 Debug.debugException(e); 740 } 741 742 final MessageDigest sha256 = CryptoHelper.getMessageDigest( 743 SubjectKeyIdentifierExtension. 744 SUBJECT_KEY_IDENTIFIER_DIGEST_ALGORITHM); 745 subjectKeyIdentifier = sha256.digest(encodedPublicKey.getBytes()); 746 } 747 catch (final Exception e) 748 { 749 Debug.debugException(e); 750 throw new CertException( 751 ERR_CSR_GEN_CANNOT_PARSE_KEY_PAIR.get( 752 StaticUtils.getExceptionMessage(e)), 753 e); 754 } 755 756 757 // Construct the set of all extensions for the certificate. 758 final ArrayList<X509CertificateExtension> extensionList = 759 new ArrayList<>(10); 760 extensionList.add(new SubjectKeyIdentifierExtension(false, 761 new ASN1OctetString(subjectKeyIdentifier))); 762 if (extensions != null) 763 { 764 for (final X509CertificateExtension e : extensions) 765 { 766 if (! e.getOID().equals(SubjectKeyIdentifierExtension. 767 SUBJECT_KEY_IDENTIFIER_OID)) 768 { 769 extensionList.add(e); 770 } 771 } 772 } 773 774 final X509CertificateExtension[] allExtensions = 775 new X509CertificateExtension[extensionList.size()]; 776 extensionList.toArray(allExtensions); 777 778 779 final ASN1BitString encodedSignature = generateSignature(signatureAlgorithm, 780 keyPair.getPrivate(), subjectDN, publicKeyAlgorithmOID, 781 publicKeyAlgorithmParameters, encodedPublicKey, allExtensions); 782 783 return new PKCS10CertificateSigningRequest( 784 PKCS10CertificateSigningRequestVersion.V1, signatureAlgorithm.getOID(), 785 null, encodedSignature, subjectDN, publicKeyAlgorithmOID, 786 publicKeyAlgorithmParameters, encodedPublicKey, decodedPublicKey, 787 null, allExtensions); 788 } 789 790 791 792 /** 793 * Generates a signature for the certificate signing request with the provided 794 * information. 795 * 796 * @param signatureAlgorithm The signature algorithm to use to 797 * generate the signature. This must 798 * not be {@code null}. 799 * @param privateKey The private key to use to sign the 800 * certificate signing request. This 801 * must not be {@code null}. 802 * @param subjectDN The subject DN for the certificate 803 * signing request. This must not be 804 * {@code null}. 805 * @param publicKeyAlgorithmOID The OID for the public key algorithm. 806 * This must not be {@code null}. 807 * @param publicKeyAlgorithmParameters The encoded public key algorithm 808 * parameters. This may be 809 * {@code null} if no parameters are 810 * needed. 811 * @param encodedPublicKey The encoded representation of the 812 * public key. This must not be 813 * {@code null}. 814 * @param extensions The set of extensions to include in 815 * the certificate signing request. 816 * This must not be {@code null} but 817 * may be empty. 818 * 819 * @return An encoded representation of the generated signature. 820 * 821 * @throws CertException If a problem is encountered while generating the 822 * certificate. 823 */ 824 @NotNull() 825 private static ASN1BitString generateSignature( 826 @NotNull final SignatureAlgorithmIdentifier signatureAlgorithm, 827 @NotNull final PrivateKey privateKey, 828 @NotNull final DN subjectDN, 829 @NotNull final OID publicKeyAlgorithmOID, 830 @Nullable final ASN1Element publicKeyAlgorithmParameters, 831 @NotNull final ASN1BitString encodedPublicKey, 832 @NotNull final X509CertificateExtension... extensions) 833 throws CertException 834 { 835 // Get and initialize the signature generator. 836 final Signature signature; 837 try 838 { 839 signature = CryptoHelper.getSignature(signatureAlgorithm.getJavaName()); 840 } 841 catch (final Exception e) 842 { 843 Debug.debugException(e); 844 throw new CertException( 845 ERR_CSR_GEN_SIGNATURE_CANNOT_GET_SIGNATURE_GENERATOR.get( 846 signatureAlgorithm.getJavaName(), 847 StaticUtils.getExceptionMessage(e)), 848 e); 849 } 850 851 try 852 { 853 signature.initSign(privateKey); 854 } 855 catch (final Exception e) 856 { 857 Debug.debugException(e); 858 throw new CertException( 859 ERR_CSR_GEN_SIGNATURE_CANNOT_INIT_SIGNATURE_GENERATOR.get( 860 signatureAlgorithm.getJavaName(), 861 StaticUtils.getExceptionMessage(e)), 862 e); 863 } 864 865 866 // Construct the requestInfo element of the certificate signing request and 867 // compute its signature. 868 try 869 { 870 final ArrayList<ASN1Element> requestInfoElements = new ArrayList<>(4); 871 requestInfoElements.add(new ASN1Integer( 872 PKCS10CertificateSigningRequestVersion.V1.getIntValue())); 873 requestInfoElements.add(X509Certificate.encodeName(subjectDN)); 874 875 if (publicKeyAlgorithmParameters == null) 876 { 877 requestInfoElements.add(new ASN1Sequence( 878 new ASN1Sequence( 879 new ASN1ObjectIdentifier(publicKeyAlgorithmOID)), 880 encodedPublicKey)); 881 } 882 else 883 { 884 requestInfoElements.add(new ASN1Sequence( 885 new ASN1Sequence( 886 new ASN1ObjectIdentifier(publicKeyAlgorithmOID), 887 publicKeyAlgorithmParameters), 888 encodedPublicKey)); 889 } 890 891 final ArrayList<ASN1Element> attrElements = new ArrayList<>(1); 892 if ((extensions != null) && (extensions.length > 0)) 893 { 894 final ArrayList<ASN1Element> extensionElements = 895 new ArrayList<>(extensions.length); 896 for (final X509CertificateExtension e : extensions) 897 { 898 extensionElements.add(e.encode()); 899 } 900 901 attrElements.add(new ASN1Sequence( 902 new ASN1ObjectIdentifier(ATTRIBUTE_OID_EXTENSIONS), 903 new ASN1Set(new ASN1Sequence(extensionElements)))); 904 } 905 requestInfoElements.add(new ASN1Set(TYPE_ATTRIBUTES, attrElements)); 906 907 final byte[] certificationRequestInfoBytes = 908 new ASN1Sequence(requestInfoElements).encode(); 909 signature.update(certificationRequestInfoBytes); 910 final byte[] signatureBytes = signature.sign(); 911 912 return new ASN1BitString(ASN1BitString.getBitsForBytes(signatureBytes)); 913 } 914 catch (final Exception e) 915 { 916 Debug.debugException(e); 917 throw new CertException( 918 ERR_CSR_GEN_SIGNATURE_CANNOT_COMPUTE.get( 919 signatureAlgorithm.getJavaName(), 920 StaticUtils.getExceptionMessage(e)), 921 e); 922 } 923 } 924 925 926 927 /** 928 * Retrieves the bytes that comprise the encoded representation of this 929 * PKCS #10 certificate signing request. 930 * 931 * @return The bytes that comprise the encoded representation of this 932 * PKCS #10 certificate signing request. 933 */ 934 @NotNull() 935 public byte[] getPKCS10CertificateSigningRequestBytes() 936 { 937 return pkcs10CertificateSigningRequestBytes; 938 } 939 940 941 942 /** 943 * Retrieves the certificate signing request version. 944 * 945 * @return The certificate signing request version. 946 */ 947 @NotNull() 948 public PKCS10CertificateSigningRequestVersion getVersion() 949 { 950 return version; 951 } 952 953 954 955 /** 956 * Retrieves the certificate signing request signature algorithm OID. 957 * 958 * @return The certificate signing request signature algorithm OID. 959 */ 960 @NotNull() 961 public OID getSignatureAlgorithmOID() 962 { 963 return signatureAlgorithmOID; 964 } 965 966 967 968 /** 969 * Retrieves the certificate signing request signature algorithm name, if 970 * available. 971 * 972 * @return The certificate signing request signature algorithm name, or 973 * {@code null} if the signature algorithm OID does not correspond to 974 * any known algorithm name. 975 */ 976 @Nullable() 977 public String getSignatureAlgorithmName() 978 { 979 return signatureAlgorithmName; 980 } 981 982 983 984 /** 985 * Retrieves the signature algorithm name if it is available, or the string 986 * representation of the signature algorithm OID if not. 987 * 988 * @return The signature algorithm name or OID. 989 */ 990 @NotNull() 991 public String getSignatureAlgorithmNameOrOID() 992 { 993 if (signatureAlgorithmName != null) 994 { 995 return signatureAlgorithmName; 996 } 997 else 998 { 999 return signatureAlgorithmOID.toString(); 1000 } 1001 } 1002 1003 1004 1005 /** 1006 * Retrieves the encoded signature algorithm parameters, if present. 1007 * 1008 * @return The encoded signature algorithm parameters, or {@code null} if 1009 * there are no signature algorithm parameters. 1010 */ 1011 @Nullable() 1012 public ASN1Element getSignatureAlgorithmParameters() 1013 { 1014 return signatureAlgorithmParameters; 1015 } 1016 1017 1018 1019 /** 1020 * Retrieves the certificate signing request subject DN. 1021 * 1022 * @return The certificate signing request subject DN. 1023 */ 1024 @NotNull() 1025 public DN getSubjectDN() 1026 { 1027 return subjectDN; 1028 } 1029 1030 1031 1032 /** 1033 * Retrieves the certificate signing request public key algorithm OID. 1034 * 1035 * @return The certificate signing request public key algorithm OID. 1036 */ 1037 @NotNull() 1038 public OID getPublicKeyAlgorithmOID() 1039 { 1040 return publicKeyAlgorithmOID; 1041 } 1042 1043 1044 1045 /** 1046 * Retrieves the certificate signing request public key algorithm name, if 1047 * available. 1048 * 1049 * @return The certificate signing request public key algorithm name, or 1050 * {@code null} if the public key algorithm OID does not correspond 1051 * to any known algorithm name. 1052 */ 1053 @Nullable() 1054 public String getPublicKeyAlgorithmName() 1055 { 1056 return publicKeyAlgorithmName; 1057 } 1058 1059 1060 1061 /** 1062 * Retrieves the public key algorithm name if it is available, or the string 1063 * representation of the public key algorithm OID if not. 1064 * 1065 * @return The signature algorithm name or OID. 1066 */ 1067 @NotNull() 1068 public String getPublicKeyAlgorithmNameOrOID() 1069 { 1070 if (publicKeyAlgorithmName != null) 1071 { 1072 return publicKeyAlgorithmName; 1073 } 1074 else 1075 { 1076 return publicKeyAlgorithmOID.toString(); 1077 } 1078 } 1079 1080 1081 1082 /** 1083 * Retrieves the encoded public key algorithm parameters, if present. 1084 * 1085 * @return The encoded public key algorithm parameters, or {@code null} if 1086 * there are no public key algorithm parameters. 1087 */ 1088 @Nullable() 1089 public ASN1Element getPublicKeyAlgorithmParameters() 1090 { 1091 return publicKeyAlgorithmParameters; 1092 } 1093 1094 1095 1096 /** 1097 * Retrieves the encoded public key as a bit string. 1098 * 1099 * @return The encoded public key as a bit string. 1100 */ 1101 @NotNull() 1102 public ASN1BitString getEncodedPublicKey() 1103 { 1104 return encodedPublicKey; 1105 } 1106 1107 1108 1109 /** 1110 * Retrieves a decoded representation of the public key, if available. 1111 * 1112 * @return A decoded representation of the public key, or {@code null} if the 1113 * public key could not be decoded. 1114 */ 1115 @Nullable() 1116 public DecodedPublicKey getDecodedPublicKey() 1117 { 1118 return decodedPublicKey; 1119 } 1120 1121 1122 1123 /** 1124 * Retrieves the encoded request attributes included in the certificate 1125 * signing request. 1126 * 1127 * @return The encoded request attributes included in the certificate signing 1128 * request. 1129 */ 1130 @NotNull() 1131 public List<ObjectPair<OID,ASN1Set>> getRequestAttributes() 1132 { 1133 return requestAttributes; 1134 } 1135 1136 1137 1138 /** 1139 * Retrieves the list of certificate extensions included in the certificate 1140 * signing request. 1141 * 1142 * @return The list of certificate extensions included in the certificate 1143 * signing request. 1144 */ 1145 @NotNull() 1146 public List<X509CertificateExtension> getExtensions() 1147 { 1148 return extensions; 1149 } 1150 1151 1152 1153 /** 1154 * Retrieves the signature value for the certificate signing request. 1155 * 1156 * @return The signature value for the certificate signing request. 1157 */ 1158 @NotNull() 1159 public ASN1BitString getSignatureValue() 1160 { 1161 return signatureValue; 1162 } 1163 1164 1165 1166 /** 1167 * Verifies the signature for this certificate signing request. 1168 * 1169 * @throws CertException If the certificate signing request's signature 1170 * could not be verified. 1171 */ 1172 public void verifySignature() 1173 throws CertException 1174 { 1175 // Generate the public key for this certificate signing request. 1176 final PublicKey publicKey; 1177 try 1178 { 1179 final byte[] encodedPublicKeyBytes; 1180 if (publicKeyAlgorithmParameters == null) 1181 { 1182 encodedPublicKeyBytes = new ASN1Sequence( 1183 new ASN1Sequence( 1184 new ASN1ObjectIdentifier(publicKeyAlgorithmOID)), 1185 encodedPublicKey).encode(); 1186 } 1187 else 1188 { 1189 encodedPublicKeyBytes = new ASN1Sequence( 1190 new ASN1Sequence( 1191 new ASN1ObjectIdentifier(publicKeyAlgorithmOID), 1192 publicKeyAlgorithmParameters), 1193 encodedPublicKey).encode(); 1194 } 1195 1196 final KeyFactory keyFactory = 1197 CryptoHelper.getKeyFactory(getPublicKeyAlgorithmNameOrOID()); 1198 publicKey = keyFactory.generatePublic( 1199 new X509EncodedKeySpec(encodedPublicKeyBytes)); 1200 } 1201 catch (final Exception e) 1202 { 1203 Debug.debugException(e); 1204 throw new CertException( 1205 ERR_CSR_VERIFY_SIGNATURE_CANNOT_GET_PUBLIC_KEY.get( 1206 StaticUtils.getExceptionMessage(e)), 1207 e); 1208 } 1209 1210 1211 // Get and initialize the signature generator. 1212 final Signature signature; 1213 final SignatureAlgorithmIdentifier signatureAlgorithm; 1214 try 1215 { 1216 signatureAlgorithm = 1217 SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID); 1218 signature = CryptoHelper.getSignature(signatureAlgorithm.getJavaName()); 1219 } 1220 catch (final Exception e) 1221 { 1222 Debug.debugException(e); 1223 throw new CertException( 1224 ERR_CSR_VERIFY_SIGNATURE_CANNOT_GET_SIGNATURE_VERIFIER.get( 1225 getSignatureAlgorithmNameOrOID(), 1226 StaticUtils.getExceptionMessage(e)), 1227 e); 1228 } 1229 1230 try 1231 { 1232 signature.initVerify(publicKey); 1233 } 1234 catch (final Exception e) 1235 { 1236 Debug.debugException(e); 1237 throw new CertException( 1238 ERR_CSR_VERIFY_SIGNATURE_CANNOT_INIT_SIGNATURE_VERIFIER.get( 1239 signatureAlgorithm.getJavaName(), 1240 StaticUtils.getExceptionMessage(e)), 1241 e); 1242 } 1243 1244 1245 // Construct the requestInfo element of the certificate signing request and 1246 // compute its signature. 1247 final boolean signatureIsValid; 1248 try 1249 { 1250 final ASN1Element[] requestInfoElements = 1251 ASN1Sequence.decodeAsSequence( 1252 pkcs10CertificateSigningRequestBytes).elements(); 1253 final byte[] requestInfoBytes = requestInfoElements[0].encode(); 1254 signature.update(requestInfoBytes); 1255 signatureIsValid = signature.verify(signatureValue.getBytes()); 1256 } 1257 catch (final Exception e) 1258 { 1259 Debug.debugException(e); 1260 throw new CertException( 1261 ERR_CSR_VERIFY_SIGNATURE_ERROR.get(subjectDN, 1262 StaticUtils.getExceptionMessage(e)), 1263 e); 1264 } 1265 1266 if (! signatureIsValid) 1267 { 1268 throw new CertException( 1269 ERR_CSR_VERIFY_SIGNATURE_NOT_VALID.get(subjectDN)); 1270 } 1271 } 1272 1273 1274 1275 /** 1276 * Retrieves a string representation of the decoded X.509 certificate. 1277 * 1278 * @return A string representation of the decoded X.509 certificate. 1279 */ 1280 @Override() 1281 @NotNull() 1282 public String toString() 1283 { 1284 final StringBuilder buffer = new StringBuilder(); 1285 toString(buffer); 1286 return buffer.toString(); 1287 } 1288 1289 1290 1291 /** 1292 * Appends a string representation of the decoded X.509 certificate to the 1293 * provided buffer. 1294 * 1295 * @param buffer The buffer to which the information should be appended. 1296 */ 1297 public void toString(@NotNull final StringBuilder buffer) 1298 { 1299 buffer.append("PKCS10CertificateSigningRequest(version='"); 1300 buffer.append(version.getName()); 1301 buffer.append("', subjectDN='"); 1302 buffer.append(subjectDN); 1303 buffer.append("', publicKeyAlgorithmOID='"); 1304 buffer.append(publicKeyAlgorithmOID.toString()); 1305 buffer.append('\''); 1306 1307 if (publicKeyAlgorithmName != null) 1308 { 1309 buffer.append(", publicKeyAlgorithmName='"); 1310 buffer.append(publicKeyAlgorithmName); 1311 buffer.append('\''); 1312 } 1313 1314 buffer.append(", subjectPublicKey="); 1315 if (decodedPublicKey == null) 1316 { 1317 buffer.append('\''); 1318 1319 try 1320 { 1321 StaticUtils.toHex(encodedPublicKey.getBytes(), ":", buffer); 1322 } 1323 catch (final Exception e) 1324 { 1325 Debug.debugException(e); 1326 encodedPublicKey.toString(buffer); 1327 } 1328 1329 buffer.append('\''); 1330 } 1331 else 1332 { 1333 decodedPublicKey.toString(buffer); 1334 1335 if (decodedPublicKey instanceof EllipticCurvePublicKey) 1336 { 1337 try 1338 { 1339 final OID namedCurveOID = 1340 publicKeyAlgorithmParameters.decodeAsObjectIdentifier().getOID(); 1341 buffer.append(", ellipticCurvePublicKeyParameters=namedCurve='"); 1342 buffer.append(NamedCurve.getNameOrOID(namedCurveOID)); 1343 buffer.append('\''); 1344 } 1345 catch (final Exception e) 1346 { 1347 Debug.debugException(e); 1348 } 1349 } 1350 } 1351 1352 buffer.append(", signatureAlgorithmOID='"); 1353 buffer.append(signatureAlgorithmOID.toString()); 1354 buffer.append('\''); 1355 1356 if (signatureAlgorithmName != null) 1357 { 1358 buffer.append(", signatureAlgorithmName='"); 1359 buffer.append(signatureAlgorithmName); 1360 buffer.append('\''); 1361 } 1362 1363 if (! extensions.isEmpty()) 1364 { 1365 buffer.append(", extensions={"); 1366 1367 final Iterator<X509CertificateExtension> iterator = extensions.iterator(); 1368 while (iterator.hasNext()) 1369 { 1370 iterator.next().toString(buffer); 1371 if (iterator.hasNext()) 1372 { 1373 buffer.append(", "); 1374 } 1375 } 1376 1377 buffer.append('}'); 1378 } 1379 1380 buffer.append(", signatureValue='"); 1381 1382 try 1383 { 1384 StaticUtils.toHex(signatureValue.getBytes(), ":", buffer); 1385 } 1386 catch (final Exception e) 1387 { 1388 Debug.debugException(e); 1389 buffer.append(signatureValue.toString()); 1390 } 1391 1392 buffer.append("')"); 1393 } 1394 1395 1396 1397 /** 1398 * Retrieves a list of the lines that comprise a PEM representation of this 1399 * PKCS #10 certificate signing request. 1400 * 1401 * @return A list of the lines that comprise a PEM representation of this 1402 * PKCS #10 certificate signing request. 1403 */ 1404 @NotNull() 1405 public List<String> toPEM() 1406 { 1407 final ArrayList<String> lines = new ArrayList<>(10); 1408 lines.add("-----BEGIN CERTIFICATE REQUEST-----"); 1409 1410 final String csrBase64 = 1411 Base64.encode(pkcs10CertificateSigningRequestBytes); 1412 lines.addAll(StaticUtils.wrapLine(csrBase64, 64)); 1413 1414 lines.add("-----END CERTIFICATE REQUEST-----"); 1415 1416 return Collections.unmodifiableList(lines); 1417 } 1418 1419 1420 1421 /** 1422 * Retrieves a multi-line string containing a PEM representation of this 1423 * PKCS #10 certificate signing request. 1424 * 1425 * @return A multi-line string containing a PEM representation of this 1426 * PKCS #10 certificate signing request. 1427 */ 1428 @NotNull() 1429 public String toPEMString() 1430 { 1431 final StringBuilder buffer = new StringBuilder(); 1432 buffer.append("-----BEGIN CERTIFICATE REQUEST-----"); 1433 buffer.append(StaticUtils.EOL); 1434 1435 final String csrBase64 = 1436 Base64.encode(pkcs10CertificateSigningRequestBytes); 1437 for (final String line : StaticUtils.wrapLine(csrBase64, 64)) 1438 { 1439 buffer.append(line); 1440 buffer.append(StaticUtils.EOL); 1441 } 1442 buffer.append("-----END CERTIFICATE REQUEST-----"); 1443 buffer.append(StaticUtils.EOL); 1444 1445 return buffer.toString(); 1446 } 1447}