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