我有一个包含证书、私钥和信任链的.pem文件,以及使用openssl pkcs12-export从中生成的.p12文件:
< code > OpenSSL pkcs12-export-out file . p12-in file . PEM-inkey file . PEM-passin pass:password-passout pass:password
我的PEM文件结构:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
我正在使用此curl请求从API获取数据:
curl --cert file.p12:password --cacert file.pem --resolve destinationHost.com:443:100.100.100.100 -H "Content-Type: text/plain" https://destinationHost.com/api
我试图使用Java实现这个请求(无论是哪个库)。
示例:使用此链接和此链接
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultDnsResolver;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.xml.bind.DatatypeConverter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
public class Main {
public static void main(String[] args) throws Exception {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
SSLContext context = SSLContext.getInstance("TLS");
byte[] certAndKey = Files.readAllBytes(Paths.get("file.pem"));
byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
byte[] keyBytes = parseDERFromPEM(certAndKey, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----");
X509Certificate cert = generateCertificateFromDER(certBytes);
RSAPrivateKey key = generatePrivateKeyFromDER(keyBytes);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null);
keystore.setCertificateEntry("alias", cert);
keystore.setKeyEntry("alias", key, "password".toCharArray(), new Certificate[] {cert});
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keystore, "password".toCharArray());
KeyManager[] km = kmf.getKeyManagers();
context.init(km, null, null);
DnsResolver dnsResolver = new SystemDefaultDnsResolver() {
@Override
public InetAddress[] resolve(final String host) throws UnknownHostException {
if (host.equalsIgnoreCase("destinationHost.com")) {
/* If we match the host we're trying to talk to,
return the IP address we want, not what is in DNS */
return new InetAddress[] { InetAddress.getByName("100.100.100.100") };
} else {
/* Else, resolve it as we would normally */
return super.resolve(host);
}
}
};
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(context, new NoopHostnameVerifier());
BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", socketFactory)
.build(),
null, /* Default ConnectionFactory */
null, /* Default SchemePortResolver */
dnsResolver
);
httpClientBuilder.setConnectionManager(connManager);
CloseableHttpClient client = httpClientBuilder.build();
HttpGet httpGet = new HttpGet("https://destinationHost.com/api");
CloseableHttpResponse execute = client.execute(httpGet);
int statusCode = execute.getStatusLine().getStatusCode();
assert statusCode == 200;
}
private static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
String data = new String(pem);
String[] tokens = data.split(beginDelimiter);
tokens = tokens[1].split(endDelimiter);
return DatatypeConverter.parseBase64Binary(tokens[0]);
}
private static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPrivateKey)factory.generatePrivate(spec);
}
private static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes));
}
}
但是接收:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
at org.apache.http.impl.conn.BasicHttpClientConnectionManager.connect(BasicHttpClientConnectionManager.java:338)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at com.test.Main.main(Main.java:95)
提前感谢任何建议。
问题是我忘记了将TrustManager添加到SSLContext的init方法中。现在一切正常。
TrustManager acceptAll = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
context.init(km, new TrustManager[]{acceptAll}, null);
问题内容: 我想从Java代码登录到应用程序。这是我的代码… 但我无法登录,它只返回登录页面。 如果有人可以,请帮助我了解我在做什么错。 问题答案: 错误 :-( www-form 中间有多余的空格) 正确
我需要使用https协议向我的web服务发送请求。使用SOAP UI,它工作得很好,也为https请求提供响应,但是,如果我发送https请求,它提供以下异常javax.xml.ws.WebServiceException:未能访问WSDL:https://abc:8443/xyz/FileTransferService?WSDL。它失败的原因是:
问题内容: 这类似于将PEM导入Java密钥存储区。但是问题的答案使用OpenSSL进行转换和使用工具将其导入文件系统上的密钥存储中。 我正在尝试使用格式良好的X509证书作为信任锚: 当我尝试运行程序时,出现错误: 我也尝试了和,但它们也不起作用。 我知道Java支持PEM和DER编码的证书,因为这是Web服务器发送给客户端的内容。但是所有的似乎都不符合我的需求,因此我怀疑我没有为此使用正确的A
问题内容: 我有一台具有通过https运行的rest API的服务器。我想在我的应用程序中调用此rest api,该应用程序在不同的端口中运行,但是由于这是通过https进行的,因此 我有2个文件pulic_key.pem和private_key可用于验证证书。使用golang发送休假请求时如何验证证书?我正在发送休息请求。这就是我现在忽略证书的操作。 问题答案: 您需要将证书的CA添加到传输中,
这类似于将PEM导入Java密钥存储。但问题的答案是使用OpenSSL进行转换,并使用工具将其导入文件系统上的密钥存储。 我试图使用一个格式良好的X509证书作为信任锚: 当我试图运行该程序时,我得到一个错误: 我还尝试了
问题内容: 我正在尝试使用HttpsUrlConnection类将请求发送到服务器。服务器存在证书问题,因此我设置了一个可信任所有内容的TrustManager以及同样宽松的主机名验证程序。当我直接发出请求时,此管理器工作正常,但是当我通过代理发送请求时,似乎根本没有使用过。 我这样设置代理设置: 默认SSLSocketFactory的TrustManager的设置如下: 如果运行以下代码,则最终