2010-09-26 45 views
6

上周我的web应用程序中使用的密钥库文件已过期。我很久以前生成了它。所以我开始使用keytool生成新的证书。我使用此证书来连接交易服务器和Web服务器。我想为此应用程序使用自签名证书。我使用以下命令生成它,为事务服务器生成自签名密钥。使用keytool在jdk中提供生成SSL证书

keytool -genkey -keystore keys/SvrKeyStore -keyalg rsa -validity 365 -alias Svr -storepass 123456 -keypass abcdefg -dname "CN=One1, OU=Development1, O=One, L=Bamba, S=Western Prov1, C=S1" 

以下commnad生成密钥存储为Web应用程序

keytool -genkey -keystore keys/ClientKeyStore -keyalg rsa -validity 365 -alias Web -storepass 123456 -keypass abcdefg -dname "CN=One, OU=Development, O=One, L=Bamba, S=Western Prov, C=SL" 

我曾经在交易服务器下面的代码创建套接字连接

  String KEYSTORE = Config.KEYSTORE_FILE;//SvrKeyStore keystore file 
      char[] KEYSTOREPW = "123456".toCharArray(); 
      char[] KEYPW = "abcdefg".toCharArray(); 
      com.sun.net.ssl.TrustManagerFactory tmf; 

      boolean requireClientAuthentication; 

      java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl. 
              Provider()); 
      java.security.KeyStore keystore = java.security.KeyStore.getInstance(
       "JKS"); 
      keystore.load(new FileInputStream(KEYSTORE), KEYSTOREPW); 

      com.sun.net.ssl.KeyManagerFactory kmf = com.sun.net.ssl. 
       KeyManagerFactory.getInstance("SunX509"); 
      kmf.init(keystore, KEYPW); 

      com.sun.net.ssl.SSLContext sslc = com.sun.net.ssl.SSLContext. 
       getInstance("SSLv3"); 
      tmf = com.sun.net.ssl.TrustManagerFactory.getInstance("sunx509"); 
      tmf.init(keystore); 

      sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
      SSLServerSocketFactory ssf = sslc.getServerSocketFactory(); 
      SSLServerSocket ssocket = (SSLServerSocket) ssf.createServerSocket(port); 
      ssocket.setNeedClientAuth(true); 

但是当我用它给了以下异常它在我的应用程序中,并尝试通过网络服务器连接到交易服务器

javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHands 
hakeException: java.security.cert.CertificateException: Untrusted Server Certifi 
cate Chain 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.jav 
a:1172) 
     at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java: 
65) 
     at net.schubart.fixme.internal.MessageInput.readExactly(MessageInput.jav 
a:166) 
     at net.schubart.fixme.internal.MessageInput.readMessage(MessageInput.jav 
a:78) 
     at cc.aot.itsWeb.ClientWriterThread.run(ClientWriterThread.java:241) 
     at java.lang.Thread.run(Thread.java:619) 
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateEx 
ception: Untrusted Server Certificate Chain 
     at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1 
520) 
     at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:182) 
     at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:176) 
     at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien 
tHandshaker.java:975) 
     at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHa 
ndshaker.java:123) 
     at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:5 
11) 
     at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.jav 
a:449) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.j 
ava:817) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SS 
LSocketImpl.java:1029) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl. 
java:621) 
     at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.ja 
va:59) 
     at java.io.OutputStream.write(OutputStream.java:58) 

请任何一个可以告诉我问题出在哪里

回答

11

首先,避免直接使用com.sun.net.ssl包和类。 JSSE的体系结构是为了让您可以使用工厂并稍后指定提供者而构建的。改为使用javax.net.ssl.TrustManagerFactoryKeyManagerFactorySSLContext)。 (我建议使用"PKIX"而不是"SunX509"作为信任管理器算法,因为它通常是Sun提供程序的默认设置,或者更好的是使用TrustManagerFactory.getDefaultAlgorithm())。

其次,除非使用客户端证书身份验证,否则不需要在客户端设置密钥管理器。

最后(也许是最重要的),您需要导出您在服务器端生成的自签名证书(仅限证书,而非私钥),并将其导入您用作密钥库的密钥库信任商店在客户端。

当您生成证书时,应确保使用CN=the.server.host.name

keytool -genkey -keystore server-keystore.jks -alias server_alias \ 
     -dname "CN=the.server.host.name,OU=whateveryoulike" \ 
     -keyalg "RSA" -sigalg "SHA1withRSA" -keysize 2048 -validity 365 

keytool -export -keystore server-keystore.jks -alias server_alias -file server.crt 

keytool -import -keystore client-truststore.jks -file server.crt 

如果你想使用客户证书认证,则需要通过与分别客户端密钥存储和服务器信任更换服务器密钥库和客户信任重复操作。

在这种情况下,server-keystore.jksserver-truststore.jks可能是同一个文件,但您不需要(在客户端一样)。

+0

哦,它的工作很好。多谢,伙计.. – nath 2010-09-26 13:04:45

0

所有你需要做的是密钥工具-selfcert - 别名XXX -validity DDD其中XXX是一样的别名,之前和DDD是天前的数到期,为服务器证书,然后导出该证书并导入到客户端的信任库。为客户重复相反的过程。您已经省略了导出/导入部分。

但是很多代码现在已经过时。您不需要调用addProvider(),并且可以在其余部分中将com.sun.net.ssl更改为javax.net.ssl。

0

要了解这一点,您必须了解证书如何工作。

由于任何人都可以创建一个证书(就像你做的那样),仅仅创建证书是不够的 - 证书必须是可信的。证书只有在被另一个可信的证书签名时才被信任。 在信任“食物链”的顶端,有几个主要的CA,您可以向其支付资金以使您的证书“公开信任”(您的计算机随其安装的证书一起提供)。

当然,您不必为了申请而向CA支付费用,但是您必须模仿此行为。您可能需要做的是导出服务器/客户端公钥,并将其安装在某种可信存储区中。

检查您的API如何定义您的可信证书。