diff options
author | Omair Majid <[email protected]> | 2010-11-11 11:43:13 -0500 |
---|---|---|
committer | Omair Majid <[email protected]> | 2010-11-11 11:43:13 -0500 |
commit | 4b48fb654279154b6126c86d5998e02d74d125fb (patch) | |
tree | 7f037a171f123564b80f5c1d237d26161ce7e8e4 /netx/net/sourceforge/jnlp/security | |
parent | ec49901d9f4844acd69a51ebc0c7fa548be70ff3 (diff) |
integrate support for multiple KeyStores into the various validators
2010-11-11 Omair Majid <[email protected]>
* netx/net/sourceforge/jnlp/runtime/Boot.java (main): Move trust
manager initialization code into JNLPRuntime.initialize.
* plugin/icedteanp/java/sun/applet/PluginMain.java
(init): Likewise.
* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java (initialize):
Set the default SSL TrustManager here.
* netx/net/sourceforge/jnlp/security/CertWarningPane.java
(CheckBoxListener.actionPerformed): Add this certificate into
user's trusted certificate store.
* netx/net/sourceforge/jnlp/tools/KeyTool.java
(addToKeyStore(File,KeyStore)): Move to CertificateUtils.
(addToKeyStore(X509Certificate,KeyStore)): Likewise.
(dumpCert): Likewise.
* netx/net/sourceforge/jnlp/security/CertificateUtils.java: New
class.
(addToKeyStore(File,KeyStore)): Moved from KeyTool.
(addToKeyStore(X509Certificate,KeyStore)): Likewise.
(dumpCert): Likewise.
(inKeyStores): New method.
* netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java
(getRootInCacerts): Check all available CA store to check if
root is in CA certificates.
* netx/net/sourceforge/jnlp/security/KeyStores.java
(getKeyStore(Level,Type,boolean)): Add security check.
(getClientKeyStores): New method.
* netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java
(VariableX509TrustManager): Initialize multiple CA, certificate and
client trust managers.
(checkClientTrusted): Check all the client TrustManagers if
certificate is trusted.
(checkAllManagers): Check multiple CA certificates and trusted
certificates to determine if the certificate chain can be trusted.
(isExplicitlyTrusted): Check with multiple TrustManagers.
(getAcceptedIssuers): Gather results from multiple TrustManagers.
* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
(ImportButtonListener): Use CertificateUtils instead of KeyTool.
* netx/net/sourceforge/jnlp/tools/JarSigner.java
(checkTrustedCerts): Use multiple key stores to check if certificate
is directly trusted and if the root is trusted.
Diffstat (limited to 'netx/net/sourceforge/jnlp/security')
6 files changed, 350 insertions, 80 deletions
diff --git a/netx/net/sourceforge/jnlp/security/CertWarningPane.java b/netx/net/sourceforge/jnlp/security/CertWarningPane.java index bad2337..e1ebecb 100644 --- a/netx/net/sourceforge/jnlp/security/CertWarningPane.java +++ b/netx/net/sourceforge/jnlp/security/CertWarningPane.java @@ -47,6 +47,9 @@ import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.X509Certificate; @@ -62,8 +65,9 @@ import javax.swing.SwingConstants; import net.sourceforge.jnlp.JNLPFile; import net.sourceforge.jnlp.PluginBridge; import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.security.KeyStores.Level; +import net.sourceforge.jnlp.security.KeyStores.Type; import net.sourceforge.jnlp.security.SecurityWarning.AccessType; -import net.sourceforge.jnlp.tools.KeyTool; /** * Provides the panel for using inside a SecurityWarningDialog. These dialogs are @@ -232,25 +236,28 @@ public class CertWarningPane extends SecurityDialogPanel { } } - /** - * Updates the user's KeyStore of trusted Certificates. - */ - private class CheckBoxListener implements ActionListener { - public void actionPerformed(ActionEvent e) { - if (alwaysTrust != null && alwaysTrust.isSelected()) { - try { - KeyTool kt = new KeyTool(); - Certificate c = parent.getJarSigner().getPublisher(); - kt.importCert(c); - if (JNLPRuntime.isDebug()) { - System.out.println("certificate is now permanently trusted"); - } - } catch (Exception ex) { - //TODO: Let NetX show a dialog here notifying user - //about being unable to add cert to keystore - } - } + /** + * Updates the user's KeyStore of trusted Certificates. + */ + private class CheckBoxListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (alwaysTrust != null && alwaysTrust.isSelected()) { + try { + KeyStore ks = KeyStores.getKeyStore(Level.USER, Type.CERTS); + X509Certificate c = (X509Certificate) parent.getJarSigner().getPublisher(); + CertificateUtils.addToKeyStore(c, ks); + OutputStream os = new FileOutputStream(KeyStores.getKeyStoreLocation(Level.USER, Type.CERTS)); + ks.store(os, KeyStores.getPassword()); + if (JNLPRuntime.isDebug()) { + System.out.println("certificate is now permanently trusted"); + } + } catch (Exception ex) { + // TODO: Let NetX show a dialog here notifying user + // about being unable to add cert to keystore + ex.printStackTrace(); } + } } + } } diff --git a/netx/net/sourceforge/jnlp/security/CertificateUtils.java b/netx/net/sourceforge/jnlp/security/CertificateUtils.java new file mode 100644 index 0000000..af48a1e --- /dev/null +++ b/netx/net/sourceforge/jnlp/security/CertificateUtils.java @@ -0,0 +1,151 @@ +/* CertificateUtils.java + Copyright (C) 2010 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package net.sourceforge.jnlp.security; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.math.BigInteger; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Random; + +import net.sourceforge.jnlp.runtime.JNLPRuntime; + +import sun.misc.BASE64Encoder; +import sun.security.provider.X509Factory; + +/** + * Common utilities to manipulate certificates. Provides methods to add + * Certificates to a KeyStores, check if certificates already exist in a + * KeyStore and printing certificates. + */ +public class CertificateUtils { + + /** + * Adds the X509Certficate in the file to the KeyStore. Note that it does + * not update the copy of the KeyStore on disk. + */ + public static final void addToKeyStore(File file, KeyStore ks) throws CertificateException, + IOException, KeyStoreException { + if (JNLPRuntime.isDebug()) { + System.out.println("Importing certificate from " + file + " into " + ks); + } + + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); + CertificateFactory cf = CertificateFactory.getInstance("X509"); + X509Certificate cert = null; + + try { + cert = (X509Certificate) cf.generateCertificate(bis); + } catch (ClassCastException cce) { + throw new CertificateException("Input file is not an X509 Certificate", cce); + } + + addToKeyStore(cert, ks); + } + + /** + * Adds an X509Certificate to the KeyStore. Note that it does not update the + * copy of the KeyStore on disk. + */ + public static final void addToKeyStore(X509Certificate cert, KeyStore ks) + throws KeyStoreException { + if (JNLPRuntime.isDebug()) { + System.out.println("Importing " + cert.getSubjectX500Principal().getName()); + } + + String alias = null; + + // does this certificate already exist? + alias = ks.getCertificateAlias(cert); + if (alias != null) { + return; + } + + // create a unique alias for this new certificate + Random random = new Random(); + do { + alias = new BigInteger(20, random).toString(); + } while (ks.getCertificate(alias) != null); + + ks.setCertificateEntry(alias, cert); + } + + /** + * Checks whether an X509Certificate is already in one of the keystores + * @param c the certificate + * @param keyStores the KeyStores to check in + * @return true if the certificate is present in one of the keystores, false otherwise + */ + public static final boolean inKeyStores(X509Certificate c, KeyStore[] keyStores) { + for (int i = 0; i < keyStores.length; i++) { + try { + if (keyStores[i].getCertificateAlias(c) != null) { + if (JNLPRuntime.isDebug()) { + System.out.println(c.getSubjectX500Principal().getName() + " found in cacerts"); + } + return true; + } + } catch (KeyStoreException e) { + e.printStackTrace(); + // continue + } + } + return false; + } + + /** + * Writes the certificate in base64 encoded from to the print stream. + * See http://tools.ietf.org/html/rfc4945#section-6.1 for more information + */ + public static void dump(Certificate cert, PrintStream out) throws IOException, + CertificateException { + + BASE64Encoder encoder = new BASE64Encoder(); + out.println(X509Factory.BEGIN_CERT); + encoder.encodeBuffer(cert.getEncoded(), out); + out.println(X509Factory.END_CERT); + } +} diff --git a/netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java b/netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java index 6cf7c9d..966023b 100644 --- a/netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java +++ b/netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java @@ -40,6 +40,7 @@ package net.sourceforge.jnlp.security; import static net.sourceforge.jnlp.runtime.Translator.R; import java.io.IOException; +import java.security.KeyStore; import java.security.cert.CertPath; import java.security.cert.Certificate; import java.security.cert.CertificateException; @@ -52,7 +53,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import net.sourceforge.jnlp.tools.KeyTool; import sun.security.util.DerValue; import sun.security.util.HostnameChecker; import sun.security.x509.X500Name; @@ -213,8 +213,8 @@ public class HttpsCertVerifier implements CertVerifier { public boolean getRootInCacerts() { try { - KeyTool kt = new KeyTool(); - return kt.checkCacertsForCertificate(getRoot()); + KeyStore[] caCertsKeyStores = KeyStores.getCAKeyStores(); + return CertificateUtils.inKeyStores((X509Certificate)getRoot(), caCertsKeyStores); } catch (Exception e) { } return false; diff --git a/netx/net/sourceforge/jnlp/security/KeyStores.java b/netx/net/sourceforge/jnlp/security/KeyStores.java index 94ea56e..05bc150 100644 --- a/netx/net/sourceforge/jnlp/security/KeyStores.java +++ b/netx/net/sourceforge/jnlp/security/KeyStores.java @@ -41,6 +41,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.security.AllPermission; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -111,6 +112,11 @@ public final class KeyStores { * @return a KeyStore containing certificates from the appropriate */ public static final KeyStore getKeyStore(Level level, Type type, boolean create) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new AllPermission()); + } + String location = getKeyStoreLocation(level, type); KeyStore ks = null; try { @@ -189,6 +195,29 @@ public final class KeyStores { } /** + * Returns KeyStores containing trusted client certificates + * + * @return an array of KeyStore objects that can be used to check client + * authentication certificates + */ + public static KeyStore[] getClientKeyStores() { + List<KeyStore> result = new ArrayList<KeyStore>(); + KeyStore ks = null; + + ks = getKeyStore(Level.SYSTEM, Type.CLIENT_CERTS); + if (ks != null) { + result.add(ks); + } + + ks = getKeyStore(Level.USER, Type.CLIENT_CERTS); + if (ks != null) { + result.add(ks); + } + + return result.toArray(new KeyStore[result.size()]); + } + + /** * Returns the location of a KeyStore corresponding to the given level and type. * @param level * @param type @@ -336,4 +365,5 @@ public final class KeyStores { return ks; } + } diff --git a/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java b/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java index 5e9c981..d40513e 100644 --- a/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java +++ b/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java @@ -42,6 +42,8 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; @@ -60,59 +62,98 @@ import net.sourceforge.jnlp.security.SecurityWarning.AccessType; * different certificates that are not in the keystore. */ -public class VariableX509TrustManager extends X509ExtendedTrustManager { +final public class VariableX509TrustManager extends X509ExtendedTrustManager { - KeyStore userKeyStore = null; - KeyStore caKeyStore = null; + /** TrustManagers containing trusted CAs */ + private X509TrustManager[] caTrustManagers = null; - X509TrustManager userTrustManager = null; - X509TrustManager caTrustManager = null; + /** TrustManagers containing trusted certificates */ + private X509TrustManager[] certTrustManagers = null; - ArrayList<Certificate> temporarilyTrusted = new ArrayList<Certificate>(); - ArrayList<Certificate> temporarilyUntrusted = new ArrayList<Certificate>(); + /** TrustManagers containing trusted client certificates */ + private X509TrustManager[] clientTrustManagers = null; - static VariableX509TrustManager instance = null; + private ArrayList<Certificate> temporarilyTrusted = new ArrayList<Certificate>(); + private ArrayList<Certificate> temporarilyUntrusted = new ArrayList<Certificate>(); + + private static VariableX509TrustManager instance = null; /** * Constructor initializes the system, user and custom stores */ public VariableX509TrustManager() { + /* + * Load TrustManagers for trusted certificates + */ try { - userKeyStore = SecurityUtil.getUserKeyStore(); - TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); - tmFactory.init(userKeyStore); + /** KeyStores containing trusted certificates */ + KeyStore[] trustedCertKeyStores = KeyStores.getCertKeyStores(); + certTrustManagers = new X509TrustManager[trustedCertKeyStores.length]; + + for (int j = 0; j < trustedCertKeyStores.length; j++) { + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); + tmFactory.init(trustedCertKeyStores[j]); - // tm factory initialized, now get the managers so we can assign the X509 one - TrustManager[] trustManagers = tmFactory.getTrustManagers(); + // tm factory initialized, now get the managers so we can assign the X509 one + TrustManager[] trustManagers = tmFactory.getTrustManagers(); - for (int i=0; i < trustManagers.length; i++) { - if (trustManagers[i] instanceof X509TrustManager) { - userTrustManager = (X509TrustManager) trustManagers[i]; + for (int i = 0; i < trustManagers.length; i++) { + if (trustManagers[i] instanceof X509TrustManager) { + certTrustManagers[j] = (X509TrustManager) trustManagers[i]; + } } } - } catch (Exception e) { - // TODO Auto-generated catch block e.printStackTrace(); } + /* + * Load TrustManagers for trusted CAs + */ try { - caKeyStore = SecurityUtil.getCacertsKeyStore(); - TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); - tmFactory.init(caKeyStore); + /** KeyStores containing trusted CAs */ + KeyStore[] trustedCAKeyStores = KeyStores.getCAKeyStores(); + caTrustManagers = new X509TrustManager[trustedCAKeyStores.length]; + + for (int j = 0; j < caTrustManagers.length; j++) { + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); + tmFactory.init(trustedCAKeyStores[j]); - // tm factory initialized, now get the managers so we can extract the X509 one - TrustManager[] trustManagers = tmFactory.getTrustManagers(); + // tm factory initialized, now get the managers so we can extract the X509 one + TrustManager[] trustManagers = tmFactory.getTrustManagers(); - for (int i=0; i < trustManagers.length; i++) { - if (trustManagers[i] instanceof X509TrustManager) { - caTrustManager = (X509TrustManager) trustManagers[i]; + for (int i=0; i < trustManagers.length; i++) { + if (trustManagers[i] instanceof X509TrustManager) { + caTrustManagers[j] = (X509TrustManager) trustManagers[i]; + } } } + } catch (Exception e) { + e.printStackTrace(); + } + + /* + * Load TrustManagers for trusted clients certificates + */ + try { + KeyStore[] clientKeyStores = KeyStores.getClientKeyStores(); + clientTrustManagers = new X509TrustManager[clientKeyStores.length]; + for (int j = 0; j < clientTrustManagers.length; j++) { + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); + tmFactory.init(clientKeyStores[j]); + + // tm factory initialized, now get the managers so we can extract the X509 one + TrustManager[] trustManagers = tmFactory.getTrustManagers(); + + for (int i=0; i < trustManagers.length; i++) { + if (trustManagers[i] instanceof X509TrustManager) { + clientTrustManagers[j] = (X509TrustManager) trustManagers[i]; + } + } + } } catch (Exception e) { - // TODO Auto-generated catch block e.printStackTrace(); } } @@ -123,18 +164,23 @@ public class VariableX509TrustManager extends X509ExtendedTrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType, String hostName, String algorithm) throws CertificateException { - // First try catrustmanager, then try usertrustmanager - try { - caTrustManager.checkClientTrusted(chain, authType); - } catch (Exception caex) { + + boolean trusted = false; + ValidatorException savedException = null; + for (int i = 0; i < clientTrustManagers.length; i++) { try { - userTrustManager.checkClientTrusted(chain, authType); - } catch (Exception userex) { - // Do nothing here. This trust manager is intended to be used - // only in the plugin instance vm, which does not act as a - // server + clientTrustManagers[i].checkClientTrusted(chain, authType); + trusted = true; + break; + } catch (ValidatorException caex) { + savedException = caex; } } + if (trusted) { + return; + } + + throw savedException; } public void checkClientTrusted(X509Certificate[] chain, String authType) @@ -214,17 +260,45 @@ public class VariableX509TrustManager extends X509ExtendedTrustManager { * Check system, user and custom trust manager */ private void checkAllManagers(X509Certificate[] chain, String authType) throws CertificateException { - // First try catrustmanager, then try usertrustmanager, and finally, check temp trusted certs - try { - caTrustManager.checkServerTrusted(chain, authType); - } catch (ValidatorException caex) { + // first try CA TrustManagers + boolean trusted = false; + ValidatorException savedException = null; + for (int i = 0; i < caTrustManagers.length; i++) { try { - userTrustManager.checkServerTrusted(chain, authType); - } catch (ValidatorException uex) { - if (!temporarilyTrusted.contains(chain[0])) - throw (CertificateException) uex; + caTrustManagers[i].checkServerTrusted(chain, authType); + trusted = true; + break; + } catch (ValidatorException caex) { + savedException = caex; + } + } + if (trusted) { + return; + } + + // then try certificate TrustManagers + for (int i = 0; i < certTrustManagers.length; i++) { + try { + certTrustManagers[i].checkServerTrusted(chain, authType); + trusted = true; + break; + } catch (ValidatorException caex) { + savedException = caex; + } + } + if (trusted) { + return; + } + + // finally check temp trusted certs + if (!temporarilyTrusted.contains(chain[0])) { + if (savedException == null) { + // System.out.println("IMPOSSIBLE!"); + throw new ValidatorException(ValidatorException.T_SIGNATURE_ERROR, chain[0]); } + throw savedException; } + } /** @@ -233,23 +307,32 @@ public class VariableX509TrustManager extends X509ExtendedTrustManager { private boolean isExplicitlyTrusted(X509Certificate[] chain, String authType) { boolean explicitlyTrusted = false; - try { - userTrustManager.checkServerTrusted(chain, authType); - explicitlyTrusted = true; - } catch (ValidatorException uex) { - if (temporarilyTrusted.contains(chain[0])) + for (int i = 0; i < certTrustManagers.length; i++) { + try { + certTrustManagers[i].checkServerTrusted(chain, authType); explicitlyTrusted = true; - } catch (CertificateException ce) { - // do nothing, this means that the cert is not explicitly trusted + break; + } catch (ValidatorException uex) { + if (temporarilyTrusted.contains(chain[0])) { + explicitlyTrusted = true; + break; + } + } catch (CertificateException ce) { + // not explicitly trusted + } } return explicitlyTrusted; - } public X509Certificate[] getAcceptedIssuers() { - // delegate to default - return caTrustManager.getAcceptedIssuers(); + List<X509Certificate> issuers = new ArrayList<X509Certificate>(); + + for (int i = 0; i < caTrustManagers.length; i++) { + issuers.addAll(Arrays.asList(caTrustManagers[i].getAcceptedIssuers())); + } + + return issuers.toArray(new X509Certificate[issuers.size()]); } /** diff --git a/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java b/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java index d0ac050..d07e741 100644 --- a/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java +++ b/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java @@ -71,11 +71,11 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.DefaultTableModel; +import net.sourceforge.jnlp.security.CertificateUtils; import net.sourceforge.jnlp.security.KeyStores; import net.sourceforge.jnlp.security.SecurityUtil; import net.sourceforge.jnlp.security.SecurityWarningDialog; import net.sourceforge.jnlp.security.KeyStores.Level; -import net.sourceforge.jnlp.tools.KeyTool; public class CertificatePane extends JPanel { @@ -359,9 +359,8 @@ public class CertificatePane extends JPanel { int returnVal = chooser.showOpenDialog(parent); if(returnVal == JFileChooser.APPROVE_OPTION) { try { - KeyTool kt = new KeyTool(); KeyStore ks = keyStore; - kt.addToKeyStore(chooser.getSelectedFile(), ks); + CertificateUtils.addToKeyStore(chooser.getSelectedFile(), ks); OutputStream os = new FileOutputStream( KeyStores.getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType)); ks.store(os, KeyStores.getPassword()); @@ -399,7 +398,7 @@ public class CertificatePane extends JPanel { if (alias != null) { Certificate c = keyStore.getCertificate(alias); PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath()); - KeyTool.dumpCert(c, ps); + CertificateUtils.dump(c, ps); repopulateTables(); } } |