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("SHA-256"); 722 subjectKeyIdentifier = sha256.digest(encodedPublicKey.getBytes()); 723 } 724 catch (final Exception e) 725 { 726 Debug.debugException(e); 727 throw new CertException( 728 ERR_CSR_GEN_CANNOT_PARSE_KEY_PAIR.get( 729 StaticUtils.getExceptionMessage(e)), 730 e); 731 } 732 733 734 // Construct the set of all extensions for the certificate. 735 final ArrayList<X509CertificateExtension> extensionList = 736 new ArrayList<>(10); 737 extensionList.add(new SubjectKeyIdentifierExtension(false, 738 new ASN1OctetString(subjectKeyIdentifier))); 739 if (extensions != null) 740 { 741 for (final X509CertificateExtension e : extensions) 742 { 743 if (! e.getOID().equals(SubjectKeyIdentifierExtension. 744 SUBJECT_KEY_IDENTIFIER_OID)) 745 { 746 extensionList.add(e); 747 } 748 } 749 } 750 751 final X509CertificateExtension[] allExtensions = 752 new X509CertificateExtension[extensionList.size()]; 753 extensionList.toArray(allExtensions); 754 755 756 final ASN1BitString encodedSignature = generateSignature(signatureAlgorithm, 757 keyPair.getPrivate(), subjectDN, publicKeyAlgorithmOID, 758 publicKeyAlgorithmParameters, encodedPublicKey, allExtensions); 759 760 return new PKCS10CertificateSigningRequest( 761 PKCS10CertificateSigningRequestVersion.V1, signatureAlgorithm.getOID(), 762 null, encodedSignature, subjectDN, publicKeyAlgorithmOID, 763 publicKeyAlgorithmParameters, encodedPublicKey, decodedPublicKey, 764 null, allExtensions); 765 } 766 767 768 769 /** 770 * Generates a signature for the certificate signing request with the provided 771 * information. 772 * 773 * @param signatureAlgorithm The signature algorithm to use to 774 * generate the signature. This must 775 * not be {@code null}. 776 * @param privateKey The private key to use to sign the 777 * certificate signing request. This 778 * must not be {@code null}. 779 * @param subjectDN The subject DN for the certificate 780 * signing request. This must not be 781 * {@code null}. 782 * @param publicKeyAlgorithmOID The OID for the public key algorithm. 783 * This must not be {@code null}. 784 * @param publicKeyAlgorithmParameters The encoded public key algorithm 785 * parameters. This may be 786 * {@code null} if no parameters are 787 * needed. 788 * @param encodedPublicKey The encoded representation of the 789 * public key. This must not be 790 * {@code null}. 791 * @param extensions The set of extensions to include in 792 * the certificate signing request. 793 * This must not be {@code null} but 794 * may be empty. 795 * 796 * @return An encoded representation of the generated signature. 797 * 798 * @throws CertException If a problem is encountered while generating the 799 * certificate. 800 */ 801 private static ASN1BitString generateSignature( 802 final SignatureAlgorithmIdentifier signatureAlgorithm, 803 final PrivateKey privateKey, final DN subjectDN, 804 final OID publicKeyAlgorithmOID, 805 final ASN1Element publicKeyAlgorithmParameters, 806 final ASN1BitString encodedPublicKey, 807 final X509CertificateExtension... extensions) 808 throws CertException 809 { 810 // Get and initialize the signature generator. 811 final Signature signature; 812 try 813 { 814 signature = Signature.getInstance(signatureAlgorithm.getJavaName()); 815 } 816 catch (final Exception e) 817 { 818 Debug.debugException(e); 819 throw new CertException( 820 ERR_CSR_GEN_SIGNATURE_CANNOT_GET_SIGNATURE_GENERATOR.get( 821 signatureAlgorithm.getJavaName(), 822 StaticUtils.getExceptionMessage(e)), 823 e); 824 } 825 826 try 827 { 828 signature.initSign(privateKey); 829 } 830 catch (final Exception e) 831 { 832 Debug.debugException(e); 833 throw new CertException( 834 ERR_CSR_GEN_SIGNATURE_CANNOT_INIT_SIGNATURE_GENERATOR.get( 835 signatureAlgorithm.getJavaName(), 836 StaticUtils.getExceptionMessage(e)), 837 e); 838 } 839 840 841 // Construct the requestInfo element of the certificate signing request and 842 // compute its signature. 843 try 844 { 845 final ArrayList<ASN1Element> requestInfoElements = new ArrayList<>(4); 846 requestInfoElements.add(new ASN1Integer( 847 PKCS10CertificateSigningRequestVersion.V1.getIntValue())); 848 requestInfoElements.add(X509Certificate.encodeName(subjectDN)); 849 850 if (publicKeyAlgorithmParameters == null) 851 { 852 requestInfoElements.add(new ASN1Sequence( 853 new ASN1Sequence( 854 new ASN1ObjectIdentifier(publicKeyAlgorithmOID)), 855 encodedPublicKey)); 856 } 857 else 858 { 859 requestInfoElements.add(new ASN1Sequence( 860 new ASN1Sequence( 861 new ASN1ObjectIdentifier(publicKeyAlgorithmOID), 862 publicKeyAlgorithmParameters), 863 encodedPublicKey)); 864 } 865 866 final ArrayList<ASN1Element> attrElements = new ArrayList<>(1); 867 if ((extensions != null) && (extensions.length > 0)) 868 { 869 final ArrayList<ASN1Element> extensionElements = 870 new ArrayList<>(extensions.length); 871 for (final X509CertificateExtension e : extensions) 872 { 873 extensionElements.add(e.encode()); 874 } 875 876 attrElements.add(new ASN1Sequence( 877 new ASN1ObjectIdentifier(ATTRIBUTE_OID_EXTENSIONS), 878 new ASN1Set(new ASN1Sequence(extensionElements)))); 879 } 880 requestInfoElements.add(new ASN1Set(TYPE_ATTRIBUTES, attrElements)); 881 882 final byte[] certificationRequestInfoBytes = 883 new ASN1Sequence(requestInfoElements).encode(); 884 signature.update(certificationRequestInfoBytes); 885 final byte[] signatureBytes = signature.sign(); 886 887 return new ASN1BitString(ASN1BitString.getBitsForBytes(signatureBytes)); 888 } 889 catch (final Exception e) 890 { 891 Debug.debugException(e); 892 throw new CertException( 893 ERR_CSR_GEN_SIGNATURE_CANNOT_COMPUTE.get( 894 signatureAlgorithm.getJavaName(), 895 StaticUtils.getExceptionMessage(e)), 896 e); 897 } 898 } 899 900 901 902 /** 903 * Retrieves the bytes that comprise the encoded representation of this 904 * PKCS #10 certificate signing request. 905 * 906 * @return The bytes that comprise the encoded representation of this 907 * PKCS #10 certificate signing request. 908 */ 909 public byte[] getPKCS10CertificateSigningRequestBytes() 910 { 911 return pkcs10CertificateSigningRequestBytes; 912 } 913 914 915 916 /** 917 * Retrieves the certificate signing request version. 918 * 919 * @return The certificate signing request version. 920 */ 921 public PKCS10CertificateSigningRequestVersion getVersion() 922 { 923 return version; 924 } 925 926 927 928 /** 929 * Retrieves the certificate signing request signature algorithm OID. 930 * 931 * @return The certificate signing request signature algorithm OID. 932 */ 933 public OID getSignatureAlgorithmOID() 934 { 935 return signatureAlgorithmOID; 936 } 937 938 939 940 /** 941 * Retrieves the certificate signing request signature algorithm name, if 942 * available. 943 * 944 * @return The certificate signing request signature algorithm name, or 945 * {@code null} if the signature algorithm OID does not correspond to 946 * any known algorithm name. 947 */ 948 public String getSignatureAlgorithmName() 949 { 950 return signatureAlgorithmName; 951 } 952 953 954 955 /** 956 * Retrieves the signature algorithm name if it is available, or the string 957 * representation of the signature algorithm OID if not. 958 * 959 * @return The signature algorithm name or OID. 960 */ 961 public String getSignatureAlgorithmNameOrOID() 962 { 963 if (signatureAlgorithmName != null) 964 { 965 return signatureAlgorithmName; 966 } 967 else 968 { 969 return signatureAlgorithmOID.toString(); 970 } 971 } 972 973 974 975 /** 976 * Retrieves the encoded signature algorithm parameters, if present. 977 * 978 * @return The encoded signature algorithm parameters, or {@code null} if 979 * there are no signature algorithm parameters. 980 */ 981 public ASN1Element getSignatureAlgorithmParameters() 982 { 983 return signatureAlgorithmParameters; 984 } 985 986 987 988 /** 989 * Retrieves the certificate signing request subject DN. 990 * 991 * @return The certificate signing request subject DN. 992 */ 993 public DN getSubjectDN() 994 { 995 return subjectDN; 996 } 997 998 999 1000 /** 1001 * Retrieves the certificate signing request public key algorithm OID. 1002 * 1003 * @return The certificate signing request public key algorithm OID. 1004 */ 1005 public OID getPublicKeyAlgorithmOID() 1006 { 1007 return publicKeyAlgorithmOID; 1008 } 1009 1010 1011 1012 /** 1013 * Retrieves the certificate signing request public key algorithm name, if 1014 * available. 1015 * 1016 * @return The certificate signing request public key algorithm name, or 1017 * {@code null} if the public key algorithm OID does not correspond 1018 * to any known algorithm name. 1019 */ 1020 public String getPublicKeyAlgorithmName() 1021 { 1022 return publicKeyAlgorithmName; 1023 } 1024 1025 1026 1027 /** 1028 * Retrieves the public key algorithm name if it is available, or the string 1029 * representation of the public key algorithm OID if not. 1030 * 1031 * @return The signature algorithm name or OID. 1032 */ 1033 public String getPublicKeyAlgorithmNameOrOID() 1034 { 1035 if (publicKeyAlgorithmName != null) 1036 { 1037 return publicKeyAlgorithmName; 1038 } 1039 else 1040 { 1041 return publicKeyAlgorithmOID.toString(); 1042 } 1043 } 1044 1045 1046 1047 /** 1048 * Retrieves the encoded public key algorithm parameters, if present. 1049 * 1050 * @return The encoded public key algorithm parameters, or {@code null} if 1051 * there are no public key algorithm parameters. 1052 */ 1053 public ASN1Element getPublicKeyAlgorithmParameters() 1054 { 1055 return publicKeyAlgorithmParameters; 1056 } 1057 1058 1059 1060 /** 1061 * Retrieves the encoded public key as a bit string. 1062 * 1063 * @return The encoded public key as a bit string. 1064 */ 1065 public ASN1BitString getEncodedPublicKey() 1066 { 1067 return encodedPublicKey; 1068 } 1069 1070 1071 1072 /** 1073 * Retrieves a decoded representation of the public key, if available. 1074 * 1075 * @return A decoded representation of the public key, or {@code null} if the 1076 * public key could not be decoded. 1077 */ 1078 public DecodedPublicKey getDecodedPublicKey() 1079 { 1080 return decodedPublicKey; 1081 } 1082 1083 1084 1085 /** 1086 * Retrieves the encoded request attributes included in the certificate 1087 * signing request. 1088 * 1089 * @return The encoded request attributes included in the certificate signing 1090 * request. 1091 */ 1092 public List<ObjectPair<OID,ASN1Set>> getRequestAttributes() 1093 { 1094 return requestAttributes; 1095 } 1096 1097 1098 1099 /** 1100 * Retrieves the list of certificate extensions included in the certificate 1101 * signing request. 1102 * 1103 * @return The list of certificate extensions included in the certificate 1104 * signing request. 1105 */ 1106 public List<X509CertificateExtension> getExtensions() 1107 { 1108 return extensions; 1109 } 1110 1111 1112 1113 /** 1114 * Retrieves the signature value for the certificate signing request. 1115 * 1116 * @return The signature value for the certificate signing request. 1117 */ 1118 public ASN1BitString getSignatureValue() 1119 { 1120 return signatureValue; 1121 } 1122 1123 1124 1125 /** 1126 * Verifies the signature for this certificate signing request. 1127 * 1128 * @throws CertException If the certificate signing request's signature 1129 * could not be verified. 1130 */ 1131 public void verifySignature() 1132 throws CertException 1133 { 1134 // Generate the public key for this certificate signing request. 1135 final PublicKey publicKey; 1136 try 1137 { 1138 final byte[] encodedPublicKeyBytes; 1139 if (publicKeyAlgorithmParameters == null) 1140 { 1141 encodedPublicKeyBytes = new ASN1Sequence( 1142 new ASN1Sequence( 1143 new ASN1ObjectIdentifier(publicKeyAlgorithmOID)), 1144 encodedPublicKey).encode(); 1145 } 1146 else 1147 { 1148 encodedPublicKeyBytes = new ASN1Sequence( 1149 new ASN1Sequence( 1150 new ASN1ObjectIdentifier(publicKeyAlgorithmOID), 1151 publicKeyAlgorithmParameters), 1152 encodedPublicKey).encode(); 1153 } 1154 1155 final KeyFactory keyFactory = 1156 KeyFactory.getInstance(getPublicKeyAlgorithmNameOrOID()); 1157 publicKey = keyFactory.generatePublic( 1158 new X509EncodedKeySpec(encodedPublicKeyBytes)); 1159 } 1160 catch (final Exception e) 1161 { 1162 Debug.debugException(e); 1163 throw new CertException( 1164 ERR_CSR_VERIFY_SIGNATURE_CANNOT_GET_PUBLIC_KEY.get( 1165 StaticUtils.getExceptionMessage(e)), 1166 e); 1167 } 1168 1169 1170 // Get and initialize the signature generator. 1171 final Signature signature; 1172 final SignatureAlgorithmIdentifier signatureAlgorithm; 1173 try 1174 { 1175 signatureAlgorithm = 1176 SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID); 1177 signature = Signature.getInstance(signatureAlgorithm.getJavaName()); 1178 } 1179 catch (final Exception e) 1180 { 1181 Debug.debugException(e); 1182 throw new CertException( 1183 ERR_CSR_VERIFY_SIGNATURE_CANNOT_GET_SIGNATURE_VERIFIER.get( 1184 getSignatureAlgorithmNameOrOID(), 1185 StaticUtils.getExceptionMessage(e)), 1186 e); 1187 } 1188 1189 try 1190 { 1191 signature.initVerify(publicKey); 1192 } 1193 catch (final Exception e) 1194 { 1195 Debug.debugException(e); 1196 throw new CertException( 1197 ERR_CSR_VERIFY_SIGNATURE_CANNOT_INIT_SIGNATURE_VERIFIER.get( 1198 signatureAlgorithm.getJavaName(), 1199 StaticUtils.getExceptionMessage(e)), 1200 e); 1201 } 1202 1203 1204 // Construct the requestInfo element of the certificate signing request and 1205 // compute its signature. 1206 final boolean signatureIsValid; 1207 try 1208 { 1209 final ASN1Element[] requestInfoElements = 1210 ASN1Sequence.decodeAsSequence( 1211 pkcs10CertificateSigningRequestBytes).elements(); 1212 final byte[] requestInfoBytes = requestInfoElements[0].encode(); 1213 signature.update(requestInfoBytes); 1214 signatureIsValid = signature.verify(signatureValue.getBytes()); 1215 } 1216 catch (final Exception e) 1217 { 1218 Debug.debugException(e); 1219 throw new CertException( 1220 ERR_CSR_VERIFY_SIGNATURE_ERROR.get(subjectDN, 1221 StaticUtils.getExceptionMessage(e)), 1222 e); 1223 } 1224 1225 if (! signatureIsValid) 1226 { 1227 throw new CertException( 1228 ERR_CSR_VERIFY_SIGNATURE_NOT_VALID.get(subjectDN)); 1229 } 1230 } 1231 1232 1233 1234 /** 1235 * Retrieves a string representation of the decoded X.509 certificate. 1236 * 1237 * @return A string representation of the decoded X.509 certificate. 1238 */ 1239 @Override() 1240 public String toString() 1241 { 1242 final StringBuilder buffer = new StringBuilder(); 1243 toString(buffer); 1244 return buffer.toString(); 1245 } 1246 1247 1248 1249 /** 1250 * Appends a string representation of the decoded X.509 certificate to the 1251 * provided buffer. 1252 * 1253 * @param buffer The buffer to which the information should be appended. 1254 */ 1255 public void toString(final StringBuilder buffer) 1256 { 1257 buffer.append("PKCS10CertificateSigningRequest(version='"); 1258 buffer.append(version.getName()); 1259 buffer.append("', subjectDN='"); 1260 buffer.append(subjectDN); 1261 buffer.append("', publicKeyAlgorithmOID='"); 1262 buffer.append(publicKeyAlgorithmOID.toString()); 1263 buffer.append('\''); 1264 1265 if (publicKeyAlgorithmName != null) 1266 { 1267 buffer.append(", publicKeyAlgorithmName='"); 1268 buffer.append(publicKeyAlgorithmName); 1269 buffer.append('\''); 1270 } 1271 1272 buffer.append(", subjectPublicKey="); 1273 if (decodedPublicKey == null) 1274 { 1275 buffer.append('\''); 1276 1277 try 1278 { 1279 StaticUtils.toHex(encodedPublicKey.getBytes(), ":", buffer); 1280 } 1281 catch (final Exception e) 1282 { 1283 Debug.debugException(e); 1284 encodedPublicKey.toString(buffer); 1285 } 1286 1287 buffer.append('\''); 1288 } 1289 else 1290 { 1291 decodedPublicKey.toString(buffer); 1292 1293 if (decodedPublicKey instanceof EllipticCurvePublicKey) 1294 { 1295 try 1296 { 1297 final OID namedCurveOID = 1298 publicKeyAlgorithmParameters.decodeAsObjectIdentifier().getOID(); 1299 buffer.append(", ellipticCurvePublicKeyParameters=namedCurve='"); 1300 buffer.append(NamedCurve.getNameOrOID(namedCurveOID)); 1301 buffer.append('\''); 1302 } 1303 catch (final Exception e) 1304 { 1305 Debug.debugException(e); 1306 } 1307 } 1308 } 1309 1310 buffer.append(", signatureAlgorithmOID='"); 1311 buffer.append(signatureAlgorithmOID.toString()); 1312 buffer.append('\''); 1313 1314 if (signatureAlgorithmName != null) 1315 { 1316 buffer.append(", signatureAlgorithmName='"); 1317 buffer.append(signatureAlgorithmName); 1318 buffer.append('\''); 1319 } 1320 1321 if (! extensions.isEmpty()) 1322 { 1323 buffer.append(", extensions={"); 1324 1325 final Iterator<X509CertificateExtension> iterator = extensions.iterator(); 1326 while (iterator.hasNext()) 1327 { 1328 iterator.next().toString(buffer); 1329 if (iterator.hasNext()) 1330 { 1331 buffer.append(", "); 1332 } 1333 } 1334 1335 buffer.append('}'); 1336 } 1337 1338 buffer.append(", signatureValue='"); 1339 1340 try 1341 { 1342 StaticUtils.toHex(signatureValue.getBytes(), ":", buffer); 1343 } 1344 catch (final Exception e) 1345 { 1346 Debug.debugException(e); 1347 buffer.append(signatureValue.toString()); 1348 } 1349 1350 buffer.append("')"); 1351 } 1352 1353 1354 1355 /** 1356 * Retrieves a list of the lines that comprise a PEM representation of this 1357 * PKCS #10 certificate signing request. 1358 * 1359 * @return A list of the lines that comprise a PEM representation of this 1360 * PKCS #10 certificate signing request. 1361 */ 1362 public List<String> toPEM() 1363 { 1364 final ArrayList<String> lines = new ArrayList<>(10); 1365 lines.add("-----BEGIN CERTIFICATE REQUEST-----"); 1366 1367 final String csrBase64 = 1368 Base64.encode(pkcs10CertificateSigningRequestBytes); 1369 lines.addAll(StaticUtils.wrapLine(csrBase64, 64)); 1370 1371 lines.add("-----END CERTIFICATE REQUEST-----"); 1372 1373 return Collections.unmodifiableList(lines); 1374 } 1375 1376 1377 1378 /** 1379 * Retrieves a multi-line string containing a PEM representation of this 1380 * PKCS #10 certificate signing request. 1381 * 1382 * @return A multi-line string containing a PEM representation of this 1383 * PKCS #10 certificate signing request. 1384 */ 1385 public String toPEMString() 1386 { 1387 final StringBuilder buffer = new StringBuilder(); 1388 buffer.append("-----BEGIN CERTIFICATE REQUEST-----"); 1389 buffer.append(StaticUtils.EOL); 1390 1391 final String csrBase64 = 1392 Base64.encode(pkcs10CertificateSigningRequestBytes); 1393 for (final String line : StaticUtils.wrapLine(csrBase64, 64)) 1394 { 1395 buffer.append(line); 1396 buffer.append(StaticUtils.EOL); 1397 } 1398 buffer.append("-----END CERTIFICATE REQUEST-----"); 1399 buffer.append(StaticUtils.EOL); 1400 1401 return buffer.toString(); 1402 } 1403}