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