1 /* 2 * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.x509; 27 28 import java.io.BufferedReader; 29 import java.io.BufferedInputStream; 30 import java.io.ByteArrayOutputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.io.InputStreamReader; 34 import java.io.OutputStream; 35 import java.math.BigInteger; 36 import java.security.*; 37 import java.security.spec.AlgorithmParameterSpec; 38 import java.security.cert.*; 39 import java.security.cert.Certificate; 40 import java.util.*; 41 import java.util.concurrent.ConcurrentHashMap; 42 43 import javax.security.auth.x500.X500Principal; 44 45 import java.util.Base64; 46 import sun.security.util.*; 47 import sun.security.provider.X509Factory; 48 49 /** 50 * The X509CertImpl class represents an X.509 certificate. These certificates 51 * are widely used to support authentication and other functionality in 52 * Internet security systems. Common applications include Privacy Enhanced 53 * Mail (PEM), Transport Layer Security (SSL), code signing for trusted 54 * software distribution, and Secure Electronic Transactions (SET). There 55 * is a commercial infrastructure ready to manage large scale deployments 56 * of X.509 identity certificates. 57 * 58 * <P>These certificates are managed and vouched for by <em>Certificate 59 * Authorities</em> (CAs). CAs are services which create certificates by 60 * placing data in the X.509 standard format and then digitally signing 61 * that data. Such signatures are quite difficult to forge. CAs act as 62 * trusted third parties, making introductions between agents who have no 63 * direct knowledge of each other. CA certificates are either signed by 64 * themselves, or by some other CA such as a "root" CA. 65 * 66 * <P>RFC 1422 is very informative, though it does not describe much 67 * of the recent work being done with X.509 certificates. That includes 68 * a 1996 version (X.509v3) and a variety of enhancements being made to 69 * facilitate an explosion of personal certificates used as "Internet 70 * Drivers' Licences", or with SET for credit card transactions. 71 * 72 * <P>More recent work includes the IETF PKIX Working Group efforts, 73 * especially RFC2459. 74 * 75 * @author Dave Brownell 76 * @author Amit Kapoor 77 * @author Hemma Prafullchandra 78 * @see X509CertInfo 79 */ 80 public class X509CertImpl extends X509Certificate implements DerEncoder { 81 82 private static final long serialVersionUID = -3457612960190864406L; 83 84 private static final char DOT = '.'; 85 /** 86 * Public attribute names. 87 */ 88 public static final String NAME = "x509"; 89 public static final String INFO = X509CertInfo.NAME; 90 public static final String ALG_ID = "algorithm"; 91 public static final String SIGNATURE = "signature"; 92 public static final String SIGNED_CERT = "signed_cert"; 93 94 /** 95 * The following are defined for ease-of-use. These 96 * are the most frequently retrieved attributes. 97 */ 98 // x509.info.subject.dname 99 public static final String SUBJECT_DN = NAME + DOT + INFO + DOT + 100 X509CertInfo.SUBJECT + DOT + X509CertInfo.DN_NAME; 101 // x509.info.issuer.dname 102 public static final String ISSUER_DN = NAME + DOT + INFO + DOT + 103 X509CertInfo.ISSUER + DOT + X509CertInfo.DN_NAME; 104 // x509.info.serialNumber.number 105 public static final String SERIAL_ID = NAME + DOT + INFO + DOT + 106 X509CertInfo.SERIAL_NUMBER + DOT + 107 CertificateSerialNumber.NUMBER; 108 // x509.info.key.value 109 public static final String PUBLIC_KEY = NAME + DOT + INFO + DOT + 110 X509CertInfo.KEY + DOT + 111 CertificateX509Key.KEY; 112 113 // x509.info.version.value 114 public static final String VERSION = NAME + DOT + INFO + DOT + 115 X509CertInfo.VERSION + DOT + 116 CertificateVersion.VERSION; 117 118 // x509.algorithm 119 public static final String SIG_ALG = NAME + DOT + ALG_ID; 120 121 // x509.signature 122 public static final String SIG = NAME + DOT + SIGNATURE; 123 124 // when we sign and decode we set this to true 125 // this is our means to make certificates immutable 126 private boolean readOnly = false; 127 128 // Certificate data, and its envelope 129 private byte[] signedCert = null; 130 protected X509CertInfo info = null; 131 protected AlgorithmId algId = null; 132 protected byte[] signature = null; 133 134 // recognized extension OIDS 135 private static final String KEY_USAGE_OID = "2.5.29.15"; 136 private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37"; 137 private static final String BASIC_CONSTRAINT_OID = "2.5.29.19"; 138 private static final String SUBJECT_ALT_NAME_OID = "2.5.29.17"; 139 private static final String ISSUER_ALT_NAME_OID = "2.5.29.18"; 140 private static final String AUTH_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.1"; 141 142 // number of standard key usage bits. 143 private static final int NUM_STANDARD_KEY_USAGE = 9; 144 145 // SubjectAlterntativeNames cache 146 private Collection<List<?>> subjectAlternativeNames; 147 148 // IssuerAlternativeNames cache 149 private Collection<List<?>> issuerAlternativeNames; 150 151 // ExtendedKeyUsage cache 152 private List<String> extKeyUsage; 153 154 // AuthorityInformationAccess cache 155 private Set<AccessDescription> authInfoAccess; 156 157 /** 158 * PublicKey that has previously been used to verify 159 * the signature of this certificate. Null if the certificate has not 160 * yet been verified. 161 */ 162 private PublicKey verifiedPublicKey; 163 /** 164 * If verifiedPublicKey is not null, name of the provider used to 165 * successfully verify the signature of this certificate, or the 166 * empty String if no provider was explicitly specified. 167 */ 168 private String verifiedProvider; 169 /** 170 * If verifiedPublicKey is not null, result of the verification using 171 * verifiedPublicKey and verifiedProvider. If true, verification was 172 * successful, if false, it failed. 173 */ 174 private boolean verificationResult; 175 176 /** 177 * Default constructor. 178 */ 179 public X509CertImpl() { } 180 181 /** 182 * Unmarshals a certificate from its encoded form, parsing the 183 * encoded bytes. This form of constructor is used by agents which 184 * need to examine and use certificate contents. That is, this is 185 * one of the more commonly used constructors. Note that the buffer 186 * must include only a certificate, and no "garbage" may be left at 187 * the end. If you need to ignore data at the end of a certificate, 188 * use another constructor. 189 * 190 * @param certData the encoded bytes, with no trailing padding. 191 * @exception CertificateException on parsing and initialization errors. 192 */ 193 public X509CertImpl(byte[] certData) throws CertificateException { 194 try { 195 parse(new DerValue(certData)); 196 } catch (IOException e) { 197 signedCert = null; 198 throw new CertificateException("Unable to initialize, " + e, e); 199 } 200 } 201 202 /** 203 * unmarshals an X.509 certificate from an input stream. If the 204 * certificate is RFC1421 hex-encoded, then it must begin with 205 * the line X509Factory.BEGIN_CERT and end with the line 206 * X509Factory.END_CERT. 207 * 208 * @param in an input stream holding at least one certificate that may 209 * be either DER-encoded or RFC1421 hex-encoded version of the 210 * DER-encoded certificate. 211 * @exception CertificateException on parsing and initialization errors. 212 */ 213 public X509CertImpl(InputStream in) throws CertificateException { 214 215 DerValue der = null; 216 217 BufferedInputStream inBuffered = new BufferedInputStream(in); 218 219 // First try reading stream as HEX-encoded DER-encoded bytes, 220 // since not mistakable for raw DER 221 try { 222 inBuffered.mark(Integer.MAX_VALUE); 223 der = readRFC1421Cert(inBuffered); 224 } catch (IOException ioe) { 225 try { 226 // Next, try reading stream as raw DER-encoded bytes 227 inBuffered.reset(); 228 der = new DerValue(inBuffered); 229 } catch (IOException ioe1) { 230 throw new CertificateException("Input stream must be " + 231 "either DER-encoded bytes " + 232 "or RFC1421 hex-encoded " + 233 "DER-encoded bytes: " + 234 ioe1.getMessage(), ioe1); 235 } 236 } 237 try { 238 parse(der); 239 } catch (IOException ioe) { 240 signedCert = null; 241 throw new CertificateException("Unable to parse DER value of " + 242 "certificate, " + ioe, ioe); 243 } 244 } 245 246 /** 247 * read input stream as HEX-encoded DER-encoded bytes 248 * 249 * @param in InputStream to read 250 * @return DerValue corresponding to decoded HEX-encoded bytes 251 * @throws IOException if stream can not be interpreted as RFC1421 252 * encoded bytes 253 */ 254 private DerValue readRFC1421Cert(InputStream in) throws IOException { 255 DerValue der = null; 256 String line = null; 257 BufferedReader certBufferedReader = 258 new BufferedReader(new InputStreamReader(in, "ASCII")); 259 try { 260 line = certBufferedReader.readLine(); 261 } catch (IOException ioe1) { 262 throw new IOException("Unable to read InputStream: " + 263 ioe1.getMessage()); 264 } 265 if (line.equals(X509Factory.BEGIN_CERT)) { 266 /* stream appears to be hex-encoded bytes */ 267 ByteArrayOutputStream decstream = new ByteArrayOutputStream(); 268 try { 269 while ((line = certBufferedReader.readLine()) != null) { 270 if (line.equals(X509Factory.END_CERT)) { 271 der = new DerValue(decstream.toByteArray()); 272 break; 273 } else { 274 decstream.write(Pem.decode(line)); 275 } 276 } 277 } catch (IOException ioe2) { 278 throw new IOException("Unable to read InputStream: " 279 + ioe2.getMessage()); 280 } 281 } else { 282 throw new IOException("InputStream is not RFC1421 hex-encoded " + 283 "DER bytes"); 284 } 285 return der; 286 } 287 288 /** 289 * Construct an initialized X509 Certificate. The certificate is stored 290 * in raw form and has to be signed to be useful. 291 * 292 * @param certInfo the X509CertificateInfo which the Certificate is to be 293 * created from. 294 */ 295 public X509CertImpl(X509CertInfo certInfo) { 296 this.info = certInfo; 297 } 298 299 /** 300 * Unmarshal a certificate from its encoded form, parsing a DER value. 301 * This form of constructor is used by agents which need to examine 302 * and use certificate contents. 303 * 304 * @param derVal the der value containing the encoded cert. 305 * @exception CertificateException on parsing and initialization errors. 306 */ 307 public X509CertImpl(DerValue derVal) throws CertificateException { 308 try { 309 parse(derVal); 310 } catch (IOException e) { 311 signedCert = null; 312 throw new CertificateException("Unable to initialize, " + e, e); 313 } 314 } 315 316 /** 317 * Appends the certificate to an output stream. 318 * 319 * @param out an input stream to which the certificate is appended. 320 * @exception CertificateEncodingException on encoding errors. 321 */ 322 public void encode(OutputStream out) 323 throws CertificateEncodingException { 324 if (signedCert == null) 325 throw new CertificateEncodingException( 326 "Null certificate to encode"); 327 try { 328 out.write(signedCert.clone()); 329 } catch (IOException e) { 330 throw new CertificateEncodingException(e.toString()); 331 } 332 } 333 334 /** 335 * DER encode this object onto an output stream. 336 * Implements the <code>DerEncoder</code> interface. 337 * 338 * @param out the output stream on which to write the DER encoding. 339 * 340 * @exception IOException on encoding error. 341 */ 342 public void derEncode(OutputStream out) throws IOException { 343 if (signedCert == null) 344 throw new IOException("Null certificate to encode"); 345 out.write(signedCert.clone()); 346 } 347 348 /** 349 * Returns the encoded form of this certificate. It is 350 * assumed that each certificate type would have only a single 351 * form of encoding; for example, X.509 certificates would 352 * be encoded as ASN.1 DER. 353 * 354 * @exception CertificateEncodingException if an encoding error occurs. 355 */ 356 public byte[] getEncoded() throws CertificateEncodingException { 357 return getEncodedInternal().clone(); 358 } 359 360 /** 361 * Returned the encoding as an uncloned byte array. Callers must 362 * guarantee that they neither modify it nor expose it to untrusted 363 * code. 364 */ 365 public byte[] getEncodedInternal() throws CertificateEncodingException { 366 if (signedCert == null) { 367 throw new CertificateEncodingException( 368 "Null certificate to encode"); 369 } 370 return signedCert; 371 } 372 373 /** 374 * Throws an exception if the certificate was not signed using the 375 * verification key provided. Successfully verifying a certificate 376 * does <em>not</em> indicate that one should trust the entity which 377 * it represents. 378 * 379 * @param key the public key used for verification. 380 * 381 * @exception InvalidKeyException on incorrect key. 382 * @exception NoSuchAlgorithmException on unsupported signature 383 * algorithms. 384 * @exception NoSuchProviderException if there's no default provider. 385 * @exception SignatureException on signature errors. 386 * @exception CertificateException on encoding errors. 387 */ 388 public void verify(PublicKey key) 389 throws CertificateException, NoSuchAlgorithmException, 390 InvalidKeyException, NoSuchProviderException, SignatureException { 391 verify(key, ""); 392 } 393 394 /** 395 * Throws an exception if the certificate was not signed using the 396 * verification key provided. Successfully verifying a certificate 397 * does <em>not</em> indicate that one should trust the entity which 398 * it represents. 399 * 400 * @param key the public key used for verification. 401 * @param sigProvider the name of the provider. 402 * 403 * @exception NoSuchAlgorithmException on unsupported signature 404 * algorithms. 405 * @exception InvalidKeyException on incorrect key. 406 * @exception NoSuchProviderException on incorrect provider. 407 * @exception SignatureException on signature errors. 408 * @exception CertificateException on encoding errors. 409 */ 410 public synchronized void verify(PublicKey key, String sigProvider) 411 throws CertificateException, NoSuchAlgorithmException, 412 InvalidKeyException, NoSuchProviderException, SignatureException { 413 if (sigProvider == null) { 414 sigProvider = ""; 415 } 416 if ((verifiedPublicKey != null) && verifiedPublicKey.equals(key)) { 417 // this certificate has already been verified using 418 // this public key. Make sure providers match, too. 419 if (sigProvider.equals(verifiedProvider)) { 420 if (verificationResult) { 421 return; 422 } else { 423 throw new SignatureException("Signature does not match."); 424 } 425 } 426 } 427 if (signedCert == null) { 428 throw new CertificateEncodingException("Uninitialized certificate"); 429 } 430 // Verify the signature ... 431 Signature sigVerf = null; 432 if (sigProvider.isEmpty()) { 433 sigVerf = Signature.getInstance(algId.getName()); 434 } else { 435 sigVerf = Signature.getInstance(algId.getName(), sigProvider); 436 } 437 438 sigVerf.initVerify(key); 439 440 // set parameters after Signature.initSign/initVerify call, 441 // so the deferred provider selection happens when key is set 442 try { 443 SignatureUtil.specialSetParameter(sigVerf, getSigAlgParams()); 444 } catch (ProviderException e) { 445 throw new CertificateException(e.getMessage(), e.getCause()); 446 } catch (InvalidAlgorithmParameterException e) { 447 throw new CertificateException(e); 448 } 449 450 byte[] rawCert = info.getEncodedInfo(); 451 sigVerf.update(rawCert, 0, rawCert.length); 452 453 // verify may throw SignatureException for invalid encodings, etc. 454 verificationResult = sigVerf.verify(signature); 455 verifiedPublicKey = key; 456 verifiedProvider = sigProvider; 457 458 if (verificationResult == false) { 459 throw new SignatureException("Signature does not match."); 460 } 461 } 462 463 /** 464 * Throws an exception if the certificate was not signed using the 465 * verification key provided. This method uses the signature verification 466 * engine supplied by the specified provider. Note that the specified 467 * Provider object does not have to be registered in the provider list. 468 * Successfully verifying a certificate does <em>not</em> indicate that one 469 * should trust the entity which it represents. 470 * 471 * @param key the public key used for verification. 472 * @param sigProvider the provider. 473 * 474 * @exception NoSuchAlgorithmException on unsupported signature 475 * algorithms. 476 * @exception InvalidKeyException on incorrect key. 477 * @exception SignatureException on signature errors. 478 * @exception CertificateException on encoding errors. 479 */ 480 public synchronized void verify(PublicKey key, Provider sigProvider) 481 throws CertificateException, NoSuchAlgorithmException, 482 InvalidKeyException, SignatureException { 483 if (signedCert == null) { 484 throw new CertificateEncodingException("Uninitialized certificate"); 485 } 486 // Verify the signature ... 487 Signature sigVerf = null; 488 if (sigProvider == null) { 489 sigVerf = Signature.getInstance(algId.getName()); 490 } else { 491 sigVerf = Signature.getInstance(algId.getName(), sigProvider); 492 } 493 494 sigVerf.initVerify(key); 495 496 // set parameters after Signature.initSign/initVerify call, 497 // so the deferred provider selection happens when key is set 498 try { 499 SignatureUtil.specialSetParameter(sigVerf, getSigAlgParams()); 500 } catch (ProviderException e) { 501 throw new CertificateException(e.getMessage(), e.getCause()); 502 } catch (InvalidAlgorithmParameterException e) { 503 throw new CertificateException(e); 504 } 505 506 byte[] rawCert = info.getEncodedInfo(); 507 sigVerf.update(rawCert, 0, rawCert.length); 508 509 // verify may throw SignatureException for invalid encodings, etc. 510 verificationResult = sigVerf.verify(signature); 511 verifiedPublicKey = key; 512 513 if (verificationResult == false) { 514 throw new SignatureException("Signature does not match."); 515 } 516 } 517 518 /** 519 * Creates an X.509 certificate, and signs it using the given key 520 * (associating a signature algorithm and an X.500 name). 521 * This operation is used to implement the certificate generation 522 * functionality of a certificate authority. 523 * 524 * @param key the private key used for signing. 525 * @param algorithm the name of the signature algorithm used. 526 * 527 * @exception InvalidKeyException on incorrect key. 528 * @exception NoSuchAlgorithmException on unsupported signature 529 * algorithms. 530 * @exception NoSuchProviderException if there's no default provider. 531 * @exception SignatureException on signature errors. 532 * @exception CertificateException on encoding errors. 533 */ 534 public void sign(PrivateKey key, String algorithm) 535 throws CertificateException, NoSuchAlgorithmException, 536 InvalidKeyException, NoSuchProviderException, SignatureException { 537 sign(key, algorithm, null); 538 } 539 540 /** 541 * Creates an X.509 certificate, and signs it using the given key 542 * (associating a signature algorithm and an X.500 name). 543 * This operation is used to implement the certificate generation 544 * functionality of a certificate authority. 545 * 546 * @param key the private key used for signing. 547 * @param algorithm the name of the signature algorithm used. 548 * @param provider the name of the provider. 549 * 550 * @exception NoSuchAlgorithmException on unsupported signature 551 * algorithms. 552 * @exception InvalidKeyException on incorrect key. 553 * @exception NoSuchProviderException on incorrect provider. 554 * @exception SignatureException on signature errors. 555 * @exception CertificateException on encoding errors. 556 */ 557 public void sign(PrivateKey key, String algorithm, String provider) 558 throws CertificateException, NoSuchAlgorithmException, 559 InvalidKeyException, NoSuchProviderException, SignatureException { 560 try { 561 sign(key, null, algorithm, provider); 562 } catch (InvalidAlgorithmParameterException e) { 563 // should not happen; re-throw just in case 564 throw new SignatureException(e); 565 } 566 } 567 568 /** 569 * Creates an X.509 certificate, and signs it using the given key 570 * (associating a signature algorithm and an X.500 name), signature 571 * parameters, and security provider. If the given provider name 572 * is null or empty, the implementation look up will be based on 573 * provider configurations. 574 * This operation is used to implement the certificate generation 575 * functionality of a certificate authority. 576 * 577 * @param key the private key used for signing 578 * @param signingParams the parameters used for signing 579 * @param algorithm the name of the signature algorithm used 580 * @param provider the name of the provider, may be null 581 * 582 * @exception NoSuchAlgorithmException on unsupported signature 583 * algorithms 584 * @exception InvalidKeyException on incorrect key 585 * @exception InvalidAlgorithmParameterException on invalid signature 586 * parameters 587 * @exception NoSuchProviderException on incorrect provider 588 * @exception SignatureException on signature errors 589 * @exception CertificateException on encoding errors 590 */ 591 public void sign(PrivateKey key, AlgorithmParameterSpec signingParams, 592 String algorithm, String provider) 593 throws CertificateException, NoSuchAlgorithmException, 594 InvalidKeyException, InvalidAlgorithmParameterException, 595 NoSuchProviderException, SignatureException { 596 try { 597 if (readOnly) 598 throw new CertificateEncodingException( 599 "cannot over-write existing certificate"); 600 Signature sigEngine = null; 601 if (provider == null || provider.isEmpty()) 602 sigEngine = Signature.getInstance(algorithm); 603 else 604 sigEngine = Signature.getInstance(algorithm, provider); 605 606 sigEngine.initSign(key); 607 608 // set parameters after Signature.initSign/initVerify call, so 609 // the deferred provider selection happens when the key is set 610 try { 611 sigEngine.setParameter(signingParams); 612 } catch (UnsupportedOperationException e) { 613 // for backward compatibility, only re-throw when 614 // parameters is not null 615 if (signingParams != null) throw e; 616 } 617 618 // in case the name is reset 619 if (signingParams != null) { 620 algId = AlgorithmId.get(sigEngine.getParameters()); 621 } else { 622 algId = AlgorithmId.get(algorithm); 623 } 624 DerOutputStream out = new DerOutputStream(); 625 DerOutputStream tmp = new DerOutputStream(); 626 627 // encode certificate info 628 info.encode(tmp); 629 byte[] rawCert = tmp.toByteArray(); 630 631 // encode algorithm identifier 632 algId.encode(tmp); 633 634 // Create and encode the signature itself. 635 sigEngine.update(rawCert, 0, rawCert.length); 636 signature = sigEngine.sign(); 637 tmp.putBitString(signature); 638 639 // Wrap the signed data in a SEQUENCE { data, algorithm, sig } 640 out.write(DerValue.tag_Sequence, tmp); 641 signedCert = out.toByteArray(); 642 readOnly = true; 643 644 } catch (IOException e) { 645 throw new CertificateEncodingException(e.toString()); 646 } 647 } 648 649 /** 650 * Checks that the certificate is currently valid, i.e. the current 651 * time is within the specified validity period. 652 * 653 * @exception CertificateExpiredException if the certificate has expired. 654 * @exception CertificateNotYetValidException if the certificate is not 655 * yet valid. 656 */ 657 public void checkValidity() 658 throws CertificateExpiredException, CertificateNotYetValidException { 659 Date date = new Date(); 660 checkValidity(date); 661 } 662 663 /** 664 * Checks that the specified date is within the certificate's 665 * validity period, or basically if the certificate would be 666 * valid at the specified date/time. 667 * 668 * @param date the Date to check against to see if this certificate 669 * is valid at that date/time. 670 * 671 * @exception CertificateExpiredException if the certificate has expired 672 * with respect to the <code>date</code> supplied. 673 * @exception CertificateNotYetValidException if the certificate is not 674 * yet valid with respect to the <code>date</code> supplied. 675 */ 676 public void checkValidity(Date date) 677 throws CertificateExpiredException, CertificateNotYetValidException { 678 679 CertificateValidity interval = null; 680 try { 681 interval = (CertificateValidity)info.get(CertificateValidity.NAME); 682 } catch (Exception e) { 683 throw new CertificateNotYetValidException("Incorrect validity period"); 684 } 685 if (interval == null) 686 throw new CertificateNotYetValidException("Null validity period"); 687 interval.valid(date); 688 } 689 690 /** 691 * Return the requested attribute from the certificate. 692 * 693 * Note that the X509CertInfo is not cloned for performance reasons. 694 * Callers must ensure that they do not modify it. All other 695 * attributes are cloned. 696 * 697 * @param name the name of the attribute. 698 * @exception CertificateParsingException on invalid attribute identifier. 699 */ 700 public Object get(String name) 701 throws CertificateParsingException { 702 X509AttributeName attr = new X509AttributeName(name); 703 String id = attr.getPrefix(); 704 if (!(id.equalsIgnoreCase(NAME))) { 705 throw new CertificateParsingException("Invalid root of " 706 + "attribute name, expected [" + NAME + 707 "], received " + "[" + id + "]"); 708 } 709 attr = new X509AttributeName(attr.getSuffix()); 710 id = attr.getPrefix(); 711 712 if (id.equalsIgnoreCase(INFO)) { 713 if (info == null) { 714 return null; 715 } 716 if (attr.getSuffix() != null) { 717 try { 718 return info.get(attr.getSuffix()); 719 } catch (IOException e) { 720 throw new CertificateParsingException(e.toString()); 721 } catch (CertificateException e) { 722 throw new CertificateParsingException(e.toString()); 723 } 724 } else { 725 return info; 726 } 727 } else if (id.equalsIgnoreCase(ALG_ID)) { 728 return(algId); 729 } else if (id.equalsIgnoreCase(SIGNATURE)) { 730 if (signature != null) 731 return signature.clone(); 732 else 733 return null; 734 } else if (id.equalsIgnoreCase(SIGNED_CERT)) { 735 if (signedCert != null) 736 return signedCert.clone(); 737 else 738 return null; 739 } else { 740 throw new CertificateParsingException("Attribute name not " 741 + "recognized or get() not allowed for the same: " + id); 742 } 743 } 744 745 /** 746 * Set the requested attribute in the certificate. 747 * 748 * @param name the name of the attribute. 749 * @param obj the value of the attribute. 750 * @exception CertificateException on invalid attribute identifier. 751 * @exception IOException on encoding error of attribute. 752 */ 753 public void set(String name, Object obj) 754 throws CertificateException, IOException { 755 // check if immutable 756 if (readOnly) 757 throw new CertificateException("cannot over-write existing" 758 + " certificate"); 759 760 X509AttributeName attr = new X509AttributeName(name); 761 String id = attr.getPrefix(); 762 if (!(id.equalsIgnoreCase(NAME))) { 763 throw new CertificateException("Invalid root of attribute name," 764 + " expected [" + NAME + "], received " + id); 765 } 766 attr = new X509AttributeName(attr.getSuffix()); 767 id = attr.getPrefix(); 768 769 if (id.equalsIgnoreCase(INFO)) { 770 if (attr.getSuffix() == null) { 771 if (!(obj instanceof X509CertInfo)) { 772 throw new CertificateException("Attribute value should" 773 + " be of type X509CertInfo."); 774 } 775 info = (X509CertInfo)obj; 776 signedCert = null; //reset this as certificate data has changed 777 } else { 778 info.set(attr.getSuffix(), obj); 779 signedCert = null; //reset this as certificate data has changed 780 } 781 } else { 782 throw new CertificateException("Attribute name not recognized or " + 783 "set() not allowed for the same: " + id); 784 } 785 } 786 787 /** 788 * Delete the requested attribute from the certificate. 789 * 790 * @param name the name of the attribute. 791 * @exception CertificateException on invalid attribute identifier. 792 * @exception IOException on other errors. 793 */ 794 public void delete(String name) 795 throws CertificateException, IOException { 796 // check if immutable 797 if (readOnly) 798 throw new CertificateException("cannot over-write existing" 799 + " certificate"); 800 801 X509AttributeName attr = new X509AttributeName(name); 802 String id = attr.getPrefix(); 803 if (!(id.equalsIgnoreCase(NAME))) { 804 throw new CertificateException("Invalid root of attribute name," 805 + " expected [" 806 + NAME + "], received " + id); 807 } 808 attr = new X509AttributeName(attr.getSuffix()); 809 id = attr.getPrefix(); 810 811 if (id.equalsIgnoreCase(INFO)) { 812 if (attr.getSuffix() != null) { 813 info = null; 814 } else { 815 info.delete(attr.getSuffix()); 816 } 817 } else if (id.equalsIgnoreCase(ALG_ID)) { 818 algId = null; 819 } else if (id.equalsIgnoreCase(SIGNATURE)) { 820 signature = null; 821 } else if (id.equalsIgnoreCase(SIGNED_CERT)) { 822 signedCert = null; 823 } else { 824 throw new CertificateException("Attribute name not recognized or " + 825 "delete() not allowed for the same: " + id); 826 } 827 } 828 829 /** 830 * Return an enumeration of names of attributes existing within this 831 * attribute. 832 */ 833 public Enumeration<String> getElements() { 834 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 835 elements.addElement(NAME + DOT + INFO); 836 elements.addElement(NAME + DOT + ALG_ID); 837 elements.addElement(NAME + DOT + SIGNATURE); 838 elements.addElement(NAME + DOT + SIGNED_CERT); 839 840 return elements.elements(); 841 } 842 843 /** 844 * Return the name of this attribute. 845 */ 846 public String getName() { 847 return(NAME); 848 } 849 850 /** 851 * Returns a printable representation of the certificate. This does not 852 * contain all the information available to distinguish this from any 853 * other certificate. The certificate must be fully constructed 854 * before this function may be called. 855 */ 856 public String toString() { 857 if (info == null || algId == null || signature == null) 858 return ""; 859 860 HexDumpEncoder encoder = new HexDumpEncoder(); 861 return "[\n" + info + '\n' + 862 " Algorithm: [" + algId + "]\n" + 863 " Signature:\n" + encoder.encodeBuffer(signature) + "\n]"; 864 } 865 866 // the strongly typed gets, as per java.security.cert.X509Certificate 867 868 /** 869 * Gets the publickey from this certificate. 870 * 871 * @return the publickey. 872 */ 873 public PublicKey getPublicKey() { 874 if (info == null) 875 return null; 876 try { 877 PublicKey key = (PublicKey)info.get(CertificateX509Key.NAME 878 + DOT + CertificateX509Key.KEY); 879 return key; 880 } catch (Exception e) { 881 return null; 882 } 883 } 884 885 /** 886 * Gets the version number from the certificate. 887 * 888 * @return the version number, i.e. 1, 2 or 3. 889 */ 890 public int getVersion() { 891 if (info == null) 892 return -1; 893 try { 894 int vers = ((Integer)info.get(CertificateVersion.NAME 895 + DOT + CertificateVersion.VERSION)).intValue(); 896 return vers+1; 897 } catch (Exception e) { 898 return -1; 899 } 900 } 901 902 /** 903 * Gets the serial number from the certificate. 904 * 905 * @return the serial number. 906 */ 907 public BigInteger getSerialNumber() { 908 SerialNumber ser = getSerialNumberObject(); 909 910 return ser != null ? ser.getNumber() : null; 911 } 912 913 /** 914 * Gets the serial number from the certificate as 915 * a SerialNumber object. 916 * 917 * @return the serial number. 918 */ 919 public SerialNumber getSerialNumberObject() { 920 if (info == null) 921 return null; 922 try { 923 SerialNumber ser = (SerialNumber)info.get( 924 CertificateSerialNumber.NAME + DOT + 925 CertificateSerialNumber.NUMBER); 926 return ser; 927 } catch (Exception e) { 928 return null; 929 } 930 } 931 932 933 /** 934 * Gets the subject distinguished name from the certificate. 935 * 936 * @return the subject name. 937 */ 938 public Principal getSubjectDN() { 939 if (info == null) 940 return null; 941 try { 942 Principal subject = (Principal)info.get(X509CertInfo.SUBJECT + DOT + 943 X509CertInfo.DN_NAME); 944 return subject; 945 } catch (Exception e) { 946 return null; 947 } 948 } 949 950 /** 951 * Get subject name as X500Principal. Overrides implementation in 952 * X509Certificate with a slightly more efficient version that is 953 * also aware of X509CertImpl mutability. 954 */ 955 public X500Principal getSubjectX500Principal() { 956 if (info == null) { 957 return null; 958 } 959 try { 960 X500Principal subject = (X500Principal)info.get( 961 X509CertInfo.SUBJECT + DOT + 962 "x500principal"); 963 return subject; 964 } catch (Exception e) { 965 return null; 966 } 967 } 968 969 /** 970 * Gets the issuer distinguished name from the certificate. 971 * 972 * @return the issuer name. 973 */ 974 public Principal getIssuerDN() { 975 if (info == null) 976 return null; 977 try { 978 Principal issuer = (Principal)info.get(X509CertInfo.ISSUER + DOT + 979 X509CertInfo.DN_NAME); 980 return issuer; 981 } catch (Exception e) { 982 return null; 983 } 984 } 985 986 /** 987 * Get issuer name as X500Principal. Overrides implementation in 988 * X509Certificate with a slightly more efficient version that is 989 * also aware of X509CertImpl mutability. 990 */ 991 public X500Principal getIssuerX500Principal() { 992 if (info == null) { 993 return null; 994 } 995 try { 996 X500Principal issuer = (X500Principal)info.get( 997 X509CertInfo.ISSUER + DOT + 998 "x500principal"); 999 return issuer; 1000 } catch (Exception e) { 1001 return null; 1002 } 1003 } 1004 1005 /** 1006 * Gets the notBefore date from the validity period of the certificate. 1007 * 1008 * @return the start date of the validity period. 1009 */ 1010 public Date getNotBefore() { 1011 if (info == null) 1012 return null; 1013 try { 1014 Date d = (Date) info.get(CertificateValidity.NAME + DOT + 1015 CertificateValidity.NOT_BEFORE); 1016 return d; 1017 } catch (Exception e) { 1018 return null; 1019 } 1020 } 1021 1022 /** 1023 * Gets the notAfter date from the validity period of the certificate. 1024 * 1025 * @return the end date of the validity period. 1026 */ 1027 public Date getNotAfter() { 1028 if (info == null) 1029 return null; 1030 try { 1031 Date d = (Date) info.get(CertificateValidity.NAME + DOT + 1032 CertificateValidity.NOT_AFTER); 1033 return d; 1034 } catch (Exception e) { 1035 return null; 1036 } 1037 } 1038 1039 /** 1040 * Gets the DER encoded certificate informations, the 1041 * <code>tbsCertificate</code> from this certificate. 1042 * This can be used to verify the signature independently. 1043 * 1044 * @return the DER encoded certificate information. 1045 * @exception CertificateEncodingException if an encoding error occurs. 1046 */ 1047 public byte[] getTBSCertificate() throws CertificateEncodingException { 1048 if (info != null) { 1049 return info.getEncodedInfo(); 1050 } else 1051 throw new CertificateEncodingException("Uninitialized certificate"); 1052 } 1053 1054 /** 1055 * Gets the raw Signature bits from the certificate. 1056 * 1057 * @return the signature. 1058 */ 1059 public byte[] getSignature() { 1060 if (signature == null) 1061 return null; 1062 return signature.clone(); 1063 } 1064 1065 /** 1066 * Gets the signature algorithm name for the certificate 1067 * signature algorithm. 1068 * For example, the string "SHA-1/DSA" or "DSS". 1069 * 1070 * @return the signature algorithm name. 1071 */ 1072 public String getSigAlgName() { 1073 if (algId == null) 1074 return null; 1075 return (algId.getName()); 1076 } 1077 1078 /** 1079 * Gets the signature algorithm OID string from the certificate. 1080 * For example, the string "1.2.840.10040.4.3" 1081 * 1082 * @return the signature algorithm oid string. 1083 */ 1084 public String getSigAlgOID() { 1085 if (algId == null) 1086 return null; 1087 ObjectIdentifier oid = algId.getOID(); 1088 return (oid.toString()); 1089 } 1090 1091 /** 1092 * Gets the DER encoded signature algorithm parameters from this 1093 * certificate's signature algorithm. 1094 * 1095 * @return the DER encoded signature algorithm parameters, or 1096 * null if no parameters are present. 1097 */ 1098 public byte[] getSigAlgParams() { 1099 if (algId == null) 1100 return null; 1101 try { 1102 return algId.getEncodedParams(); 1103 } catch (IOException e) { 1104 return null; 1105 } 1106 } 1107 1108 /** 1109 * Gets the Issuer Unique Identity from the certificate. 1110 * 1111 * @return the Issuer Unique Identity. 1112 */ 1113 public boolean[] getIssuerUniqueID() { 1114 if (info == null) 1115 return null; 1116 try { 1117 UniqueIdentity id = (UniqueIdentity)info.get( 1118 X509CertInfo.ISSUER_ID); 1119 if (id == null) 1120 return null; 1121 else 1122 return (id.getId()); 1123 } catch (Exception e) { 1124 return null; 1125 } 1126 } 1127 1128 /** 1129 * Gets the Subject Unique Identity from the certificate. 1130 * 1131 * @return the Subject Unique Identity. 1132 */ 1133 public boolean[] getSubjectUniqueID() { 1134 if (info == null) 1135 return null; 1136 try { 1137 UniqueIdentity id = (UniqueIdentity)info.get( 1138 X509CertInfo.SUBJECT_ID); 1139 if (id == null) 1140 return null; 1141 else 1142 return (id.getId()); 1143 } catch (Exception e) { 1144 return null; 1145 } 1146 } 1147 1148 public KeyIdentifier getAuthKeyId() { 1149 AuthorityKeyIdentifierExtension aki 1150 = getAuthorityKeyIdentifierExtension(); 1151 if (aki != null) { 1152 try { 1153 return (KeyIdentifier)aki.get( 1154 AuthorityKeyIdentifierExtension.KEY_ID); 1155 } catch (IOException ioe) {} // not possible 1156 } 1157 return null; 1158 } 1159 1160 /** 1161 * Returns the subject's key identifier, or null 1162 */ 1163 public KeyIdentifier getSubjectKeyId() { 1164 SubjectKeyIdentifierExtension ski = getSubjectKeyIdentifierExtension(); 1165 if (ski != null) { 1166 try { 1167 return ski.get(SubjectKeyIdentifierExtension.KEY_ID); 1168 } catch (IOException ioe) {} // not possible 1169 } 1170 return null; 1171 } 1172 1173 /** 1174 * Get AuthorityKeyIdentifier extension 1175 * @return AuthorityKeyIdentifier object or null (if no such object 1176 * in certificate) 1177 */ 1178 public AuthorityKeyIdentifierExtension getAuthorityKeyIdentifierExtension() 1179 { 1180 return (AuthorityKeyIdentifierExtension) 1181 getExtension(PKIXExtensions.AuthorityKey_Id); 1182 } 1183 1184 /** 1185 * Get BasicConstraints extension 1186 * @return BasicConstraints object or null (if no such object in 1187 * certificate) 1188 */ 1189 public BasicConstraintsExtension getBasicConstraintsExtension() { 1190 return (BasicConstraintsExtension) 1191 getExtension(PKIXExtensions.BasicConstraints_Id); 1192 } 1193 1194 /** 1195 * Get CertificatePoliciesExtension 1196 * @return CertificatePoliciesExtension or null (if no such object in 1197 * certificate) 1198 */ 1199 public CertificatePoliciesExtension getCertificatePoliciesExtension() { 1200 return (CertificatePoliciesExtension) 1201 getExtension(PKIXExtensions.CertificatePolicies_Id); 1202 } 1203 1204 /** 1205 * Get ExtendedKeyUsage extension 1206 * @return ExtendedKeyUsage extension object or null (if no such object 1207 * in certificate) 1208 */ 1209 public ExtendedKeyUsageExtension getExtendedKeyUsageExtension() { 1210 return (ExtendedKeyUsageExtension) 1211 getExtension(PKIXExtensions.ExtendedKeyUsage_Id); 1212 } 1213 1214 /** 1215 * Get IssuerAlternativeName extension 1216 * @return IssuerAlternativeName object or null (if no such object in 1217 * certificate) 1218 */ 1219 public IssuerAlternativeNameExtension getIssuerAlternativeNameExtension() { 1220 return (IssuerAlternativeNameExtension) 1221 getExtension(PKIXExtensions.IssuerAlternativeName_Id); 1222 } 1223 1224 /** 1225 * Get NameConstraints extension 1226 * @return NameConstraints object or null (if no such object in certificate) 1227 */ 1228 public NameConstraintsExtension getNameConstraintsExtension() { 1229 return (NameConstraintsExtension) 1230 getExtension(PKIXExtensions.NameConstraints_Id); 1231 } 1232 1233 /** 1234 * Get PolicyConstraints extension 1235 * @return PolicyConstraints object or null (if no such object in 1236 * certificate) 1237 */ 1238 public PolicyConstraintsExtension getPolicyConstraintsExtension() { 1239 return (PolicyConstraintsExtension) 1240 getExtension(PKIXExtensions.PolicyConstraints_Id); 1241 } 1242 1243 /** 1244 * Get PolicyMappingsExtension extension 1245 * @return PolicyMappingsExtension object or null (if no such object 1246 * in certificate) 1247 */ 1248 public PolicyMappingsExtension getPolicyMappingsExtension() { 1249 return (PolicyMappingsExtension) 1250 getExtension(PKIXExtensions.PolicyMappings_Id); 1251 } 1252 1253 /** 1254 * Get PrivateKeyUsage extension 1255 * @return PrivateKeyUsage object or null (if no such object in certificate) 1256 */ 1257 public PrivateKeyUsageExtension getPrivateKeyUsageExtension() { 1258 return (PrivateKeyUsageExtension) 1259 getExtension(PKIXExtensions.PrivateKeyUsage_Id); 1260 } 1261 1262 /** 1263 * Get SubjectAlternativeName extension 1264 * @return SubjectAlternativeName object or null (if no such object in 1265 * certificate) 1266 */ 1267 public SubjectAlternativeNameExtension getSubjectAlternativeNameExtension() 1268 { 1269 return (SubjectAlternativeNameExtension) 1270 getExtension(PKIXExtensions.SubjectAlternativeName_Id); 1271 } 1272 1273 /** 1274 * Get SubjectKeyIdentifier extension 1275 * @return SubjectKeyIdentifier object or null (if no such object in 1276 * certificate) 1277 */ 1278 public SubjectKeyIdentifierExtension getSubjectKeyIdentifierExtension() { 1279 return (SubjectKeyIdentifierExtension) 1280 getExtension(PKIXExtensions.SubjectKey_Id); 1281 } 1282 1283 /** 1284 * Get CRLDistributionPoints extension 1285 * @return CRLDistributionPoints object or null (if no such object in 1286 * certificate) 1287 */ 1288 public CRLDistributionPointsExtension getCRLDistributionPointsExtension() { 1289 return (CRLDistributionPointsExtension) 1290 getExtension(PKIXExtensions.CRLDistributionPoints_Id); 1291 } 1292 1293 /** 1294 * Return true if a critical extension is found that is 1295 * not supported, otherwise return false. 1296 */ 1297 public boolean hasUnsupportedCriticalExtension() { 1298 if (info == null) 1299 return false; 1300 try { 1301 CertificateExtensions exts = (CertificateExtensions)info.get( 1302 CertificateExtensions.NAME); 1303 if (exts == null) 1304 return false; 1305 return exts.hasUnsupportedCriticalExtension(); 1306 } catch (Exception e) { 1307 return false; 1308 } 1309 } 1310 1311 /** 1312 * Gets a Set of the extension(s) marked CRITICAL in the 1313 * certificate. In the returned set, each extension is 1314 * represented by its OID string. 1315 * 1316 * @return a set of the extension oid strings in the 1317 * certificate that are marked critical. 1318 */ 1319 public Set<String> getCriticalExtensionOIDs() { 1320 if (info == null) { 1321 return null; 1322 } 1323 try { 1324 CertificateExtensions exts = (CertificateExtensions)info.get( 1325 CertificateExtensions.NAME); 1326 if (exts == null) { 1327 return null; 1328 } 1329 Set<String> extSet = new TreeSet<>(); 1330 for (Extension ex : exts.getAllExtensions()) { 1331 if (ex.isCritical()) { 1332 extSet.add(ex.getExtensionId().toString()); 1333 } 1334 } 1335 return extSet; 1336 } catch (Exception e) { 1337 return null; 1338 } 1339 } 1340 1341 /** 1342 * Gets a Set of the extension(s) marked NON-CRITICAL in the 1343 * certificate. In the returned set, each extension is 1344 * represented by its OID string. 1345 * 1346 * @return a set of the extension oid strings in the 1347 * certificate that are NOT marked critical. 1348 */ 1349 public Set<String> getNonCriticalExtensionOIDs() { 1350 if (info == null) { 1351 return null; 1352 } 1353 try { 1354 CertificateExtensions exts = (CertificateExtensions)info.get( 1355 CertificateExtensions.NAME); 1356 if (exts == null) { 1357 return null; 1358 } 1359 Set<String> extSet = new TreeSet<>(); 1360 for (Extension ex : exts.getAllExtensions()) { 1361 if (!ex.isCritical()) { 1362 extSet.add(ex.getExtensionId().toString()); 1363 } 1364 } 1365 extSet.addAll(exts.getUnparseableExtensions().keySet()); 1366 return extSet; 1367 } catch (Exception e) { 1368 return null; 1369 } 1370 } 1371 1372 /** 1373 * Gets the extension identified by the given ObjectIdentifier 1374 * 1375 * @param oid the Object Identifier value for the extension. 1376 * @return Extension or null if certificate does not contain this 1377 * extension 1378 */ 1379 public Extension getExtension(ObjectIdentifier oid) { 1380 if (info == null) { 1381 return null; 1382 } 1383 try { 1384 CertificateExtensions extensions; 1385 try { 1386 extensions = (CertificateExtensions)info.get(CertificateExtensions.NAME); 1387 } catch (CertificateException ce) { 1388 return null; 1389 } 1390 if (extensions == null) { 1391 return null; 1392 } else { 1393 Extension ex = extensions.getExtension(oid.toString()); 1394 if (ex != null) { 1395 return ex; 1396 } 1397 for (Extension ex2: extensions.getAllExtensions()) { 1398 if (ex2.getExtensionId().equals(oid)) { 1399 //XXXX May want to consider cloning this 1400 return ex2; 1401 } 1402 } 1403 /* no such extension in this certificate */ 1404 return null; 1405 } 1406 } catch (IOException ioe) { 1407 return null; 1408 } 1409 } 1410 1411 public Extension getUnparseableExtension(ObjectIdentifier oid) { 1412 if (info == null) { 1413 return null; 1414 } 1415 try { 1416 CertificateExtensions extensions; 1417 try { 1418 extensions = (CertificateExtensions)info.get(CertificateExtensions.NAME); 1419 } catch (CertificateException ce) { 1420 return null; 1421 } 1422 if (extensions == null) { 1423 return null; 1424 } else { 1425 return extensions.getUnparseableExtensions().get(oid.toString()); 1426 } 1427 } catch (IOException ioe) { 1428 return null; 1429 } 1430 } 1431 1432 /** 1433 * Gets the DER encoded extension identified by the given 1434 * oid String. 1435 * 1436 * @param oid the Object Identifier value for the extension. 1437 */ 1438 public byte[] getExtensionValue(String oid) { 1439 try { 1440 ObjectIdentifier findOID = new ObjectIdentifier(oid); 1441 String extAlias = OIDMap.getName(findOID); 1442 Extension certExt = null; 1443 CertificateExtensions exts = (CertificateExtensions)info.get( 1444 CertificateExtensions.NAME); 1445 1446 if (extAlias == null) { // may be unknown 1447 // get the extensions, search thru' for this oid 1448 if (exts == null) { 1449 return null; 1450 } 1451 1452 for (Extension ex : exts.getAllExtensions()) { 1453 ObjectIdentifier inCertOID = ex.getExtensionId(); 1454 if (inCertOID.equals(findOID)) { 1455 certExt = ex; 1456 break; 1457 } 1458 } 1459 } else { // there's sub-class that can handle this extension 1460 try { 1461 certExt = (Extension)this.get(extAlias); 1462 } catch (CertificateException e) { 1463 // get() throws an Exception instead of returning null, ignore 1464 } 1465 } 1466 if (certExt == null) { 1467 if (exts != null) { 1468 certExt = exts.getUnparseableExtensions().get(oid); 1469 } 1470 if (certExt == null) { 1471 return null; 1472 } 1473 } 1474 byte[] extData = certExt.getExtensionValue(); 1475 if (extData == null) { 1476 return null; 1477 } 1478 DerOutputStream out = new DerOutputStream(); 1479 out.putOctetString(extData); 1480 return out.toByteArray(); 1481 } catch (Exception e) { 1482 return null; 1483 } 1484 } 1485 1486 /** 1487 * Get a boolean array representing the bits of the KeyUsage extension, 1488 * (oid = 2.5.29.15). 1489 * @return the bit values of this extension as an array of booleans. 1490 */ 1491 public boolean[] getKeyUsage() { 1492 try { 1493 String extAlias = OIDMap.getName(PKIXExtensions.KeyUsage_Id); 1494 if (extAlias == null) 1495 return null; 1496 1497 KeyUsageExtension certExt = (KeyUsageExtension)this.get(extAlias); 1498 if (certExt == null) 1499 return null; 1500 1501 boolean[] ret = certExt.getBits(); 1502 if (ret.length < NUM_STANDARD_KEY_USAGE) { 1503 boolean[] usageBits = new boolean[NUM_STANDARD_KEY_USAGE]; 1504 System.arraycopy(ret, 0, usageBits, 0, ret.length); 1505 ret = usageBits; 1506 } 1507 return ret; 1508 } catch (Exception e) { 1509 return null; 1510 } 1511 } 1512 1513 /** 1514 * This method are the overridden implementation of 1515 * getExtendedKeyUsage method in X509Certificate in the Sun 1516 * provider. It is better performance-wise since it returns cached 1517 * values. 1518 */ 1519 public synchronized List<String> getExtendedKeyUsage() 1520 throws CertificateParsingException { 1521 if (readOnly && extKeyUsage != null) { 1522 return extKeyUsage; 1523 } else { 1524 ExtendedKeyUsageExtension ext = getExtendedKeyUsageExtension(); 1525 if (ext == null) { 1526 return null; 1527 } 1528 extKeyUsage = 1529 Collections.unmodifiableList(ext.getExtendedKeyUsage()); 1530 return extKeyUsage; 1531 } 1532 } 1533 1534 /** 1535 * This static method is the default implementation of the 1536 * getExtendedKeyUsage method in X509Certificate. A 1537 * X509Certificate provider generally should overwrite this to 1538 * provide among other things caching for better performance. 1539 */ 1540 public static List<String> getExtendedKeyUsage(X509Certificate cert) 1541 throws CertificateParsingException { 1542 try { 1543 byte[] ext = cert.getExtensionValue(EXTENDED_KEY_USAGE_OID); 1544 if (ext == null) 1545 return null; 1546 DerValue val = new DerValue(ext); 1547 byte[] data = val.getOctetString(); 1548 1549 ExtendedKeyUsageExtension ekuExt = 1550 new ExtendedKeyUsageExtension(Boolean.FALSE, data); 1551 return Collections.unmodifiableList(ekuExt.getExtendedKeyUsage()); 1552 } catch (IOException ioe) { 1553 throw new CertificateParsingException(ioe); 1554 } 1555 } 1556 1557 /** 1558 * Get the certificate constraints path length from 1559 * the critical BasicConstraints extension, (oid = 2.5.29.19). 1560 * @return the length of the constraint. 1561 */ 1562 public int getBasicConstraints() { 1563 try { 1564 String extAlias = OIDMap.getName(PKIXExtensions.BasicConstraints_Id); 1565 if (extAlias == null) 1566 return -1; 1567 BasicConstraintsExtension certExt = 1568 (BasicConstraintsExtension)this.get(extAlias); 1569 if (certExt == null) 1570 return -1; 1571 1572 if (((Boolean)certExt.get(BasicConstraintsExtension.IS_CA) 1573 ).booleanValue() == true) 1574 return ((Integer)certExt.get( 1575 BasicConstraintsExtension.PATH_LEN)).intValue(); 1576 else 1577 return -1; 1578 } catch (Exception e) { 1579 return -1; 1580 } 1581 } 1582 1583 /** 1584 * Converts a GeneralNames structure into an immutable Collection of 1585 * alternative names (subject or issuer) in the form required by 1586 * {@link #getSubjectAlternativeNames} or 1587 * {@link #getIssuerAlternativeNames}. 1588 * 1589 * @param names the GeneralNames to be converted 1590 * @return an immutable Collection of alternative names 1591 */ 1592 private static Collection<List<?>> makeAltNames(GeneralNames names) { 1593 if (names.isEmpty()) { 1594 return Collections.<List<?>>emptySet(); 1595 } 1596 List<List<?>> newNames = new ArrayList<>(); 1597 for (GeneralName gname : names.names()) { 1598 GeneralNameInterface name = gname.getName(); 1599 List<Object> nameEntry = new ArrayList<>(2); 1600 nameEntry.add(Integer.valueOf(name.getType())); 1601 switch (name.getType()) { 1602 case GeneralNameInterface.NAME_RFC822: 1603 nameEntry.add(((RFC822Name) name).getName()); 1604 break; 1605 case GeneralNameInterface.NAME_DNS: 1606 nameEntry.add(((DNSName) name).getName()); 1607 break; 1608 case GeneralNameInterface.NAME_DIRECTORY: 1609 nameEntry.add(((X500Name) name).getRFC2253Name()); 1610 break; 1611 case GeneralNameInterface.NAME_URI: 1612 nameEntry.add(((URIName) name).getName()); 1613 break; 1614 case GeneralNameInterface.NAME_IP: 1615 try { 1616 nameEntry.add(((IPAddressName) name).getName()); 1617 } catch (IOException ioe) { 1618 // IPAddressName in cert is bogus 1619 throw new RuntimeException("IPAddress cannot be parsed", 1620 ioe); 1621 } 1622 break; 1623 case GeneralNameInterface.NAME_OID: 1624 nameEntry.add(((OIDName) name).getOID().toString()); 1625 break; 1626 default: 1627 // add DER encoded form 1628 DerOutputStream derOut = new DerOutputStream(); 1629 try { 1630 name.encode(derOut); 1631 } catch (IOException ioe) { 1632 // should not occur since name has already been decoded 1633 // from cert (this would indicate a bug in our code) 1634 throw new RuntimeException("name cannot be encoded", ioe); 1635 } 1636 nameEntry.add(derOut.toByteArray()); 1637 break; 1638 } 1639 newNames.add(Collections.unmodifiableList(nameEntry)); 1640 } 1641 return Collections.unmodifiableCollection(newNames); 1642 } 1643 1644 /** 1645 * Checks a Collection of altNames and clones any name entries of type 1646 * byte []. 1647 */ // only partially generified due to javac bug 1648 private static Collection<List<?>> cloneAltNames(Collection<List<?>> altNames) { 1649 boolean mustClone = false; 1650 for (List<?> nameEntry : altNames) { 1651 if (nameEntry.get(1) instanceof byte[]) { 1652 // must clone names 1653 mustClone = true; 1654 } 1655 } 1656 if (mustClone) { 1657 List<List<?>> namesCopy = new ArrayList<>(); 1658 for (List<?> nameEntry : altNames) { 1659 Object nameObject = nameEntry.get(1); 1660 if (nameObject instanceof byte[]) { 1661 List<Object> nameEntryCopy = 1662 new ArrayList<>(nameEntry); 1663 nameEntryCopy.set(1, ((byte[])nameObject).clone()); 1664 namesCopy.add(Collections.unmodifiableList(nameEntryCopy)); 1665 } else { 1666 namesCopy.add(nameEntry); 1667 } 1668 } 1669 return Collections.unmodifiableCollection(namesCopy); 1670 } else { 1671 return altNames; 1672 } 1673 } 1674 1675 /** 1676 * This method are the overridden implementation of 1677 * getSubjectAlternativeNames method in X509Certificate in the Sun 1678 * provider. It is better performance-wise since it returns cached 1679 * values. 1680 */ 1681 public synchronized Collection<List<?>> getSubjectAlternativeNames() 1682 throws CertificateParsingException { 1683 // return cached value if we can 1684 if (readOnly && subjectAlternativeNames != null) { 1685 return cloneAltNames(subjectAlternativeNames); 1686 } 1687 SubjectAlternativeNameExtension subjectAltNameExt = 1688 getSubjectAlternativeNameExtension(); 1689 if (subjectAltNameExt == null) { 1690 return null; 1691 } 1692 GeneralNames names; 1693 try { 1694 names = subjectAltNameExt.get( 1695 SubjectAlternativeNameExtension.SUBJECT_NAME); 1696 } catch (IOException ioe) { 1697 // should not occur 1698 return Collections.<List<?>>emptySet(); 1699 } 1700 subjectAlternativeNames = makeAltNames(names); 1701 return subjectAlternativeNames; 1702 } 1703 1704 /** 1705 * This static method is the default implementation of the 1706 * getSubjectAlternaitveNames method in X509Certificate. A 1707 * X509Certificate provider generally should overwrite this to 1708 * provide among other things caching for better performance. 1709 */ 1710 public static Collection<List<?>> getSubjectAlternativeNames(X509Certificate cert) 1711 throws CertificateParsingException { 1712 try { 1713 byte[] ext = cert.getExtensionValue(SUBJECT_ALT_NAME_OID); 1714 if (ext == null) { 1715 return null; 1716 } 1717 DerValue val = new DerValue(ext); 1718 byte[] data = val.getOctetString(); 1719 1720 SubjectAlternativeNameExtension subjectAltNameExt = 1721 new SubjectAlternativeNameExtension(Boolean.FALSE, 1722 data); 1723 1724 GeneralNames names; 1725 try { 1726 names = subjectAltNameExt.get( 1727 SubjectAlternativeNameExtension.SUBJECT_NAME); 1728 } catch (IOException ioe) { 1729 // should not occur 1730 return Collections.<List<?>>emptySet(); 1731 } 1732 return makeAltNames(names); 1733 } catch (IOException ioe) { 1734 throw new CertificateParsingException(ioe); 1735 } 1736 } 1737 1738 /** 1739 * This method are the overridden implementation of 1740 * getIssuerAlternativeNames method in X509Certificate in the Sun 1741 * provider. It is better performance-wise since it returns cached 1742 * values. 1743 */ 1744 public synchronized Collection<List<?>> getIssuerAlternativeNames() 1745 throws CertificateParsingException { 1746 // return cached value if we can 1747 if (readOnly && issuerAlternativeNames != null) { 1748 return cloneAltNames(issuerAlternativeNames); 1749 } 1750 IssuerAlternativeNameExtension issuerAltNameExt = 1751 getIssuerAlternativeNameExtension(); 1752 if (issuerAltNameExt == null) { 1753 return null; 1754 } 1755 GeneralNames names; 1756 try { 1757 names = issuerAltNameExt.get( 1758 IssuerAlternativeNameExtension.ISSUER_NAME); 1759 } catch (IOException ioe) { 1760 // should not occur 1761 return Collections.<List<?>>emptySet(); 1762 } 1763 issuerAlternativeNames = makeAltNames(names); 1764 return issuerAlternativeNames; 1765 } 1766 1767 /** 1768 * This static method is the default implementation of the 1769 * getIssuerAlternaitveNames method in X509Certificate. A 1770 * X509Certificate provider generally should overwrite this to 1771 * provide among other things caching for better performance. 1772 */ 1773 public static Collection<List<?>> getIssuerAlternativeNames(X509Certificate cert) 1774 throws CertificateParsingException { 1775 try { 1776 byte[] ext = cert.getExtensionValue(ISSUER_ALT_NAME_OID); 1777 if (ext == null) { 1778 return null; 1779 } 1780 1781 DerValue val = new DerValue(ext); 1782 byte[] data = val.getOctetString(); 1783 1784 IssuerAlternativeNameExtension issuerAltNameExt = 1785 new IssuerAlternativeNameExtension(Boolean.FALSE, 1786 data); 1787 GeneralNames names; 1788 try { 1789 names = issuerAltNameExt.get( 1790 IssuerAlternativeNameExtension.ISSUER_NAME); 1791 } catch (IOException ioe) { 1792 // should not occur 1793 return Collections.<List<?>>emptySet(); 1794 } 1795 return makeAltNames(names); 1796 } catch (IOException ioe) { 1797 throw new CertificateParsingException(ioe); 1798 } 1799 } 1800 1801 public AuthorityInfoAccessExtension getAuthorityInfoAccessExtension() { 1802 return (AuthorityInfoAccessExtension) 1803 getExtension(PKIXExtensions.AuthInfoAccess_Id); 1804 } 1805 1806 /************************************************************/ 1807 1808 /* 1809 * Cert is a SIGNED ASN.1 macro, a three elment sequence: 1810 * 1811 * - Data to be signed (ToBeSigned) -- the "raw" cert 1812 * - Signature algorithm (SigAlgId) 1813 * - The signature bits 1814 * 1815 * This routine unmarshals the certificate, saving the signature 1816 * parts away for later verification. 1817 */ 1818 private void parse(DerValue val) 1819 throws CertificateException, IOException { 1820 // check if can over write the certificate 1821 if (readOnly) 1822 throw new CertificateParsingException( 1823 "cannot over-write existing certificate"); 1824 1825 if (val.data == null || val.tag != DerValue.tag_Sequence) 1826 throw new CertificateParsingException( 1827 "invalid DER-encoded certificate data"); 1828 1829 signedCert = val.toByteArray(); 1830 DerValue[] seq = new DerValue[3]; 1831 1832 seq[0] = val.data.getDerValue(); 1833 seq[1] = val.data.getDerValue(); 1834 seq[2] = val.data.getDerValue(); 1835 1836 if (val.data.available() != 0) { 1837 throw new CertificateParsingException("signed overrun, bytes = " 1838 + val.data.available()); 1839 } 1840 if (seq[0].tag != DerValue.tag_Sequence) { 1841 throw new CertificateParsingException("signed fields invalid"); 1842 } 1843 1844 algId = AlgorithmId.parse(seq[1]); 1845 signature = seq[2].getBitString(); 1846 1847 if (seq[1].data.available() != 0) { 1848 throw new CertificateParsingException("algid field overrun"); 1849 } 1850 if (seq[2].data.available() != 0) 1851 throw new CertificateParsingException("signed fields overrun"); 1852 1853 // The CertificateInfo 1854 info = new X509CertInfo(seq[0]); 1855 1856 // the "inner" and "outer" signature algorithms must match 1857 AlgorithmId infoSigAlg = (AlgorithmId)info.get( 1858 CertificateAlgorithmId.NAME 1859 + DOT + 1860 CertificateAlgorithmId.ALGORITHM); 1861 if (! algId.equals(infoSigAlg)) 1862 throw new CertificateException("Signature algorithm mismatch"); 1863 readOnly = true; 1864 } 1865 1866 /** 1867 * Extract the subject or issuer X500Principal from an X509Certificate. 1868 * Parses the encoded form of the cert to preserve the principal's 1869 * ASN.1 encoding. 1870 */ 1871 private static X500Principal getX500Principal(X509Certificate cert, 1872 boolean getIssuer) throws Exception { 1873 byte[] encoded = cert.getEncoded(); 1874 DerInputStream derIn = new DerInputStream(encoded); 1875 DerValue tbsCert = derIn.getSequence(3)[0]; 1876 DerInputStream tbsIn = tbsCert.data; 1877 DerValue tmp; 1878 tmp = tbsIn.getDerValue(); 1879 // skip version number if present 1880 if (tmp.isContextSpecific((byte)0)) { 1881 tmp = tbsIn.getDerValue(); 1882 } 1883 // tmp always contains serial number now 1884 tmp = tbsIn.getDerValue(); // skip signature 1885 tmp = tbsIn.getDerValue(); // issuer 1886 if (getIssuer == false) { 1887 tmp = tbsIn.getDerValue(); // skip validity 1888 tmp = tbsIn.getDerValue(); // subject 1889 } 1890 byte[] principalBytes = tmp.toByteArray(); 1891 return new X500Principal(principalBytes); 1892 } 1893 1894 /** 1895 * Extract the subject X500Principal from an X509Certificate. 1896 * Called from java.security.cert.X509Certificate.getSubjectX500Principal(). 1897 */ 1898 public static X500Principal getSubjectX500Principal(X509Certificate cert) { 1899 try { 1900 return getX500Principal(cert, false); 1901 } catch (Exception e) { 1902 throw new RuntimeException("Could not parse subject", e); 1903 } 1904 } 1905 1906 /** 1907 * Extract the issuer X500Principal from an X509Certificate. 1908 * Called from java.security.cert.X509Certificate.getIssuerX500Principal(). 1909 */ 1910 public static X500Principal getIssuerX500Principal(X509Certificate cert) { 1911 try { 1912 return getX500Principal(cert, true); 1913 } catch (Exception e) { 1914 throw new RuntimeException("Could not parse issuer", e); 1915 } 1916 } 1917 1918 /** 1919 * Returned the encoding of the given certificate for internal use. 1920 * Callers must guarantee that they neither modify it nor expose it 1921 * to untrusted code. Uses getEncodedInternal() if the certificate 1922 * is instance of X509CertImpl, getEncoded() otherwise. 1923 */ 1924 public static byte[] getEncodedInternal(Certificate cert) 1925 throws CertificateEncodingException { 1926 if (cert instanceof X509CertImpl) { 1927 return ((X509CertImpl)cert).getEncodedInternal(); 1928 } else { 1929 return cert.getEncoded(); 1930 } 1931 } 1932 1933 /** 1934 * Utility method to convert an arbitrary instance of X509Certificate 1935 * to a X509CertImpl. Does a cast if possible, otherwise reparses 1936 * the encoding. 1937 */ 1938 public static X509CertImpl toImpl(X509Certificate cert) 1939 throws CertificateException { 1940 if (cert instanceof X509CertImpl) { 1941 return (X509CertImpl)cert; 1942 } else { 1943 return X509Factory.intern(cert); 1944 } 1945 } 1946 1947 /** 1948 * Utility method to test if a certificate is self-issued. This is 1949 * the case iff the subject and issuer X500Principals are equal. 1950 */ 1951 public static boolean isSelfIssued(X509Certificate cert) { 1952 X500Principal subject = cert.getSubjectX500Principal(); 1953 X500Principal issuer = cert.getIssuerX500Principal(); 1954 return subject.equals(issuer); 1955 } 1956 1957 /** 1958 * Utility method to test if a certificate is self-signed. This is 1959 * the case iff the subject and issuer X500Principals are equal 1960 * AND the certificate's subject public key can be used to verify 1961 * the certificate. In case of exception, returns false. 1962 */ 1963 public static boolean isSelfSigned(X509Certificate cert, 1964 String sigProvider) { 1965 if (isSelfIssued(cert)) { 1966 try { 1967 if (sigProvider == null) { 1968 cert.verify(cert.getPublicKey()); 1969 } else { 1970 cert.verify(cert.getPublicKey(), sigProvider); 1971 } 1972 return true; 1973 } catch (Exception e) { 1974 // In case of exception, return false 1975 } 1976 } 1977 return false; 1978 } 1979 1980 private ConcurrentHashMap<String,String> fingerprints = 1981 new ConcurrentHashMap<>(2); 1982 1983 public String getFingerprint(String algorithm) { 1984 return fingerprints.computeIfAbsent(algorithm, 1985 x -> getFingerprint(x, this)); 1986 } 1987 1988 /** 1989 * Gets the requested finger print of the certificate. The result 1990 * only contains 0-9 and A-F. No small case, no colon. 1991 */ 1992 public static String getFingerprint(String algorithm, 1993 X509Certificate cert) { 1994 try { 1995 byte[] encCertInfo = cert.getEncoded(); 1996 MessageDigest md = MessageDigest.getInstance(algorithm); 1997 byte[] digest = md.digest(encCertInfo); 1998 StringBuilder sb = new StringBuilder(digest.length * 2); 1999 for (int i = 0; i < digest.length; i++) { 2000 byte2hex(digest[i], sb); 2001 } 2002 return sb.toString(); 2003 } catch (NoSuchAlgorithmException | CertificateEncodingException e) { 2004 // ignored 2005 } 2006 return ""; 2007 } 2008 2009 /** 2010 * Converts a byte to hex digit and writes to the supplied builder 2011 */ 2012 private static void byte2hex(byte b, StringBuilder buf) { 2013 char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', 2014 '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 2015 int high = ((b & 0xf0) >> 4); 2016 int low = (b & 0x0f); 2017 buf.append(hexChars[high]) 2018 .append(hexChars[low]); 2019 } 2020 }