为清楚起见,这些可能被表述为单独的问题,但它们都与同一问题有关.
SSL证书服务器名称是如何解析的?
为什么浏览器似乎使用证书的CN字段,但Java的机制似乎只关注"主题替代名称"?
是否可以使用keytool为SSL证书添加备用名称?如果没有,是使用openSSL而不是一个好的选择?
只是一点背景:我需要让主服务器使用HTTPS与多个服务器通信.显然,我们不想为每个服务器购买SSL证书(可能有很多),所以我想使用自签名证书(我一直使用keytool来生成它们).在操作系统中添加证书后,浏览器(IE和Chrome)很乐意接受该连接为可信任的.但是,即使将证书添加到Java的cacerts之后,Java仍然不会将该连接接受为受信任,并抛出以下异常:
引起:java.security.cert.CertificateException:在sun.security.util.HostnameChecker.match(HostnameChecker.java:75)的sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:142)中没有主题备用名称. at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity(X509T rustManagerImpl.java:264)at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:250)at com. sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien tHandshaker.java:1185)... 14更多
我发现我可以让Java信任实现我自己的HostNameVerifier的证书,我从这里复制了:com.sun.jbi.internal.security.https.DefaultHostnameVerifier只是为了测试(顺便说一句,主机名作为参数传递给HostnameVerifier是正确的,所以我认为应该已经接受了).
我一直使用证书字段CN作为主机名(通常是IP地址).
任何人都可以告诉我,如果我做错了什么,并指出我正确的方向?
我编写了一个基于Java SSLServerSocket的服务器,它接受连接并通过自定义二进制协议与Android应用程序通信:
ServerSocket serverSocket = SSLServerSocketFactory.getDefault().createServerSocket(1234);
while (true) {
Socket socket = serverSocket.accept();
...
}
Run Code Online (Sandbox Code Playgroud)
我使用以下参数运行服务器:
-Djavax.net.ssl.keyStore=keystore.jks
-Djavax.net.ssl.keyStorePassword=<PASSWORD>
Run Code Online (Sandbox Code Playgroud)
并使用以下教程生成证书,该教程构建公钥和私钥集:http://judebert.com/progress/archives/425-Using-SSL-in-Java,-Part-2.html:
keytool -genkeypair -keystore keystore.jks -alias keyname
keytool -export -alias keyname -file keyname.crt -keystore keystore.jks
keytool -importcert -file keyname.crt -keystore truststore.jks
Run Code Online (Sandbox Code Playgroud)
另外,我通过使用bouncycastle构建一个信任库来使它与android兼容:
keytool -importkeystore -srckeystore truststore.jks -srcstoretype JKS -srcstorepass <PASSWORD> -destkeystore truststore.bks -deststoretype BKS -deststorepass <PASSWORD> -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-ext-jdk15on-1.58.jar
Run Code Online (Sandbox Code Playgroud)
在此下载bouncycastle提供商:https://www.bouncycastle.org/latest_releases.html
并将生成的truststore.bks移动到原始资源文件夹中.
在Android上我使用以下代码构建一个SSLSocketFactory允许我导入生成的bouncycastle证书,该证书对我的服务器进行身份验证:
KeyStore trustStore = KeyStore.getInstance("BKS");
InputStream trustStoreStream = context.getResources().openRawResource(R.raw.truststore);
trustStore.load(trustStoreStream, "<PASSWORD>".toCharArray()); …Run Code Online (Sandbox Code Playgroud) 我想问一下是否可以创建包含SAN记录的CSR.
我创建了密钥库
keytool -genkeypair -keyalg RSA -keysize 2048 -alias testAlias -ext SAN=dns:test.example.com -keystore test.jks -storetype JKS -dname "CN=test"
Run Code Online (Sandbox Code Playgroud)
我可以使用keytool检查SAN是否在密钥库中
keytool -list -v -keystore test.jks
Run Code Online (Sandbox Code Playgroud)
和输出的相关部分是
#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: test.example.com
]
Run Code Online (Sandbox Code Playgroud)
然后我使用keytool创建了CSR:
keytool -certreq -file test.csr -keystore test.jks -alias testAlias
Run Code Online (Sandbox Code Playgroud)
但在CSR中有关于缺少SAN的信息.
如何检查:
keytool -printcertreq -file test.csr -v
Run Code Online (Sandbox Code Playgroud)
正确地应该有类似的东西
Extension Request:
#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: test.example.com
]
Run Code Online (Sandbox Code Playgroud)
我错过了一些选择certreq吗?
我想创建一个带有SAN字段(主题备用名称)集的自签名证书,但Java keytool工具似乎不支持它.什么是我最好的选择?这是供Java使用的,因此即使使用非Java工具创建证书,密钥库仍必须与JKS格式匹配.
我需要拼命的帮助来弄清楚为什么我的应用程序没有创建Web服务。
这是我的Web服务Java类:
@WebService
@Component
public class LoginWs extends AbstractWs
{
private static final Logger logger=MiscUtils.getLogger();
@Autowired
private PersonDao personDao = null;
/**
* Returns PersonTransfer on valid login
* @throws NotAuthorisedException if password is incorrect
*/
public PersonTransfer login(String userNameOrEmailAddress, String password) throws NotAuthorisedException
{
Person person=personDao.findByUserNameOrEmailAddress(userNameOrEmailAddress, true);
if (person != null && person.checkPassword(password))
{
PersonTransfer personTransfer = PersonTransfer.getTransfer(person);
personDao.setLastLogin(person.getId(), new GregorianCalendar());
EventLogDao.logEvent(ActionType.READ_DATA.name(), "LoginWs.login()", "personId=" + person.getId());
return(personTransfer);
}
logger.debug("Login failed : u/p="+userNameOrEmailAddress+"/"+password);
throw(new NotAuthorisedException("Invalid Username/Password"));
}
}
Run Code Online (Sandbox Code Playgroud)
调用此服务的代码是:
public …Run Code Online (Sandbox Code Playgroud)