繁体   English   中英

使用.cer证书发出HTTPS请求

[英]Using .cer certificate to make an HTTPS request

我已经看到了这个问题: 需要使用.cer证书执行GET&POST HTTPS请求

我的完全不同:

是否可以使用Java(香草或使用任何库),信任服务器证书并提供客户端证书来发出HTTPS请求,而无需使用密钥库,而是使用普通证书?

我拥有X.509格式的两个证书,并且我不想在密钥库中拥有所有证书。

这是一个粗糙的例子。 表示X509KeyManager装饰器。

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(null, null);

X509KeyManager manager = (X509KeyManager) kmf.getKeyManagers()[0];
KeyManager km = new X509KeyManager() {
    @Override
    public String[] getClientAliases(String s, Principal[] principals) {
        return manager.getServerAliases(s, principals);
    }

    @Override
    public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket) {
        return manager.chooseClientAlias(strings, principals, socket);
    }

    @Override
    public String[] getServerAliases(String s, Principal[] principals) {
        return manager.getServerAliases(s, principals);
    }

    @Override
    public String chooseServerAlias(String s, Principal[] principals, Socket socket) {
        return manager.chooseServerAlias(s, principals, socket);
    }

    @Override
    public X509Certificate[] getCertificateChain(String s) {
        // You can use `s` to select the appropriate file

        try {
            File file = new File("path to certificate");

            try(InputStream is = new FileInputStream(file)) {
                CertificateFactory factory = CertificateFactory.getInstance("X.509");
                return new X509Certificate[] {
                        (X509Certificate) factory.generateCertificate(is)
                };
            }
        }
        catch (CertificateException| IOException  e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public PrivateKey getPrivateKey(String s) {
        // You can use `s` to select the appropriate file

        // load and private key from selected certificate
        // this use for certificate authorisation

        try {
            File file = new File("private key file");
            byte buffer[] = Files.readAllBytes(file.toPath());

            KeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory factory = KeyFactory.getInstance("RSA");

            return factory.generatePrivate(keySpec);
        }
        catch (NoSuchAlgorithmException | IOException | InvalidKeySpecException e) {
            e.printStackTrace();
        }

        return null;
    }
};

TrustManager tm = new X509TrustManager() {
    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

    }

    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        try {
            File file = new File("path to certificate");

            try(InputStream is = new FileInputStream(file)) {
                CertificateFactory factory = CertificateFactory.getInstance("X.509");
                return new X509Certificate[] {
                        (X509Certificate) factory.generateCertificate(is)
                };
            }
        }
        catch (CertificateException| IOException  e) {
            e.printStackTrace();
        }

        return null;
    }
};

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore)null); //use java system trust certificates

TrustManager managers[] = new TrustManager[tmf.getTrustManagers().length + 1];
System.arraycopy(tmf.getTrustManagers(), 0, managers, 0, tmf.getTrustManagers().length);
managers[managers.length - 1] = tm;

SSLContext context = SSLContext.getInstance("TLS");
context.init(new KeyManager[]{ km }, managers, new SecureRandom());

URL url = new URL("https://............/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(connection.getSSLSocketFactory());

connection.connect();

如果您确实不想创建新的密钥库文件,则可以使用KeyStore API在内存中创建并直接加载证书。

InputStream is = new FileInputStream("somecert.cer");
// You could get a resource as a stream instead.

CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate)cf.generateCertificate(is);

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null); // You don't need the KeyStore instance to come from a file.
ks.setCertificateEntry("caCert", caCert);

tmf.init(ks);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

另外,如果要避免修改默认的cacerts文件,则需要实现自己的TrustManager。 但是,TrustManager需要加载密钥库,因此您可以创建仅导入证书的新密钥库文件。

keytool -import -alias ca -file somecert.cer -keystore truststore.jks -storepass changeit

并使用类似以下代码片段的方式加载密钥库文件。

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
// Using null here initialises the TMF with the default trust store.
tmf.init((KeyStore) null);

// Get hold of the default trust manager
X509TrustManager defaultTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
    if (tm instanceof X509TrustManager) {
        defaultTm = (X509TrustManager) tm;
        break;
    }
}

FileInputStream myKeys = new FileInputStream("truststore.jks");

// Do the same with your trust store this time
// Adapt how you load the keystore to your needs
KeyStore myTrustStore = KeyStore.getInstance(KeyStore.getDefaultType());
myTrustStore.load(myKeys, "password".toCharArray());

myKeys.close();

tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(myTrustStore);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM