java.security.SignatureException:签名不匹配

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26537987/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 02:43:59  来源:igfitidea点击:

java.security.SignatureException: Signature does not match

javasecuritytomcat7keytool

提问by Himalay Majumdar

  1. I created a java keystore with name cloudsslkeystore.jks

     keytool -genkeypair -validity 730 -alias cloudsslkey -keystore cloudsslkeystore.jks -dname "cn=localhost" -keypass password -storepass password
    
  2. I exported it as certificate with name cloudcertificate.cer

     keytool -export -rfc -keystore cloudsslkeystore.jks -alias cloudsslkey -file cloudcertificate.cer 
     Enter keystore password:password
     Certificate stored in file <cloudcertificate.cer>
    
  3. I added the certificate cloudcertificate.cer to my local java security folder

    C:\Program Files\Java\jre7\lib\security>keytool -keystore cacerts -importcert -noprompt -trustcacerts -alias cloudsslkey -file cloudcertificate.cer
    Enter keystore password:changeit
    Certificate was added to keystore
    

    Now I used the same java keystore cloudsslkeystore.jksin tomcat server of a different machineby modifying server.xml

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
                   maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
                   clientAuth="false" sslProtocol="TLS" keystoreFile="c:\keytool\cloudsslkeystore.jks" keystorePass="password" />
    
  1. 我创建了一个名为cloudslkeystore.jks的 java 密钥库

     keytool -genkeypair -validity 730 -alias cloudsslkey -keystore cloudsslkeystore.jks -dname "cn=localhost" -keypass password -storepass password
    
  2. 我将其导出为名称为cloudcertificate.cer 的证书

     keytool -export -rfc -keystore cloudsslkeystore.jks -alias cloudsslkey -file cloudcertificate.cer 
     Enter keystore password:password
     Certificate stored in file <cloudcertificate.cer>
    
  3. 我将证书 cloudcertificate.cer 添加到我的本地 java 安全文件夹

    C:\Program Files\Java\jre7\lib\security>keytool -keystore cacerts -importcert -noprompt -trustcacerts -alias cloudsslkey -file cloudcertificate.cer
    Enter keystore password:changeit
    Certificate was added to keystore
    

    现在,我使用的相同的Java密钥cloudsslkeystore.jks不同的机器的Tomcat服务器通过修改的server.xml

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
                   maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
                   clientAuth="false" sslProtocol="TLS" keystoreFile="c:\keytool\cloudsslkeystore.jks" keystorePass="password" />
    

When I try to hit a webservice thru a java client, I get this exception.

当我尝试通过 Java 客户端访问 Web 服务时,出现此异常。

Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Problem writing SAAJ model to stream: sun.security.validator.ValidatorException: PKIX
 path validation failed: java.security.cert.CertPathValidatorException: signature check failed
        at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:159)
        at com.sun.proxy.$Proxy39.getAllRecommendations(Unknown Source)
        at client.WSClient.main(WSClient.java:73)
Caused by: com.ctc.wstx.exc.WstxIOException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValida
torException: signature check failed
        at com.ctc.wstx.sw.BaseStreamWriter.writeCharacters(BaseStreamWriter.java:458)
        at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:749)
        at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:696)
        at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:214)
        at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:174)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
        at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:514)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:423)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:326)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:279)
        at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
        at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:137)
        ... 2 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathVal
idatorException: signature check failed
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1341)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1091)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
        at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.setupWrappedStream(URLConnectionHTTPConduit.java:17
4)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1302)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1258)
        at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.onFirstWrite(URLConnectionHTTPConduit.java:201)
        at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
        at org.apache.cxf.io.AbstractThresholdOutputStream.unBuffer(AbstractThresholdOutputStream.java:89)
        at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:63)
        at org.apache.cxf.io.CacheAndWriteOutputStream.write(CacheAndWriteOutputStream.java:80)
        at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:51)
        at com.ctc.wstx.io.UTF8Writer.write(UTF8Writer.java:143)
        at com.ctc.wstx.sw.BufferingXmlWriter.writeRaw(BufferingXmlWriter.java:285)
        at com.ctc.wstx.sw.BufferingXmlWriter.writeCharacters(BufferingXmlWriter.java:603)
        at com.ctc.wstx.sw.BaseStreamWriter.writeCharacters(BaseStreamWriter.java:456)
        ... 13 more
Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check fail
ed
        at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:350)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:260)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1323)
        ... 37 more
Caused by: java.security.cert.CertPathValidatorException: signature check failed
        at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:159)
        at sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:351)
        at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:191)
        at java.security.cert.CertPathValidator.validate(CertPathValidator.java:279)
        at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:345)
        ... 43 more
Caused by: java.security.SignatureException: Signature does not match.
        at sun.security.x509.X509CertImpl.verify(X509CertImpl.java:451)
        at sun.security.provider.certpath.BasicChecker.verifySignature(BasicChecker.java:160)
        at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:139)
        at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:133)
        ... 47 more

采纳答案by reim

The Signature does not matcherror is the symptom that the server identity is unknown to the client, ie the client truststore does not have the server certificate.

Signature does not match错误是客户端未知服务器身份的症状,即客户端信任库没有服务器证书。

Create the server certificate and add it to a keystore:

创建服务器证书并将其添加到密钥库:

keytool -genkey -noprompt -alias "$alias" -dname "CN=$dname_cn, OU=$dname_ou, O=$dname_o, L=$dname_l, S=$dname_s, C=$dname_c" -keystore "$keystore" -storepass "$storepass" -keypass "$keypass"

keytool -genkey -noprompt -alias "$alias" -dname "CN=$dname_cn, OU=$dname_ou, O=$dname_o, L=$dname_l, S=$dname_s, C=$dname_c" -keystore "$keystore" -storepass "$storepass" -keypass "$keypass"

and export it for the client into a truststore:

并将其为客户端导出到信任库中:

keytool -export -alias "$alias" -storepass "$storepass" -file "$alias".cer -keystore "$keystore"

keytool -export -alias "$alias" -storepass "$storepass" -file "$alias".cer -keystore "$keystore"

If you want 2-way SSL then you have to repeat this twice, inverting, they both must know each other.

如果你想要 2-way SSL,那么你必须重复两次,倒过来,他们都必须互相认识。

Now the tricky part is to build an SSLContextcorrectly and configure your client and server with it.

现在棘手的部分是SSLContext正确构建并使用它配置您的客户端和服务器。

In Grizzly I do:

在灰熊我做:

SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();

// set up security context
sslContextConfigurator.setKeyStoreFile(configuration.getKeystore()); // contains the server keypair
sslContextConfigurator.setKeyStorePass(configuration.getKeystorePassword());
sslContextConfigurator.setKeyStoreType(configuration.getKeystoreType());
sslContextConfigurator.setKeyPass(configuration.getKeystoreKeypass());
sslContextConfigurator.setTrustStoreFile(configuration.getTruststore()); // contains the list of trusted certificates
sslContextConfigurator.setTrustStorePass(configuration.getTruststorePassword());
sslContextConfigurator.setTrustStoreType(configuration.getTruststoreType());
if (!sslContextConfigurator.validateConfiguration(true))
    throw new Exception("Invalid SSL configuration");

For advanced debugging do not forget System.setProperty("javax.net.debug", "all");

对于高级调试不要忘记 System.setProperty("javax.net.debug", "all");

回答by user207421

-keypass password 

Get rid of this parameter. The mechanism that supports javax.net.ssl.keyStoreand javax.net.ssl.keyStorePassworddoesn't support key passwords, only keystore passwords.

去掉这个参数。支持javax.net.ssl.keyStorejavax.net.ssl.keyStorePassword不支持密钥密码的机制,仅支持密钥库密码。

回答by Eternal Beginner

I finally found the problem: The SignatureException does notindicate that the issuer is unknown to the client. In that case a CertPathBuilderException would be thrown.

终于找到问题所在:SignatureException 并没有说明客户端知道发行者。在这种情况下,将抛出 CertPathBuilderException。

The SignatureException was actually caused by not having the self-signed certificate imported as trustedcertificate which must be done by the additional parameter -trustcacerts.

SignatureException 实际上是由于没有将自签名证书作为受信任证书导入而引起的,而必须通过附加参数来完成-trustcacerts

To answer the question why someone should want to trust a self signed certificate: The server is used for test purposes for automated client tests connecting to the server over HTTPS.

回答为什么有人应该信任自签名证书的问题:服务器用于测试目的,用于通过 HTTPS 连接到服务器的自动化客户端测试。