001/*
002 * Copyright 2017-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2017-2019 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.math.BigInteger;
026import java.util.ArrayList;
027import java.util.Collections;
028import java.util.Iterator;
029import java.util.List;
030
031import com.unboundid.asn1.ASN1BigInteger;
032import com.unboundid.asn1.ASN1Element;
033import com.unboundid.asn1.ASN1Integer;
034import com.unboundid.asn1.ASN1OctetString;
035import com.unboundid.asn1.ASN1Sequence;
036import com.unboundid.util.Debug;
037import com.unboundid.util.NotMutable;
038import com.unboundid.util.StaticUtils;
039import com.unboundid.util.ThreadSafety;
040import com.unboundid.util.ThreadSafetyLevel;
041
042import static com.unboundid.util.ssl.cert.CertMessages.*;
043
044
045
046/**
047 * This class provides a data structure for representing the information
048 * contained in an RSA private key.  As per
049 * <A HREF="https://www.ietf.org/rfc/rfc8017.txt">RFC 8017</A> section A.1.2,
050 * an RSA private key is identified by OID 1.2.840.113549.1.1.1 and the value is
051 * encoded as follows:
052 * <PRE>
053 *   RSAPrivateKey ::= SEQUENCE {
054 *       version           Version,
055 *       modulus           INTEGER,  -- n
056 *       publicExponent    INTEGER,  -- e
057 *       privateExponent   INTEGER,  -- d
058 *       prime1            INTEGER,  -- p
059 *       prime2            INTEGER,  -- q
060 *       exponent1         INTEGER,  -- d mod (p-1)
061 *       exponent2         INTEGER,  -- d mod (q-1)
062 *       coefficient       INTEGER,  -- (inverse of q) mod p
063 *       otherPrimeInfos   OtherPrimeInfos OPTIONAL
064 *   }
065 *
066 *   OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
067 *
068 *   OtherPrimeInfo ::= SEQUENCE {
069 *       prime             INTEGER,  -- ri
070 *       exponent          INTEGER,  -- di
071 *       coefficient       INTEGER   -- ti
072 *   }
073 * </PRE>
074 */
075@NotMutable()
076@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
077public final class RSAPrivateKey
078       extends DecodedPrivateKey
079{
080  /**
081   * The serial version UID for this serializable class.
082   */
083  private static final long serialVersionUID = -7101141316095373904L;
084
085
086
087  // The coefficient value for the RSA private key.
088  private final BigInteger coefficient;
089
090  // The exponent1 value for the RSA private key.
091  private final BigInteger exponent1;
092
093  // The exponent2 value for the RSA private key.
094  private final BigInteger exponent2;
095
096  // The modulus for the RSA private key.
097  private final BigInteger modulus;
098
099  // The prime1 value for the RSA private key.
100  private final BigInteger prime1;
101
102  // The prime2 value for the RSA private key.
103  private final BigInteger prime2;
104
105  // The private exponent for the RSA private key.
106  private final BigInteger privateExponent;
107
108  // The public exponent for the RSA private key.
109  private final BigInteger publicExponent;
110
111  // A list of information about additional primes used by the RSA private key.
112  private final List<BigInteger[]> otherPrimeInfos;
113
114  // The private key version.
115  private final RSAPrivateKeyVersion version;
116
117
118
119  /**
120   * Creates a new RSA private key with the provided information.
121   *
122   * @param  version          The version for this private key.  It must not be
123   *                          {@code null}.
124   * @param  modulus          The modulus for this RSA private key.  It must not
125   *                          be {@code null}.
126   * @param  publicExponent   The public exponent for this RSA private key.  It
127   *                          must not be {@code null}.
128   * @param  privateExponent  The private exponent for this RSA private key.  It
129   *                          must not be {@code null}.
130   * @param  prime1           The prime1 value for this RSA private key.  It
131   *                          must not be {@code null}.
132   * @param  prime2           The prime2 value for this RSA private key.  It
133   *                          must not be {@code null}.
134   * @param  exponent1        The exponent1 value for this RSA private key.  It
135   *                          must not be {@code null}.
136   * @param  exponent2        The exponent2 value for this RSA private key.  It
137   *                          must not be {@code null}.
138   * @param  coefficient      The coefficient for this RSA private key. It must
139   *                          not be {@code null}.
140   * @param  otherPrimeInfos  A list of information about additional primes used
141   *                          by the private key.  It must not be {@code null},
142   *                          but may be empty.  If it is non-empty, then each
143   *                          array must contain three items, which represent a
144   *                          prime, an exponent, and a coefficient,
145   *                          respectively.
146   */
147  RSAPrivateKey(final RSAPrivateKeyVersion version, final BigInteger modulus,
148                final BigInteger publicExponent,
149                final BigInteger privateExponent, final BigInteger prime1,
150                final BigInteger prime2, final BigInteger exponent1,
151                final BigInteger exponent2, final BigInteger coefficient,
152                final List<BigInteger[]> otherPrimeInfos)
153  {
154    this.version = version;
155    this.modulus = modulus;
156    this.publicExponent = publicExponent;
157    this.privateExponent = privateExponent;
158    this.prime1 = prime1;
159    this.prime2 = prime2;
160    this.exponent1 = exponent1;
161    this.exponent2 = exponent2;
162    this.coefficient = coefficient;
163    this.otherPrimeInfos = otherPrimeInfos;
164  }
165
166
167
168  /**
169   * Creates a new RSA decoded private key from the provided octet string.
170   *
171   * @param  encodedPrivateKey  The encoded private key to be decoded as an RSA
172   *                            private key.
173   *
174   * @throws  CertException  If the provided private key cannot be decoded as an
175   *                         RSA private key.
176   */
177  RSAPrivateKey(final ASN1OctetString encodedPrivateKey)
178       throws CertException
179  {
180    try
181    {
182      final ASN1Element[] elements = ASN1Sequence.decodeAsSequence(
183           encodedPrivateKey.getValue()).elements();
184      final int versionIntValue = elements[0].decodeAsInteger().intValue();
185      version = RSAPrivateKeyVersion.valueOf(versionIntValue);
186      if (version == null)
187      {
188        throw new CertException(
189             ERR_RSA_PRIVATE_KEY_UNSUPPORTED_VERSION.get(versionIntValue));
190      }
191
192      modulus = elements[1].decodeAsBigInteger().getBigIntegerValue();
193      publicExponent = elements[2].decodeAsBigInteger().getBigIntegerValue();
194      privateExponent = elements[3].decodeAsBigInteger().getBigIntegerValue();
195      prime1 = elements[4].decodeAsBigInteger().getBigIntegerValue();
196      prime2 = elements[5].decodeAsBigInteger().getBigIntegerValue();
197      exponent1 = elements[6].decodeAsBigInteger().getBigIntegerValue();
198      exponent2 = elements[7].decodeAsBigInteger().getBigIntegerValue();
199      coefficient = elements[8].decodeAsBigInteger().getBigIntegerValue();
200
201      if (elements.length == 9)
202      {
203        otherPrimeInfos = Collections.emptyList();
204      }
205      else
206      {
207        final ASN1Element[] otherPrimesElements =
208             elements[9].decodeAsSequence().elements();
209        final ArrayList<BigInteger[]> otherPrimes =
210             new ArrayList<>(otherPrimesElements.length);
211        for (final ASN1Element e : otherPrimesElements)
212        {
213          final ASN1Element[] primeElements = e.decodeAsSequence().elements();
214          otherPrimes.add(
215               new BigInteger[]
216               {
217                 primeElements[0].decodeAsBigInteger().getBigIntegerValue(),
218                 primeElements[1].decodeAsBigInteger().getBigIntegerValue(),
219                 primeElements[2].decodeAsBigInteger().getBigIntegerValue()
220               });
221        }
222
223        otherPrimeInfos = Collections.unmodifiableList(otherPrimes);
224      }
225    }
226    catch (final CertException e)
227    {
228      Debug.debugException(e);
229      throw e;
230    }
231    catch (final Exception e)
232    {
233      Debug.debugException(e);
234      throw new CertException(
235           ERR_RSA_PRIVATE_KEY_CANNOT_DECODE.get(
236                StaticUtils.getExceptionMessage(e)),
237           e);
238    }
239  }
240
241
242
243  /**
244   * Encodes this RSA private key to an ASN.1 octet string.
245   *
246   * @return  The ASN.1 octet string containing the encoded private key.
247   */
248  ASN1OctetString encode()
249  {
250    final ArrayList<ASN1Element> elements = new ArrayList<>(9);
251    elements.add(new ASN1Integer(version.getIntValue()));
252    elements.add(new ASN1BigInteger(modulus));
253    elements.add(new ASN1BigInteger(publicExponent));
254    elements.add(new ASN1BigInteger(privateExponent));
255    elements.add(new ASN1BigInteger(prime1));
256    elements.add(new ASN1BigInteger(prime2));
257    elements.add(new ASN1BigInteger(exponent1));
258    elements.add(new ASN1BigInteger(exponent2));
259    elements.add(new ASN1BigInteger(coefficient));
260
261    if (! otherPrimeInfos.isEmpty())
262    {
263      final ArrayList<ASN1Element> otherElements =
264           new ArrayList<>(otherPrimeInfos.size());
265      for (final BigInteger[] info : otherPrimeInfos)
266      {
267        otherElements.add(new ASN1Sequence(
268             new ASN1BigInteger(info[0]),
269             new ASN1BigInteger(info[1]),
270             new ASN1BigInteger(info[2])));
271      }
272
273      elements.add(new ASN1Sequence(otherElements));
274    }
275
276    return new ASN1OctetString(new ASN1Sequence(elements).encode());
277  }
278
279
280
281  /**
282   * Retrieves the version for the RSA private key.
283   *
284   * @return  The version for the RSA private key.
285   */
286  public RSAPrivateKeyVersion getVersion()
287  {
288    return version;
289  }
290
291
292
293  /**
294   * Retrieves the modulus (n) for the RSA private key.
295   *
296   * @return  The modulus for the RSA private key.
297   */
298  public BigInteger getModulus()
299  {
300    return modulus;
301  }
302
303
304
305  /**
306   * Retrieves the public exponent (e) for the RSA public key.
307   *
308   * @return  The public exponent for the RSA public key.
309   */
310  public BigInteger getPublicExponent()
311  {
312    return publicExponent;
313  }
314
315
316
317  /**
318   * Retrieves the private exponent (d) for the RSA private key.
319   *
320   * @return  The private exponent for the RSA private key.
321   */
322  public BigInteger getPrivateExponent()
323  {
324    return privateExponent;
325  }
326
327
328
329  /**
330   * Retrieves the prime1 (p) value for the RSA private key.
331   *
332   * @return  The prime1 value for the RSA private key.
333   */
334  public BigInteger getPrime1()
335  {
336    return prime1;
337  }
338
339
340
341  /**
342   * Retrieves the prime2 (q) value for the RSA private key.
343   *
344   * @return  The prime2 value for the RSA private key.
345   */
346  public BigInteger getPrime2()
347  {
348    return prime2;
349  }
350
351
352
353  /**
354   * Retrieves the exponent1 value for the RSA private key.
355   *
356   * @return  The exponent1 value for the RSA private key.
357   */
358  public BigInteger getExponent1()
359  {
360    return exponent1;
361  }
362
363
364
365  /**
366   * Retrieves the exponent2 value for the RSA private key.
367   *
368   * @return  The exponent2 value for the RSA private key.
369   */
370  public BigInteger getExponent2()
371  {
372    return exponent2;
373  }
374
375
376
377  /**
378   * Retrieves the coefficient for the RSA private key.
379   *
380   * @return  The coefficient for the RSA private key.
381   */
382  public BigInteger getCoefficient()
383  {
384    return coefficient;
385  }
386
387
388
389  /**
390   * Retrieves a list of information about other primes used by the private key.
391   * If the list is non-empty, then each item will be an array of three
392   * {@code BigInteger} values, which represent a prime, an exponent, and a
393   * coefficient, respectively.
394   *
395   * @return  A list of information about other primes used by the private key.
396   */
397  public List<BigInteger[]> getOtherPrimeInfos()
398  {
399    return otherPrimeInfos;
400  }
401
402
403
404  /**
405   * {@inheritDoc}
406   */
407  @Override()
408  public void toString(final StringBuilder buffer)
409  {
410    buffer.append("RSAPrivateKey(version='");
411    buffer.append(version.getName());
412    buffer.append("', modulus=");
413    StaticUtils.toHex(modulus.toByteArray(), ":", buffer);
414    buffer.append(", publicExponent=");
415    StaticUtils.toHex(publicExponent.toByteArray(), ":", buffer);
416    buffer.append(", privateExponent=");
417    StaticUtils.toHex(privateExponent.toByteArray(), ":", buffer);
418    buffer.append(", prime1=");
419    StaticUtils.toHex(prime1.toByteArray(), ":", buffer);
420    buffer.append(", prime2=");
421    StaticUtils.toHex(prime2.toByteArray(), ":", buffer);
422    buffer.append(", exponent1=");
423    StaticUtils.toHex(exponent1.toByteArray(), ":", buffer);
424    buffer.append(", exponent2=");
425    StaticUtils.toHex(exponent2.toByteArray(), ":", buffer);
426    buffer.append(", coefficient=");
427    StaticUtils.toHex(coefficient.toByteArray(), ":", buffer);
428
429    if (! otherPrimeInfos.isEmpty())
430    {
431      buffer.append(", otherPrimeInfos={");
432
433      final Iterator<BigInteger[]> iterator = otherPrimeInfos.iterator();
434      while (iterator.hasNext())
435      {
436        final BigInteger[] array = iterator.next();
437        buffer.append("PrimeInfo(prime=");
438        StaticUtils.toHex(array[0].toByteArray(), ":", buffer);
439        buffer.append(", exponent=");
440        StaticUtils.toHex(array[1].toByteArray(), ":", buffer);
441        buffer.append(", coefficient=");
442        StaticUtils.toHex(array[2].toByteArray(), ":", buffer);
443        buffer.append(')');
444
445        if (iterator.hasNext())
446        {
447          buffer.append(", ");
448        }
449      }
450
451      buffer.append('}');
452    }
453
454    buffer.append(')');
455  }
456}