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