我正在添加到我们的大型Java应用程序的模块必须与另一家公司的SSL安全网站进行交谈.问题是该站点使用自签名证书.我有一份证书副本,以验证我没有遇到中间人攻击,我需要将此证书合并到我们的代码中,以便与服务器的连接成功.
这是基本代码:
void sendRequest(String dataPacket) {
String urlStr = "https://host.example.com/";
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setMethod("POST");
conn.setRequestProperty("Content-Length", data.length());
conn.setDoOutput(true);
OutputStreamWriter o = new OutputStreamWriter(conn.getOutputStream());
o.write(data);
o.flush();
}
Run Code Online (Sandbox Code Playgroud)
在没有为自签名证书进行任何额外处理的情况下,这会在conn.getOutputStream()处死,但有以下异常:
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
....
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path …Run Code Online (Sandbox Code Playgroud) 我有两个应用程序在同一个java虚拟机中运行,并且都使用不同的密钥库和信任库.
一个可行的选择是使用单个密钥库并将所有其他密钥库导入共享密钥库(例如keytool -import),但如果我可以为在同一个jvm中运行的单独应用程序使用单独的密钥库,它将真正有助于我的要求.
我可以将keystore和truststore设置为jvm参数或系统属性,如下所示:
java -Djavax.net.ssl.keyStore=serverKeys
-Djavax.net.ssl.keyStorePassword=password
-Djavax.net.ssl.trustStore=serverTrust
-Djavax.net.ssl.trustStorePassword=password SSLApplication
Run Code Online (Sandbox Code Playgroud)
要么
System.setProperty("javax.net.ssl.keyStore","serverKeys")
Run Code Online (Sandbox Code Playgroud)
但是这种方法的问题在于它指定了要在JVM级别使用的密钥库/信任库,因此在同一JVM中运行的所有应用程序都获得相同的密钥库/信任库.
我还尝试创建自定义SSLContext并将其设置为默认值,但它还为在同一JVM中运行的所有应用程序设置上下文.
SSLContext context = SSLContext.getInstance("SSL");
context.init(kms, tms, null);
SSLContext.setDefault(context);
Run Code Online (Sandbox Code Playgroud)
我希望能够使用不同的密钥库/信任库而无需修改单个应用程序代码.
除了jre中的默认密钥库/证书之外,还可以动态注册多个密钥库的解决方案非常棒.
解决方案将以这种方式工作:
请让我知道您的想法或解决方案.提前致谢!
我需要忽略PKIX路径构建异常
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderExc
ption: unable to find valid certification path to requested target
Run Code Online (Sandbox Code Playgroud)
我知道如何写我自己的类实现要做到这一点X509TrustManager,我总是return true从isServerTrusted.
但是,我不想信任所有服务器和所有客户端.
我怎样才能实现这样的目标 - 即在我更换之前将部分验证传递给X509TrustFactory对象.
这就是我想要做的
public boolean isServerTrusted(X509Certificate[] chain)
{
if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer"))
return true;
// else I want to do whatever verification is normally done
}
Run Code Online (Sandbox Code Playgroud)
我也不想打扰现有的isClientTrusted验证.
我怎样才能做到这一点?
我有一个用Java编写的内部HTTP服务器; 完整的源代码供我使用.HTTP服务器可以配置任意数量的网站,每个网站都有一个单独的监听套接字创建:
skt=SSLServerSocketFactory.getDefault().createServerSocket(prt,bcklog,adr);
Run Code Online (Sandbox Code Playgroud)
使用使用Java keytool创建的标准密钥库,我不能在我的生活中找出如何获得与不同侦听套接字关联的不同证书,以便每个配置的网站都拥有自己的证书.
我现在正处于这种状态,因此一些代码示例将非常受欢迎.但是我很欣赏JSSE如何在这方面联系起来的任何好的概述(我已经搜索了Sun的JSSE doco,直到我的大脑疼痛(字面意思;虽然它可能与咖啡因戒断一样多)).
编辑
有没有简单的方法来使用别名将密钥存储区中的服务器证书与侦听套接字相关联?以便:
我得到的印象(今天下午早些时候)我可以编写一个简单的KeyManager,只chooseServerAlias(...)返回非null,这是我想要的别名的名字 - 任何人对这一推理线有什么想法?
解
我使用的解决方案是根据slyvarking的回答构建的,它创建了一个临时密钥库,并使用从单个外部密钥库中提取的所需密钥/证书填充它.对于任何感兴趣的人(svrctfals是我的"服务器证书别名"值),代码如下:
SSLServerSocketFactory ssf; // server socket factory
SSLServerSocket skt; // server socket
// LOAD EXTERNAL KEY STORE
KeyStore mstkst;
try {
String kstfil=GlobalSettings.getString("javax.net.ssl.keyStore" ,System.getProperty("javax.net.ssl.keyStore" ,""));
String ksttyp=GlobalSettings.getString("javax.net.ssl.keyStoreType" ,System.getProperty("javax.net.ssl.keyStoreType" ,"jks"));
char[] kstpwd=GlobalSettings.getString("javax.net.ssl.keyStorePassword",System.getProperty("javax.net.ssl.keyStorePassword","")).toCharArray();
mstkst=KeyStore.getInstance(ksttyp);
mstkst.load(new FileInputStream(kstfil),kstpwd);
}
catch(java.security.GeneralSecurityException thr) {
throw new IOException("Cannot load keystore ("+thr+")");
}
// CREATE EPHEMERAL KEYSTORE FOR THIS SOCKET USING DESIRED CERTIFICATE
try {
SSLContext ctx=SSLContext.getInstance("TLS"); …Run Code Online (Sandbox Code Playgroud) 我希望我的Java代码在一个密钥库中搜索服务器的CA证书...如果它无法找到特定的证书(我认为只有当我尝试通过LDAP连接到Directory Server时才会知道),它应该是在另一个密钥库中查找证书,我知道它的路径.
我试过这个:
System.setProperty("javax.net.ssl.trustStore", System.getProperty("java.home") + "/lib/security/cacerts" + System.getProperty("path.separator") + path/to/second/keystore);
但它似乎没有用.
只添加一个路径(其中任何一个)都可以工作,即如果找到证书则会像魅力一样运行,否则就会失败.
所以我的问题是:
是否有方法将多堆密钥库路径添加到javax.net.ssl.trustStore?
如果不可能我应该如何编写我的代码(我要求算法),以便它在第一次搜索后不会抛出异常而失败?
PS:我对Java不太熟悉.
以下是我的代码的相关部分:
if(useSSL)
{
try
{
SSLContext se = SSLContext.getInstance("TLS");
Security.addProvider(se.getProvider());
}
catch(NoSuchAlgorithmException e) { }
System.setProperty("javax.net.ssl.trustStore", System.getProperty("java.home") + "/lib/security/cacerts");
com.org.ldap.LDAPSocketFactory ssf = new LDAPJSSESecureSocketFactory();
LDAPConnection.setSocketFactory(ssf);
}
try
{
lc = new LDAPConnection();
lc.connect( ldapServer, ldapPort);
lc.bind( ldapVersion, ldapUser, (userInfo[1]).getBytes() );
}
catch (LDAPException le)
{
le.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud) 我有这个简单的JMX客户端
public void testTomcatBasicAuthentication() throws Exception
{
System.out.println("Test Server Basic Authentication");
try
{
String truststore = "C:\\client.jks";
String trustStorePassword = "password";
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://xxx.xxx.xxx.xxx:9999/jmxrmi");
HashMap environment = new HashMap();
String[] credentials = new String[]
{
"user", "passwd"
};
environment.put(JMXConnector.CREDENTIALS, credentials);
// environment.put("javax.net.ssl.trustStore", truststore);
// environment.put("javax.net.ssl.trustStorePassword", trustStorePassword);
// environment.put("javax.net.ssl.keyStore", truststore);
// environment.put("javax.net.ssl.keyStorePassword", trustStorePassword);
KeyManager[] kms = getKeyManagers(truststore, trustStorePassword);
TrustManager[] tms = getTrustManagers(truststore, trustStorePassword);
System.setProperty("javax.net.ssl.trustStore", truststore);
System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
System.setProperty("javax.net.ssl.keyStore", truststore);
System.setProperty("javax.net.ssl.keyStorePassword", trustStorePassword);
JMXConnector jmxc = JMXConnectorFactory.connect(url, environment);
MBeanServerConnection server = …Run Code Online (Sandbox Code Playgroud) Java中是否有指定其他信任库的方法,但如果在指定的信任库中找不到匹配的证书,则java默认为cacerts?我希望能够在几个应用程序中创建一个包含一些我需要的基本证书的信任库,但无需单独更新每个jre的cacerts文件.
我意识到我可以扩展cacerts文件(即:复制并添加到它),但我宁愿拥有一个只有我的附加证书的中央信任库.
我确实发现这个问题已经问过了,但是已经有好几年了,我不知道Java 7,8或9是否已经解决了这个问题.
我发现的所有文档都指向使用javax.net.ssl.trustStore并将其指向我的新信任库,但这将忽略我的cacerts中的所有内容.
如果我指向我的密钥库javax.net.ssl.keyStore,那么我就不能拥有特定于应用程序的密钥库.
理想情况下,我希望能够为java迭代创建一个信任库列表.
Java 7+中是否存在这种情况?
试图从 aws lambda 连接到外部肥皂服务,但低于异常。
com.sun.xml.internal.ws.client.ClientTransportException:HTTP 传输错误:javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到到请求目标的有效认证路径
尝试从本地环境调用服务时,我遇到了同样的异常。使用 keytool 命令将安全证书导入 jre/lib/security 文件夹后即可解决。
如何在 AWS 中导入外部安全证书以解决异常。
我已经浏览了下面的链接。
注意::我有浏览器的证书,但我没有私钥。
我正在尝试通过 SSL 套接字连接到本地服务器。服务器使用 SSL 证书,该证书:
我知道安全隐患,但由于我无法控制的原因,我无法更改或请求更改此证书,因此我被迫使用它 - 或者更确切地说,围绕它工作。
为了克服以上两点,我创建了:
TrustManager允许所有证书。AlgorithmConstraints允许所有算法。我最终出现以下错误:
Caused by: java.security.cert.CertPathValidatorException: Algorithm constraints check failed on signature algorithm: MD5withRSA
看来我放松算法约束的方法是有缺陷的。
注意:我知道MD5withRSA可以通过更改 JVM 配置或命令行参数来允许该算法,但我需要以编程方式执行此操作。
将TrustManager创建如下:
TrustManager[] trustManager = new TrustManager[] {
new X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) …Run Code Online (Sandbox Code Playgroud) I have been building web downloaders over the years (e.g., using Apache HTTPClient and recently JBrowser [1]). These have worked OK till recently when some sites result in certification errors. I do not understand the details, and I cannot find a simple tutorial for people who know relatively little about certificates (e.g., what one looks like and how it obtained or created). This is a request for a default explanation of the simplest case and how to fix it. Typical …
有没有办法在 PCF 中添加信任库和密钥库:
部署到 unix box 的应用程序可以拥有信任库,并且可以通过将它们保存在单独的位置并将该位置添加为 vm 参数来外部化密钥库。
但是如何在 PCF 中外部化密钥库和信任库。
我遇到的选项 1 是将密钥库和信任库保存在 spring-boot 应用程序的 /resource 中,并在 manifest.yml 中给出路径: JAVA_OPTS arguments 。但是如果我们有 5 个不同的环境,有 5 个不同的信任库和密钥库呢?
由于这个原因,我们需要将 . 请建议是否有任何方法可以在 PCF 中做到这一点。
提前致谢 !
java ×11
ssl ×8
certificate ×2
jsse ×2
security ×2
truststore ×2
aws-lambda ×1
cryptography ×1
jvm ×1
keystore ×1
macos ×1
pcf ×1
pki ×1
pkix ×1
spring-boot ×1