我正在尝试使用内置类com.sun.net.httpserver.HttpsServer在Java(6)中构建自定义HTTPS服务器.它工作正常,直到我需要客户端身份验证 此时,它在服务器上的SSL调试中失败并出现以下异常.
sun.security.validator.ValidatorException:Netscape证书类型不允许用于SSL客户端
我使用的是内部CA颁发的证书,用于我们内部的所有应用程序.我查看了证书详细信息,发现该类型是"SSL Server"(详情请参阅下文).由于我们的政策是对所有内部应用程序使用"SSL服务器"类型,因此很难更改证书.由于我想为客户端使用服务器证书,我不认为这是一个安全问题.
我正在寻找的方法是在Java中禁用此约束检查.有谁遇到过这个并解决了这个问题?任何帮助都非常感谢.
最诚挚的问候,阿伦
Owner: CN=myapp, OU=mygroup, O=mycompany
Issuer: O=MYCA
Serial number: 4cc8c1da
Valid from: Mon Jan 10 13:46:34 EST 2011 until: Thu Jan 10 14:16:34 EST 2013
Certificate fingerprints:
MD5: 8C:84:7F:7A:40:23:F1:B5:81:CD:F9:0C:27:16:69:5E
SHA1: 9B:39:0B:2F:61:83:52:93:D5:58:E5:43:13:7A:8F:E1:FD:AC:98:A4
Signature algorithm name: SHA1withRSA
Version: 3
Extensions:
[1]: ObjectId: 2.5.29.16 Criticality=false
PrivateKeyUsage: [
From: Mon Jan 10 13:46:34 EST 2011, To: Wed Jul 11 21:16:34 EDT 2012]
[2]: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
DigitalSignature
Key_Encipherment
]
[3]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier …Run Code Online (Sandbox Code Playgroud) JSSE允许用户通过指定javax.net.ssl.*参数来提供默认信任存储和密钥存储.我想为我的应用程序提供一个非默认的TrustManager,同时允许用户像往常一样指定KeyManager,但似乎没有任何方法可以实现这一点.
假设在unix机器上我想允许用户使用pkcs12密钥库进行身份验证,而在OS XI上则希望允许用户使用系统密钥链.在OS X上,应用程序可能会按如下方式启动:
java -Djavax.net.ssl.keyStore=NONE -Djavax.net.ssl.keyStoreType=KeychainStore \
-Djavax.net.ssl.keyStorePassword=- -jar MyApplication.jar
Run Code Online (Sandbox Code Playgroud)
这将很好地工作:当应用程序访问需要相互身份验证(客户端证书身份验证),那么用户将被提示允许访问自己的钥匙串HTTPS服务器.
现在假设我想将自签名证书颁发机构与我的应用程序捆绑在一起.我可以通过构造一个TrustManagerFactory并传入一个包含我的证书(javadoc)的KeyStore来覆盖默认的信任管理器.但是,要使用此非默认信任管理器,我需要创建并初始化SSLContext.这里存在问题.
通过调用init(..)并传递KeyManager和TrustManager 来初始化SSLContexts .但是,使用javax.net.ssl.*参数创建KeyManager的逻辑嵌入在默认SSLContexts的实现中 - 我找不到使用默认行为获取KeyManager或KeyManagerFactory的方法,同时还指定了非默认的TrustManager或TrustManagerFactory.因此,似乎是不可能的使用,例如,适当的操作系统特定钥匙扣实施,同时还提供用于认证远程服务器根证书.
我正在尝试使用STARTTLS将套接字升级到SSLSocket。在InspIRCd的Wiki上,这是应该如何工作的
>> STARTTLS
<< :test2.chatspike.net 670 nickname :STARTTLS successful, go ahead with TLS handshake
(SSL Handshake)
Run Code Online (Sandbox Code Playgroud)
所以在我的代码中,我已经写过(略有简化)
else if (code.equals("670")) {
SSLSocketFactory sslSocketFactory = ((SSLSocketFactory) SSLSocketFactory.getDefault());
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(
socket,
socket.getInetAddress().getHostAddress(),
socket.getPort(),
true);
sslSocket.startHandshake();
bufferedReader = new BufferedReader(new InputStreamReader(sslSocket.getInputStream(), getEncoding()));
bufferedWriter = new BufferedWriter(new OutputStreamWriter(sslSocket.getOutputStream(), getEncoding()));
socket = sslSocket;
}
Run Code Online (Sandbox Code Playgroud)
但是,无论是否有startHandshake(),我总是会收到一个recv失败(当我尝试从新的bufferedReader中读取时,我不会得到它
java.io.IOException: Can't connect to server
at org.pircbotx.PircBotX.connect(PircBotX.java:472) [Exception handling]
at org.pircbotx.PircBotX.connect(PircBotX.java:224) [Overridden constructor]
at org.pircbotx.impl.PircBotXExample.main(PircBotXExample.java:185)
Caused by: java.net.SocketException: Software caused connection abort: recv failed
at java.net.SocketInputStream.read(SocketInputStream.java:150)
at …Run Code Online (Sandbox Code Playgroud) 我正在使用 Java 的 SSL 库来保护我的应用程序之间的连接。我注意到SSLServerSocket.accept()即使握手失败也会返回一个套接字。
SSLServerSocket.accept()不会等到初始握手完成?和SSLSocket,握手会在实际操作之前自动完成吗?此外,在当前握手完成之前,写入和读取当前(重新)握手的 SSLSocket 是否会阻塞?如果不是,在握手套接字上操作是否安全?握手和应用程序数据是否会并行发送且互不影响?
我想用 Java 实现 DTLS 1.0 客户端,经过一番谷歌搜索后,我发现JSSERefGuide说了以下内容:
JSSE API 能够支持 SSL 版本 2.0 和 3.0 以及 TLS 版本 1.0。这些安全协议封装了普通的双向流套接字,JSSE API 添加了对身份验证、加密和完整性保护的透明支持。JDK 附带的 JSSE 实现支持 SSL 3.0、TLS(1.0、1.1 和 1.2)和 DTLS(版本 1.0 和 1.2)。它不实现 SSL 2.0。
所以我想我可以用纯Java实现它而不使用任何库(例如BouncyCastle)
但是当我尝试运行(以及其他一些,如 DTLSv1.2、DTLSv1...)时:
final SSLContext sslContext = SSLContext.getInstance("DTLSv1.0", "SunJSSE");
Run Code Online (Sandbox Code Playgroud)
它抛出:
Exception in thread "main" java.security.NoSuchAlgorithmException: no such algorithm: DTLSv1.0 for provider SunJSSE
at sun.security.jca.GetInstance.getService(GetInstance.java:87)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at javax.net.ssl.SSLContext.getInstance(SSLContext.java:199)
Run Code Online (Sandbox Code Playgroud)
例如以下工作:
final SSLContext sslContext = SSLContext.getInstance("TLSv1.2", "SunJSSE");
Run Code Online (Sandbox Code Playgroud)
列出所有安全提供商,我根本没有发现任何 DTLS 内容。
那么实际上有 DTLS 实现吗?如果是的话你应该如何使用它?
将 BouncyCastle FIPS JSSE 和 TLS 提供程序用于我的服务器应用程序。
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-fips</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bc-fips</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bctls-fips</artifactId>
<version>1.0.10</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
在应用程序中配置 FIPS 和 JSSE 提供程序,如下所示。
Security.insertProviderAt(new BouncyCastleFipsProvider(), 1);
Security.insertProviderAt(new BouncyCastleJsseProvider("fips:BCFIPS"), 2);
Security.setProperty("keystore.type", "BCFKS");
Run Code Online (Sandbox Code Playgroud)
SSL证书配置如下:
Server Cert - Public Key: RSA 2048 bit, Sign Algorithm: SHA256WithRSA
Issuing CA - Public Key: RSA 2048 bit, Sign Algorithm: SHA256WithRSA
Root CA - Public Key: RSA 2048 bit, Sign Algorithm: SHA1WithRSA
Run Code Online (Sandbox Code Playgroud)
使用 Zulu OpenJDK JRE 11。以下是与 TLS 相关的其他系统属性
-Djdk.tls.disabledAlgorithms="MD5, RC4, TLSv1, SSLv2Hello, …Run Code Online (Sandbox Code Playgroud) 我们正在编写一个应连接到不同LDAP服务器的应用程序。对于每台服务器,我们仅接受特定证书。该证书中的主机名无关紧要。这很容易,当我们使用LDAP和STARTTLS,因为我们可以用StartTlsResponse.setHostnameVerifier(..-)和使用StartTlsResponse.negotiate(...)具有匹配SSLSocketFactory。但是,我们还需要支持LDAPS连接。Java本机支持此功能,但前提是默认Java密钥库信任服务器证书。尽管可以替换它,但仍然不能为不同的服务器使用不同的密钥库。
现有的连接代码如下:
Hashtable<String,String> env = new Hashtable<String,String>();
env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
env.put( Context.PROVIDER_URL, ( encryption == SSL ? "ldaps://" : "ldap://" ) + host + ":" + port );
if ( encryption == SSL ) {
// env.put( "java.naming.ldap.factory.socket", "CustomSocketFactory" );
}
ctx = new InitialLdapContext( env, null );
if ( encryption != START_TLS )
tls = null;
else {
tls = (StartTlsResponse) ctx.extendedOperation( new StartTlsRequest() );
tls.setHostnameVerifier( hostnameVerifier );
tls.negotiate( sslContext.getSocketFactory() );
} …Run Code Online (Sandbox Code Playgroud) JSSE在Apache Tomcat服务器中支持的密码是什么?如何启用AES256并重新排序密码?
在什么情况下一个用HostnameVerifier在TrustManagerJava中?一个推荐超过另一个?看看Java文档(Interface HostnameVerifier和Interface TrustManager),我无法分辨它何时最好使用(虽然TrustManager看起来更通用).
在过去,我一直使用自定义TrustManager.但是,我注意到java中的Heartbleed漏洞使用了两者(但我不认为它是正确的).
编辑:在使用时HostnameVerifier,是否执行了其他惯常的X509检查,如路径构建,到期和撤销(如果已配置)?我想我基本上是在考虑HostnameVerifier补充其他检查(而不是替换它们).
例如,假设开发服务器位于dev.example.com内部CA并且由内部CA签名.dev.example.com证书中有一个DNS名称及其名称dev.example.com.此外,假设我连接到它192.168.1.10.我可以使用a HostnameVerifier来同时允许dev.example.com和192.168.1.10吗?在这种情况下,是否允许使用其他名称,是否执行了其他惯常的X509检查?
System.setProperty("com.sun.net.ssl.checkRevocation", "true");
Security.setProperty("ocsp.enable", "true");
Run Code Online (Sandbox Code Playgroud)
设置这些属性真的足以启用 OCSP 吗?
如果是这样,那么为什么我们需要充气城堡 OCSP 支持而不是仅仅设置此属性?