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