KeyStore.load(InputStream stream,char [] password); 我如何知道客户端的密码?

Jav*_*ool 2 java ssl certificate

我知道要加载证书使用,我需要打电话KeyStore.load(InputStream, char[]);.如果需要密码,如何在客户端加载证书?连接到Google时我不需要这个,但我想使用信任管理器来验证Google证书.我也无法在SSLServerSocket不加载证书的情况下进行连接.
编辑:添加代码:

package testing;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SSLClientTest {
    public static void main(String[] args) {
        int port = 443;
        String host = "google.com";

        try {

            SSLContext sc = SSLContext.getInstance("TLSv1.2");
            KeyStore ks = KeyStore.getInstance("JKS");
            InputStream ksIs = new FileInputStream("securecert.certificate");
            try {
                ks.load(ksIs, "pwdpwdpwd".toCharArray());
            } finally {
                if (ksIs != null) {
                    ksIs.close();
                }
            }
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, "pwdpwdpwd".toCharArray());
            sc.init(kmf.getKeyManagers(),
                    new TrustManager[] { new MyTrustManager() }, null);

            SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
                    .getDefault();
            SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
            socket.startHandshake();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            System.out.println(in.readLine());
            in.close();
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static final class MyTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[] {};
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我必须加载证书,securecert.certificate,代码为ks.load(InputStream,char []); 我当然知道密码,但如果不知道怎么办?那我怎么能用信任管理器验证证书呢?这段代码只是锁定.请回答.谢谢!

alb*_*iff 6

似乎您需要通过客户端身份验证,SSL并且您希望让用户输入他的密码keystore.根据你的解释,我想每个安装的客户端都有自己keystore的本地路径(如果不是问题有废话,因为如果keystore总是相同的话,你不需要每次都传递不同的密码...但是如果这是你需要检查这个客户端是否安全的情况.

因此,要让用户输入密码,您可以keystore以不同的方式实例化而不是使用KeyStore.getInstance(InputStream, Char[]),您可以使用KeyStore.Builder.newInstanceKeyStore.CallbackHandlerProtection方法,并且您必须创建一个实现的类javax.security.auth.callback.CallbackHandler,此类必须覆盖handle()方法,例如使用swing或awt面板来让用户介绍密码.下面我将向您展示一些示例代码,以指导您完成以下步骤:

加载密钥库

import java.io.File;
import java.security.KeyStore;
import java.security.Provider;
import java.util.Enumeration;

public class KeyStoreCallbackSample {

    public static void main(String args[]) throws Exception {
        // instantiate a keystore to get the provider for specific type
        KeyStore ks = KeyStore.getInstance("JKS");

        // create the callback handler to get the password
        KeyStore.CallbackHandlerProtection cbhp = new KeyStore.CallbackHandlerProtection(new YourImplementationCallbackHander());
        // create the builder passing keystoreType, provider, keystore file, and callbackhandler
        KeyStore.Builder builder = KeyStore.Builder.newInstance("JKS", ks.getProvider(), new File("/path/YourKeyStore.jks"), cbhp);
        // create the keystore
        ks = builder.getKeyStore();

        // print the keystores alias to check if all it's load correctly
        Enumeration<String> aliases = ks.aliases();
        while(aliases.hasMoreElements()){
            System.out.println(aliases.nextElement());
        }       
    }
}   
Run Code Online (Sandbox Code Playgroud)

CallbackHandler实现

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

/**
 * PIN handler for keystores
 */
public class PinInputHandler implements CallbackHandler {

    private char[] lastPassword;

    public PinInputHandler(){}

    // implement this method to handle the callback
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (Callback cb : callbacks) {
            if (cb instanceof javax.security.auth.callback.PasswordCallback) {
                javax.security.auth.callback.PasswordCallback pcb = (javax.security.auth.callback.PasswordCallback) cb;
                try {
                    this.lastPassword = // HERE YOUR SWING OR AWT OR ANOTHER WAY TO GET THE PASSWORD FROM THE CLIENT
                } catch (Exception e) {}
                pcb.setPassword(this.lastPassword);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您需要更多的信息,您可以检查的KeyStore,KeyStore.Builder,KeyStore.CallbackHandlerProtectionCallbackHandler文档.

希望这可以帮助,