Securing web services with Metro – com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null

Typical exception:
PrivateKey returned by PrivateKeyCallback was Null

SEVERE: WSS1417: Error while processing signature java.lang.RuntimeException: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
09-Apr-2010 10:27:09 com.sun.xml.wss.jaxws.impl.SecurityTubeBase secureOutboundMessage
SEVERE: WSSTUBE0024: Error in Securing Outbound Message.
com.sun.xml.wss.XWSSecurityException: com.sun.xml.wss.XWSSecurityException: java.lang.RuntimeException: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
	at com.sun.xml.wss.impl.filter.SignatureFilter.process(SignatureFilter.java:241)
	at com.sun.xml.wss.impl.HarnessUtil.processWSSPolicy(HarnessUtil.java:93)
	at com.sun.xml.wss.impl.HarnessUtil.processDeep(HarnessUtil.java:268)
	at com.sun.xml.wss.impl.SecurityAnnotator.processMessagePolicy(SecurityAnnotator.java:186)
	at com.sun.xml.wss.impl.SecurityAnnotator.secureMessage(SecurityAnnotator.java:147)
	at com.sun.xml.wss.jaxws.impl.SecurityTubeBase.secureOutboundMessage(SecurityTubeBase.java:346)
	at com.sun.xml.wss.jaxws.impl.SecurityClientTube.processClientRequestPacket(SecurityClientTube.java:236)
	at com.sun.xml.wss.jaxws.impl.SecurityClientTube.processRequest(SecurityClientTube.java:167)
	at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:598)
	at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:557)
	at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:542)
	at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:439)
	at com.sun.xml.ws.client.Stub.process(Stub.java:222)
	at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:135)
	at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:109)
	at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
	at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
	at $Proxy48.instanceAccessQuery3(Unknown Source)
	at eu.webfarmr.servlet.ws.WSConnection.evaluate(WSConnection.java:156)
	at eu.webfarmr.servlet.ServletEnforcer.enforce(ServletEnforcer.java:150)
	at eu.webfarmr.servlet.AuthFilter.doFilter(AuthFilter.java:133)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:558)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:619)
Caused by: com.sun.xml.wss.XWSSecurityException: java.lang.RuntimeException: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
	at com.sun.xml.wss.impl.misc.DefaultSecurityEnvironmentImpl.getDefaultPrivKeyCertRequest(DefaultSecurityEnvironmentImpl.java:233)
	at com.sun.xml.wss.impl.filter.SignatureFilter.process(SignatureFilter.java:156)
	... 33 more
Caused by: java.lang.RuntimeException: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
	at com.sun.xml.wss.impl.misc.DefaultCallbackHandler.getDefaultPrivKeyCert(DefaultCallbackHandler.java:1359)
	at com.sun.xml.wss.impl.misc.DefaultCallbackHandler.handle(DefaultCallbackHandler.java:520)
	at com.sun.xml.wss.impl.misc.DefaultSecurityEnvironmentImpl.getDefaultPrivKeyCertRequest(DefaultSecurityEnvironmentImpl.java:228)
	... 34 more
Caused by: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
	at com.sun.xml.wss.impl.misc.DefaultCallbackHandler.getPrivateKey(DefaultCallbackHandler.java:2198)
	at com.sun.xml.wss.impl.misc.DefaultCallbackHandler.getDefaultPrivKeyCert(DefaultCallbackHandler.java:1350)
	... 36 more
09-Apr-2010 10:27:09 com.sun.xml.wss.jaxws.impl.SecurityClientTube processClientRequestPacket
SEVERE: WSSTUBE0024: Error in Securing Outbound Message.
com.sun.xml.wss.impl.WssSoapFaultException: com.sun.xml.wss.XWSSecurityException: java.lang.RuntimeException: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
	at com.sun.xml.wss.impl.SecurableSoapMessage.newSOAPFaultException(SecurableSoapMessage.java:337)
	at com.sun.xml.wss.jaxws.impl.SecurityTubeBase.secureOutboundMessage(SecurityTubeBase.java:353)
	at com.sun.xml.wss.jaxws.impl.SecurityClientTube.processClientRequestPacket(SecurityClientTube.java:236)
	at com.sun.xml.wss.jaxws.impl.SecurityClientTube.processRequest(SecurityClientTube.java:167)
	at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:598)
	at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:557)
	at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:542)
	at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:439)
	at com.sun.xml.ws.client.Stub.process(Stub.java:222)
	at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:135)
	at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:109)
	at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
	at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
	at $Proxy48.instanceAccessQuery3(Unknown Source)
	at eu.webfarmr.servlet.ws.WSConnection.evaluate(WSConnection.java:156)
	at eu.webfarmr.servlet.ServletEnforcer.enforce(ServletEnforcer.java:150)
	at eu.webfarmr.servlet.AuthFilter.doFilter(AuthFilter.java:133)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:558)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:619)
Caused by: com.sun.xml.wss.XWSSecurityException: com.sun.xml.wss.XWSSecurityException: java.lang.RuntimeException: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
	at com.sun.xml.wss.impl.filter.SignatureFilter.process(SignatureFilter.java:241)
	at com.sun.xml.wss.impl.HarnessUtil.processWSSPolicy(HarnessUtil.java:93)
	at com.sun.xml.wss.impl.HarnessUtil.processDeep(HarnessUtil.java:268)
	at com.sun.xml.wss.impl.SecurityAnnotator.processMessagePolicy(SecurityAnnotator.java:186)
	at com.sun.xml.wss.impl.SecurityAnnotator.secureMessage(SecurityAnnotator.java:147)
	at com.sun.xml.wss.jaxws.impl.SecurityTubeBase.secureOutboundMessage(SecurityTubeBase.java:346)
	... 28 more
Caused by: com.sun.xml.wss.XWSSecurityException: java.lang.RuntimeException: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
	at com.sun.xml.wss.impl.misc.DefaultSecurityEnvironmentImpl.getDefaultPrivKeyCertRequest(DefaultSecurityEnvironmentImpl.java:233)
	at com.sun.xml.wss.impl.filter.SignatureFilter.process(SignatureFilter.java:156)
	... 33 more
Caused by: java.lang.RuntimeException: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
	at com.sun.xml.wss.impl.misc.DefaultCallbackHandler.getDefaultPrivKeyCert(DefaultCallbackHandler.java:1359)
	at com.sun.xml.wss.impl.misc.DefaultCallbackHandler.handle(DefaultCallbackHandler.java:520)
	at com.sun.xml.wss.impl.misc.DefaultSecurityEnvironmentImpl.getDefaultPrivKeyCertRequest(DefaultSecurityEnvironmentImpl.java:228)
	... 34 more
Caused by: com.sun.xml.wss.impl.XWSSecurityRuntimeException: PrivateKey returned by PrivateKeyCallback was Null
	at com.sun.xml.wss.impl.misc.DefaultCallbackHandler.getPrivateKey(DefaultCallbackHandler.java:2198)
	at com.sun.xml.wss.impl.misc.DefaultCallbackHandler.getDefaultPrivKeyCert(DefaultCallbackHandler.java:1350)
	... 36 more

The reason may lie in the private key used. In this case the configuration contains the following lines:

servlet.keystore = O:/cygwin/home/djob/truststore.jks
servlet.keystore.password = changeit
servlet.keystore.alias = alice
servlet.keystore.type = JKS

We are trying to use a private key stored in truststore.jks. This private key is identified by its alias, alice. Both key and keystore can / are protected by a password. In this configuration. it is expected that the keystore be protected by the password changeit but what is not explicitly said is that the private key should also have the same password. How can we make sure it is the case?

Let’s use keytool and explore the keystore, truststore.jks:

  1. List the private keys contained in the store and check that there is one with an alias ‘alice’
    O:\cygwin\home\djob>keytool -v -list -keystore truststore.jks

    This prints out the following

    Keystore type: JKS
    Keystore provider: SUN
    
    Your keystore contains 1 entry
    
    Alias name: wrong-alias
    Creation date: 09-Apr-2010
    Entry type: PrivateKeyEntry
    Certificate chain length: 1
    Certificate[1]:
    Owner: CN=alice, O=Example AB
    Issuer: EMAILADDRESS=ca@example.com, CN=Certificate Authority, O=Example
    Serial number: c932cd054af3c347
    Valid from: Wed Aug 19 10:25:07 CEST 2009 until: Sat Aug 17 10:25:07 CEST 2019
    Certificate fingerprints:
             MD5:  71:17:DF:E0:31:5D:D2:3B:F1:FD:C2:96:E7:AE:28:12
             SHA1: 28:B5:8E:16:11:88:E9:00:58:D5:76:30:12:B9:59:B8:E4:CE:7C:AA
             Signature algorithm name: SHA1withRSA
             Version: 3
    
    Extensions:
    
    #1: ObjectId: 2.5.29.14 Criticality=false
    SubjectKeyIdentifier [
    KeyIdentifier [
    0000: 8C 89 33 CF 1C 6B 40 48   05 7C F5 E6 2C AB 6B 8F  ..3..k@H....,.k.
    0010: 3E 68 9B E4                                        >h..
    ]
    ]
    
    #2: ObjectId: 2.5.29.19 Criticality=false
    BasicConstraints:[
      CA:false
      PathLen: undefined
    ]
    
    #3: ObjectId: 2.5.29.35 Criticality=false
    AuthorityKeyIdentifier [
    KeyIdentifier [
    0000: C3 D4 7E 81 FA E1 0F 36   F5 B8 F1 44 0C 4C B9 A1  .......6...D.L..
    0010: BB 09 5C 1D                                        ..\.
    ]
    
    ]
    
    #4: ObjectId: 2.16.840.1.113730.1.13 Criticality=false
    
    *******************************************
    *******************************************
  2. If the alias is wrong, change it. As you can see in the previous example, the alias is ‘wrong-alias’ rather than ‘alice’.
    O:\cygwin\home\djob>keytool -v -changealias -alias wrong-alias -destalias alice -keystore truststore.jks

    . This will ask for the keystore certificate ‘changeit’. It prints out

    Enter keystore password:
    [Storing O:/cygwin/home/djob/truststore.jks]
  3. Make sure the key password is the same as the keystore password. Simply update the key password to that of the store.
    O:\cygwin\home\djob>keytool -v -keypasswd -keystore truststore.jks -alias alice

    This will ask for the keystore certificate ‘changeit’, the key’s old password and new password which you should set to the same as the store (changeit). It prints out

    Enter keystore password:
    Enter key password for <alice>
    New key password for <alice>:
    Re-enter new key password for <alice>:
    [Storing O:/cygwin/home/djob/truststore.jks]

    Note that if key password and store password were already the same, then when running the command aforementioned, it will not ask for key password. This is therefore an indication you need not change your key password.