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