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}