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