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}