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