} } private static <T> Iterable<T> e2i(final Enumeration<T> e) { return new Iterable<T>() { @Override public Iterator<T> iterator() { return new Iterator<T>() { @Override public boolean hasNext() { return e.hasMoreElements(); } @Override public T next() { return e.nextElement(); } public void remove() { throw new UnsupportedOperationException("Not supported yet."); } }; } }; } /** * Loads CRLs from a source. This method is also called in JarSigner. * @param src the source, which means System.in if null, or a URI, * or a bare file path name */ public static Collection<? extends CRL> loadCRLs(String src) throws Exception { InputStream in = null; URI uri = null; if (src == null) { in = System.in; } else { try { uri = new URI(src); if (uri.getScheme().equals("ldap")) { // No input stream for LDAP } else { in = uri.toURL().openStream(); } } catch (Exception e) { try { in = new FileInputStream(src); } catch (Exception e2) { if (uri == null || uri.getScheme() == null) { throw e2; // More likely a bare file path } else { throw e; // More likely a protocol or network problem } } } } if (in != null) { try { // Read the full stream before feeding to X509Factory, // otherwise, keytool -gencrl | keytool -printcrl // might not work properly, since -gencrl is slow // and there's no data in the pipe at the beginning. ByteArrayOutputStream bout = new ByteArrayOutputStream(); byte[] b = new byte[4096]; while (true) { int len = in.read(b); if (len < 0) break; bout.write(b, 0, len); } return CertificateFactory.getInstance("X509").generateCRLs( new ByteArrayInputStream(bout.toByteArray())); } finally { if (in != System.in) { in.close(); } } } else { // must be LDAP, and uri is not null String path = uri.getPath(); if (path.charAt(0) == '/') path = path.substring(1); LDAPCertStoreHelper h = new LDAPCertStoreHelper(); CertStore s = h.getCertStore(uri); X509CRLSelector sel = h.wrap(new X509CRLSelector(), null, path); return s.getCRLs(sel); } } /** * Returns CRLs described in a X509Certificate's CRLDistributionPoints * Extension. Only those containing a general name of type URI are read. */ public static List<CRL> readCRLsFromCert(X509Certificate cert) throws Exception { List<CRL> crls = new ArrayList<>(); CRLDistributionPointsExtension ext = X509CertImpl.toImpl(cert).getCRLDistributionPointsExtension(); if (ext == null) return crls; for (DistributionPoint o: (List<DistributionPoint>) ext.get(CRLDistributionPointsExtension.POINTS)) { GeneralNames names = o.getFullName(); if (names != null) { for (GeneralName name: names.names()) { if (name.getType() == GeneralNameInterface.NAME_URI) { URIName uriName = (URIName)name.getName(); for (CRL crl: KeyTool.loadCRLs(uriName.getName())) { if (crl instanceof X509CRL) { crls.add((X509CRL)crl); } } break; // Different name should point to same CRL } } } } return crls; } private static String verifyCRL(KeyStore ks, CRL crl) throws Exception { X509CRLImpl xcrl = (X509CRLImpl)crl; X500Principal issuer = xcrl.getIssuerX500Principal(); for (String s: e2i(ks.aliases())) { Certificate cert = ks.getCertificate(s); if (cert instanceof X509Certificate) { X509Certificate xcert = (X509Certificate)cert; if (xcert.getSubjectX500Principal().equals(issuer)) { try { ((X509CRLImpl)crl).verify(cert.getPublicKey()); return s; } catch (Exception e) { } } } } return null; } private void doPrintCRL(String src, PrintStream out) throws Exception { for (CRL crl: loadCRLs(src)) { printCRL(crl, out); String issuer = null; if (caks != null) { issuer = verifyCRL(caks, crl); if (issuer != null) { System.out.println("Verified by " + issuer + " in cacerts"); } } if (issuer == null && keyStore != null) { issuer = verifyCRL(keyStore, crl); if (issuer != null) { System.out.println("Verified by " + issuer + " in keystore"); } } if (issuer == null) { out.println(rb.getString ("STAR")); out.println("WARNING: not verified. Make sure -keystore and -alias are correct."); out.println(rb.getString ("STARNN")); } } } private void printCRL(CRL crl, PrintStream out) throws Exception { if (rfc) { X509CRL xcrl = (X509CRL)crl; out.println("-----BEGIN X509 CRL-----"); new BASE64Encoder().encodeBuffer(xcrl.getEncoded(), out); out.println("-----END X509 CRL-----"); } else { out.println(crl.toString()); } } private void doPrintCertReq(InputStream in, PrintStream out) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuffer sb = new StringBuffer(); boolean started = false; while (true) { String s = reader.readLine(); if (s == null) break; if (!started) { if (s.startsWith("-----")) { started = true; } } else { if (s.startsWith("-----")) { break; } sb.append(s); } } PKCS10 req = new PKCS10(new BASE64Decoder().decodeBuffer(new String(sb))); PublicKey pkey = req.getSubjectPublicKeyInfo(); out.printf(rb.getString("PKCS.10.Certificate.Request.Version.1.0.Subject.s.Public.Key.s.format.s.key."), req.getSubjectName(), pkey.getFormat(), pkey.getAlgorithm()); for (PKCS10Attribute attr: req.getAttributes().getAttributes()) { ObjectIdentifier oid = attr.getAttributeId(); if (oid.equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) { CertificateExtensions exts = (CertificateExtensions)attr.getAttributeValue(); if (exts != null) { printExtensions(rb.getString("Extension.Request."), exts, out); } } else { out.println(attr.getAttributeId()); out.println(attr.getAttributeValue()); } } if (debug) { out.println(req); // Just to see more, say, public key length... } } /** * Reads a certificate (or certificate chain) and prints its contents in * a human readable format. */ private void printCertFromStream(InputStream in, PrintStream out) throws Exception { Collection<? extends Certificate> c = null; try { c = cf.generateCertificates(in); } catch (CertificateException ce) { throw new Exception(rb.getString("Failed.to.parse.input"), ce); } if (c.isEmpty()) { throw new Exception(rb.getString("Empty.input")); } Certificate[] certs = c.toArray(new Certificate[c.size()]); for (int i=0; i<certs.length; i++) { X509Certificate x509Cert = null; try { x509Cert = (X509Certificate)certs[i]; } catch (ClassCastException cce) { throw new Exception(rb.getString("Not.X.509.certificate")); } if (certs.length > 1) { MessageFormat form = new MessageFormat (rb.getString("Certificate.i.1.")); Object[] source = {new Integer(i + 1)}; out.println(form.format(source)); } if (rfc) dumpCert(x509Cert, out); else printX509Cert(x509Cert, out); if (i < (certs.length-1)) { out.println(); } } } private void doPrintCert(final PrintStream out) throws Exception { if (jarfile != null) { JarFile jf = new JarFile(jarfile, true); Enumeration<JarEntry> entries = jf.entries(); Set<CodeSigner> ss = new HashSet<>(); byte[] buffer = new byte[8192]; int pos = 0; while (entries.hasMoreElements()) { JarEntry je = entries.nextElement(); InputStream is = null; try { is = jf.getInputStream(je); while (is.read(buffer) != -1) { // we just read. this will throw a SecurityException // if a signature/digest check fails. This also // populate the signers } } finally { if (is != null) { is.close(); } } CodeSigner[] signers = je.getCodeSigners(); if (signers != null) { for (CodeSigner signer: signers) { if (!ss.contains(signer)) { ss.add(signer); out.printf(rb.getString("Signer.d."), ++pos); out.println(); out.println(); out.println(rb.getString("Signature.")); out.println(); for (Certificate cert: signer.getSignerCertPath().getCertificates()) { X509Certificate x = (X509Certificate)cert; if (rfc) { out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n"); dumpCert(x, out); } else { printX509Cert(x, out); } out.println(); } Timestamp ts = signer.getTimestamp(); if (ts != null) { out.println(rb.getString("Timestamp.")); out.println(); for (Certificate cert: ts.getSignerCertPath().getCertificates()) { X509Certificate x = (X509Certificate)cert; if (rfc) { out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n"); dumpCert(x, out); } else { printX509Cert(x, out); } out.println(); } } } } } } jf.close(); if (ss.size() == 0) { out.println(rb.getString("Not.a.signed.jar.file")); } } else if (sslserver != null) { SSLContext sc = SSLContext.getInstance("SSL"); final boolean[] certPrinted = new boolean[1]; sc.init(null, new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { for (int i=0; i<certs.length; i++) { X509Certificate cert = certs[i]; try { if (rfc) { dumpCert(cert, out); } else { out.println("Certificate #" + i); out.println("===================================="); printX509Cert(cert, out); out.println(); } } catch (Exception e) { if (debug) { e.printStackTrace(); } } } // Set to true where there's something to print if (certs.length > 0) { certPrinted[0] = true; } } } }, null); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); // HTTPS instead of raw SSL, so that -Dhttps.proxyHost and // -Dhttps.proxyPort can be used. Since we only go through // the handshake process, an HTTPS server is not needed. // This program should be able to deal with any SSL-based // network service. Exception ex = null; try { new URL("https://" + sslserver).openConnection().connect(); } catch (Exception e) { ex = e; } // If the certs are not printed out, we consider it an error even // if the URL connection is successful. if (!certPrinted[0]) { Exception e = new Exception( rb.getString("No.certificate.from.the.SSL.server")); if (ex != null) { e.initCause(ex); } throw e; } } else { InputStream inStream = System.in; if (filename != null) { inStream = new FileInputStream(filename); } try { printCertFromStream(inStream, out); } finally { if (inStream != System.in) { inStream.close(); } } } } /** * Creates a self-signed certificate, and stores it as a single-element * certificate chain. */ private void doSelfCert(String alias, String dname, String sigAlgName) throws Exception { if (alias == null) { alias = keyAlias; } Pair<Key,char[]> objs = recoverKey(alias, storePass, keyPass); PrivateKey privKey = (PrivateKey)objs.fst; if (keyPass == null) keyPass = objs.snd; // Determine the signature algorithm if (sigAlgName == null) { sigAlgName = getCompatibleSigAlgName(privKey.getAlgorithm()); } // Get the old certificate Certificate oldCert = keyStore.getCertificate(alias); if (oldCert == null) { MessageFormat form = new MessageFormat (rb.getString("alias.has.no.public.key")); Object[] source = {alias}; throw new Exception(form.format(source)); } if (!(oldCert instanceof X509Certificate)) { MessageFormat form = new MessageFormat (rb.getString("alias.has.no.X.509.certificate")); Object[] source = {alias}; throw new Exception(form.format(source)); } // convert to X509CertImpl, so that we can modify selected fields // (no public APIs available yet) byte[] encoded = oldCert.getEncoded(); X509CertImpl certImpl = new X509CertImpl(encoded); X509CertInfo certInfo = (X509CertInfo)certImpl.get(X509CertImpl.NAME + "." + X509CertImpl.INFO); // Extend its validity Date firstDate = getStartDate(startDate); Date lastDate = new Date(); lastDate.setTime(firstDate.getTime() + validity*1000L*24L*60L*60L); CertificateValidity interval = new CertificateValidity(firstDate, lastDate); certInfo.set(X509CertInfo.VALIDITY, interval); // Make new serial number certInfo.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber( new java.util.Random().nextInt() & 0x7fffffff)); // Set owner and issuer fields X500Name owner; if (dname == null) { // Get the owner name from the certificate owner = (X500Name)certInfo.get(X509CertInfo.SUBJECT + "." + CertificateSubjectName.DN_NAME); } else { // Use the owner name specified at the command line owner = new X500Name(dname); certInfo.set(X509CertInfo.SUBJECT + "." + CertificateSubjectName.DN_NAME, owner); } // Make issuer same as owner (self-signed!) certInfo.set(X509CertInfo.ISSUER + "." + CertificateIssuerName.DN_NAME, owner); // The inner and outer signature algorithms have to match. // The way we achieve that is really ugly, but there seems to be no // other solution: We first sign the cert, then retrieve the // outer sigalg and use it to set the inner sigalg X509CertImpl newCert = new X509CertImpl(certInfo); newCert.sign(privKey, sigAlgName); AlgorithmId sigAlgid = (AlgorithmId)newCert.get(X509CertImpl.SIG_ALG); certInfo.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, sigAlgid); certInfo.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); CertificateExtensions ext = createV3Extensions( null, (CertificateExtensions)certInfo.get(X509CertInfo.EXTENSIONS), v3ext, oldCert.getPublicKey(), null); certInfo.set(X509CertInfo.EXTENSIONS, ext); // Sign the new certificate newCert = new X509CertImpl(certInfo); newCert.sign(privKey, sigAlgName); // Store the new certificate as a single-element certificate chain keyStore.setKeyEntry(alias, privKey,Lines 2001–2500 of 4217. Previous lines Load more
} } private static <T> Iterable<T> e2i(final Enumeration<T> e) { return new Iterable<T>() { @Override public Iterator<T> iterator() { return new Iterator<T>() { @Override public boolean hasNext() { return e.hasMoreElements(); } @Override public T next() { return e.nextElement(); } public void remove() { throw new UnsupportedOperationException("Not supported yet."); } }; } }; } /** * Loads CRLs from a source. This method is also called in JarSigner. * @param src the source, which means System.in if null, or a URI, * or a bare file path name */ public static Collection<? extends CRL> loadCRLs(String src) throws Exception { InputStream in = null; URI uri = null; if (src == null) { in = System.in; } else { try { uri = new URI(src); if (uri.getScheme().equals("ldap")) { // No input stream for LDAP } else { in = uri.toURL().openStream(); } } catch (Exception e) { try { in = new FileInputStream(src); } catch (Exception e2) { if (uri == null || uri.getScheme() == null) { throw e2; // More likely a bare file path } else { throw e; // More likely a protocol or network problem } } } } if (in != null) { try { // Read the full stream before feeding to X509Factory, // otherwise, keytool -gencrl | keytool -printcrl // might not work properly, since -gencrl is slow // and there's no data in the pipe at the beginning. ByteArrayOutputStream bout = new ByteArrayOutputStream(); byte[] b = new byte[4096]; while (true) { int len = in.read(b); if (len < 0) break; bout.write(b, 0, len); } return CertificateFactory.getInstance("X509").generateCRLs( new ByteArrayInputStream(bout.toByteArray())); } finally { if (in != System.in) { in.close(); } } } else { // must be LDAP, and uri is not null String path = uri.getPath(); if (path.charAt(0) == '/') path = path.substring(1); LDAPCertStoreHelper h = new LDAPCertStoreHelper(); CertStore s = h.getCertStore(uri); X509CRLSelector sel = h.wrap(new X509CRLSelector(), null, path); return s.getCRLs(sel); } } /** * Returns CRLs described in a X509Certificate's CRLDistributionPoints * Extension. Only those containing a general name of type URI are read. */ public static List<CRL> readCRLsFromCert(X509Certificate cert) throws Exception { List<CRL> crls = new ArrayList<>(); CRLDistributionPointsExtension ext = X509CertImpl.toImpl(cert).getCRLDistributionPointsExtension(); if (ext == null) return crls; for (DistributionPoint o: (List<DistributionPoint>) ext.get(CRLDistributionPointsExtension.POINTS)) { GeneralNames names = o.getFullName(); if (names != null) { for (GeneralName name: names.names()) { if (name.getType() == GeneralNameInterface.NAME_URI) { URIName uriName = (URIName)name.getName(); for (CRL crl: KeyTool.loadCRLs(uriName.getName())) { if (crl instanceof X509CRL) { crls.add((X509CRL)crl); } } break; // Different name should point to same CRL } } } } return crls; } private static String verifyCRL(KeyStore ks, CRL crl) throws Exception { X509CRLImpl xcrl = (X509CRLImpl)crl; X500Principal issuer = xcrl.getIssuerX500Principal(); for (String s: e2i(ks.aliases())) { Certificate cert = ks.getCertificate(s); if (cert instanceof X509Certificate) { X509Certificate xcert = (X509Certificate)cert; if (xcert.getSubjectX500Principal().equals(issuer)) { try { ((X509CRLImpl)crl).verify(cert.getPublicKey()); return s; } catch (Exception e) { } } } } return null; } private void doPrintCRL(String src, PrintStream out) throws Exception { for (CRL crl: loadCRLs(src)) { printCRL(crl, out); String issuer = null; if (caks != null) { issuer = verifyCRL(caks, crl); if (issuer != null) { System.out.println("Verified by " + issuer + " in cacerts"); } } if (issuer == null && keyStore != null) { issuer = verifyCRL(keyStore, crl); if (issuer != null) { System.out.println("Verified by " + issuer + " in keystore"); } } if (issuer == null) { out.println(rb.getString ("STAR")); out.println("WARNING: not verified. Make sure -keystore and -alias are correct."); out.println(rb.getString ("STARNN")); } } } private void printCRL(CRL crl, PrintStream out) throws Exception { if (rfc) { X509CRL xcrl = (X509CRL)crl; out.println("-----BEGIN X509 CRL-----"); new BASE64Encoder().encodeBuffer(xcrl.getEncoded(), out); out.println("-----END X509 CRL-----"); } else { out.println(crl.toString()); } } private void doPrintCertReq(InputStream in, PrintStream out) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuffer sb = new StringBuffer(); boolean started = false; while (true) { String s = reader.readLine(); if (s == null) break; if (!started) { if (s.startsWith("-----")) { started = true; } } else { if (s.startsWith("-----")) { break; } sb.append(s); } } PKCS10 req = new PKCS10(new BASE64Decoder().decodeBuffer(new String(sb))); PublicKey pkey = req.getSubjectPublicKeyInfo(); out.printf(rb.getString("PKCS.10.Certificate.Request.Version.1.0.Subject.s.Public.Key.s.format.s.key."), req.getSubjectName(), pkey.getFormat(), pkey.getAlgorithm()); for (PKCS10Attribute attr: req.getAttributes().getAttributes()) { ObjectIdentifier oid = attr.getAttributeId(); if (oid.equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) { CertificateExtensions exts = (CertificateExtensions)attr.getAttributeValue(); if (exts != null) { printExtensions(rb.getString("Extension.Request."), exts, out); } } else { out.println(attr.getAttributeId()); out.println(attr.getAttributeValue()); } } if (debug) { out.println(req); // Just to see more, say, public key length... } } /** * Reads a certificate (or certificate chain) and prints its contents in * a human readable format. */ private void printCertFromStream(InputStream in, PrintStream out) throws Exception { Collection<? extends Certificate> c = null; try { c = cf.generateCertificates(in); } catch (CertificateException ce) { throw new Exception(rb.getString("Failed.to.parse.input"), ce); } if (c.isEmpty()) { throw new Exception(rb.getString("Empty.input")); } Certificate[] certs = c.toArray(new Certificate[c.size()]); for (int i=0; i<certs.length; i++) { X509Certificate x509Cert = null; try { x509Cert = (X509Certificate)certs[i]; } catch (ClassCastException cce) { throw new Exception(rb.getString("Not.X.509.certificate")); } if (certs.length > 1) { MessageFormat form = new MessageFormat (rb.getString("Certificate.i.1.")); Object[] source = {new Integer(i + 1)}; out.println(form.format(source)); } if (rfc) dumpCert(x509Cert, out); else printX509Cert(x509Cert, out); if (i < (certs.length-1)) { out.println(); } } } private void doPrintCert(final PrintStream out) throws Exception { if (jarfile != null) { JarFile jf = new JarFile(jarfile, true); Enumeration<JarEntry> entries = jf.entries(); Set<CodeSigner> ss = new HashSet<>(); byte[] buffer = new byte[8192]; int pos = 0; while (entries.hasMoreElements()) { JarEntry je = entries.nextElement(); InputStream is = null; try { is = jf.getInputStream(je); while (is.read(buffer) != -1) { // we just read. this will throw a SecurityException // if a signature/digest check fails. This also // populate the signers } } finally { if (is != null) { is.close(); } } CodeSigner[] signers = je.getCodeSigners(); if (signers != null) { for (CodeSigner signer: signers) { if (!ss.contains(signer)) { ss.add(signer); out.printf(rb.getString("Signer.d."), ++pos); out.println(); out.println(); out.println(rb.getString("Signature.")); out.println(); for (Certificate cert: signer.getSignerCertPath().getCertificates()) { X509Certificate x = (X509Certificate)cert; if (rfc) { out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n"); dumpCert(x, out); } else { printX509Cert(x, out); } out.println(); } Timestamp ts = signer.getTimestamp(); if (ts != null) { out.println(rb.getString("Timestamp.")); out.println(); for (Certificate cert: ts.getSignerCertPath().getCertificates()) { X509Certificate x = (X509Certificate)cert; if (rfc) { out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n"); dumpCert(x, out); } else { printX509Cert(x, out); } out.println(); } } } } } } jf.close(); if (ss.size() == 0) { out.println(rb.getString("Not.a.signed.jar.file")); } } else if (sslserver != null) { SSLContext sc = SSLContext.getInstance("SSL"); final boolean[] certPrinted = new boolean[1]; sc.init(null, new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { for (int i=0; i<certs.length; i++) { X509Certificate cert = certs[i]; try { if (rfc) { dumpCert(cert, out); } else { out.println("Certificate #" + i); out.println("===================================="); printX509Cert(cert, out); out.println(); } } catch (Exception e) { if (debug) { e.printStackTrace(); } } } // Set to true where there's something to print if (certs.length > 0) { certPrinted[0] = true; } } } }, null); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); // HTTPS instead of raw SSL, so that -Dhttps.proxyHost and // -Dhttps.proxyPort can be used. Since we only go through // the handshake process, an HTTPS server is not needed. // This program should be able to deal with any SSL-based // network service. Exception ex = null; try { new URL("https://" + sslserver).openConnection().connect(); } catch (Exception e) { ex = e; } // If the certs are not printed out, we consider it an error even // if the URL connection is successful. if (!certPrinted[0]) { Exception e = new Exception( rb.getString("No.certificate.from.the.SSL.server")); if (ex != null) { e.initCause(ex); } throw e; } } else { InputStream inStream = System.in; if (filename != null) { inStream = new FileInputStream(filename); } try { printCertFromStream(inStream, out); } finally { if (inStream != System.in) { inStream.close(); } } } } /** * Creates a self-signed certificate, and stores it as a single-element * certificate chain. */ private void doSelfCert(String alias, String dname, String sigAlgName) throws Exception { if (alias == null) { alias = keyAlias; } Pair<Key,char[]> objs = recoverKey(alias, storePass, keyPass); PrivateKey privKey = (PrivateKey)objs.fst; if (keyPass == null) keyPass = objs.snd; // Determine the signature algorithm if (sigAlgName == null) { sigAlgName = getCompatibleSigAlgName(privKey.getAlgorithm()); } // Get the old certificate Certificate oldCert = keyStore.getCertificate(alias); if (oldCert == null) { MessageFormat form = new MessageFormat (rb.getString("alias.has.no.public.key")); Object[] source = {alias}; throw new Exception(form.format(source)); } if (!(oldCert instanceof X509Certificate)) { MessageFormat form = new MessageFormat (rb.getString("alias.has.no.X.509.certificate")); Object[] source = {alias}; throw new Exception(form.format(source)); } // convert to X509CertImpl, so that we can modify selected fields // (no public APIs available yet) byte[] encoded = oldCert.getEncoded(); X509CertImpl certImpl = new X509CertImpl(encoded); X509CertInfo certInfo = (X509CertInfo)certImpl.get(X509CertImpl.NAME + "." + X509CertImpl.INFO); // Extend its validity Date firstDate = getStartDate(startDate); Date lastDate = new Date(); lastDate.setTime(firstDate.getTime() + validity*1000L*24L*60L*60L); CertificateValidity interval = new CertificateValidity(firstDate, lastDate); certInfo.set(X509CertInfo.VALIDITY, interval); // Make new serial number certInfo.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber( new java.util.Random().nextInt() & 0x7fffffff)); // Set owner and issuer fields X500Name owner; if (dname == null) { // Get the owner name from the certificate owner = (X500Name)certInfo.get(X509CertInfo.SUBJECT + "." + CertificateSubjectName.DN_NAME); } else { // Use the owner name specified at the command line owner = new X500Name(dname); certInfo.set(X509CertInfo.SUBJECT + "." + CertificateSubjectName.DN_NAME, owner); } // Make issuer same as owner (self-signed!) certInfo.set(X509CertInfo.ISSUER + "." + CertificateIssuerName.DN_NAME, owner); // The inner and outer signature algorithms have to match. // The way we achieve that is really ugly, but there seems to be no // other solution: We first sign the cert, then retrieve the // outer sigalg and use it to set the inner sigalg X509CertImpl newCert = new X509CertImpl(certInfo); newCert.sign(privKey, sigAlgName); AlgorithmId sigAlgid = (AlgorithmId)newCert.get(X509CertImpl.SIG_ALG); certInfo.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, sigAlgid); certInfo.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); CertificateExtensions ext = createV3Extensions( null, (CertificateExtensions)certInfo.get(X509CertInfo.EXTENSIONS), v3ext, oldCert.getPublicKey(), null); certInfo.set(X509CertInfo.EXTENSIONS, ext); // Sign the new certificate newCert = new X509CertImpl(certInfo); newCert.sign(privKey, sigAlgName); // Store the new certificate as a single-element certificate chain keyStore.setKeyEntry(alias, privKey,