1 2 Previous Next 18 Replies Latest reply on Jul 20, 2012 3:26 AM by pratik.pai

    WS-Security: keystores and truststores

    zarzar

      Hi,

      I'm using WS-Security to sign and encrypt SOAP messages. I'm signing with the sender's private key and encrypting with the receiver's public key.

       <config>
       <sign type="x509v3" alias="client"/>
       <encrypt type="x509v3" alias="server"/>
       </config>
      


      The problem is that JBoss doesn't look for the receiver's cert in the truststore, but in the keystore. My understanding of keystores and truststores is that keystores contain your own private and public keys, while truststores contain public certs of others you trust. So I'm wondering why I've got to put certs of others that I want to send to in my keystore.

      Is there a way around this? Or does the keystore have to be a duplicate of the truststore plus your own private key?

      Thanks for any help.

      Zar






        • 1. Re: WS-Security: keystores and truststores
          peterj

          I'll add my own two cents to this (I was going to do a new post but found this one).

          The only way that I can get WS-Security encryption to work is if I place the private key into the keystore in both the client and the server. If either one has a public key, it complains with the error:

          org.jboss.ws.extensions.security.WSSecurityException: Problems retrieving private key: Private key (XXX) not in keystore

          This appears to be a major flaw if both the client and the server have to have the private key available, I would think that the public key would be sufficient for one side. I cannot imagine a company that provides a Web service willingly giving out the private key for that Web service. Or a second company that wants to use said web service providing its private key to the first company.

          Any thoughts on this or am I just doing it wrong. (I will post the config files on request, but they are pretty much what appears at http://jbws.dyndns.org/mediawiki/index.php/JAX-WS_User_Guide#WS-Security, though substitute 'encrypt' for 'sign'. I think I tried 'sign' also and it had the same problem.)

          I am using JBossWS 1.2.0.GA

          • 2. Re: WS-Security: keystores and truststores
            jason.greene

            Encryption operates very differently than signature processing. You can relate it to do ssl mutual auth, or pgp.

            In order to use encryption you need 2 key pairs (public/private) for each party; in spirit of old school cryptography lets call them bob and alice. In order to send an encrypted message to Alice, Bob must have her public key. He encrypts the message to Alice, using her public key, which she can then decrypt using her private key. Likewise when she replies to the message she uses Bob's public key to encrypt the message, and he uses his private key to decrypt the message.

            Now when sending these messages WS-Security needs to know which public key the message was encrypted with. To do this, one mechanism is to send the X509 token of the public cert in the message. However this causes another form of validation to occur. WS-Security requires that all tokens be validated. So therefore Bob and Alice need to trust their own public keys.

            Here is the setup
            bobs.keystore
            ---------------
            bob - keyPair (public + private key)
            alice - trustedCertEntry (just alice's public key)

            bobs.truststore
            ----------------
            bob - trustedCertEntry (just bob's public key)

            alices.keystore
            -----------------
            alice - keyPair (public + private key)
            bob - trustedCertEntry (just bob's public key)

            alices.trustore
            ----------------
            alice - trustedCertEntry (just alice's public key)


            Note, this is just for encryption, to enable signing as well you need to also add a trust entry for the other party, since in signature processing it's the public key that is used for decryption.

            Let me know if you have any other questions.

            -Jason

            • 3. Re: WS-Security: keystores and truststores
              peterj

              Thanks again, Jason. I tried this for encryption (and your suggested additions to support signing by updating both truststores so that they contain both public keys) and it worked. I think I now have a little better understanding of the role of the truststore in this scheme.

              For those of you following along at home (or at work), when Bob sends a message he uses Alice's key to encrypt the message but his key to sign it, so the config section of jboss-wsse-xxx.xml file looks like:

              <config>
               <sign type="x509v3" alias="bobs_key"/>
               <encrypt type="x509v3" alias="alices_key"/>
               <requires>
               <signature />
               <encryption/>
               </requires>
               </config>


              Of course, on Alice's machine, the aliases are the opposite. If you don't want to sign the messages, remove the < sign > and < signature/ > tags.

              • 4. Re: WS-Security: keystores and truststores
                peterj

                Another question. Let's say that Bob runs the web service and Alice has a client that uses the web service. Now John would also like to use the web service. John would create:

                johns.keystore
                ----------------
                john - keyPair (pub+priv)
                bob - trustedCertEntry (pub)

                johns.truststore
                ----------------
                john - trustedCertEntry (just john's public key)

                In addition, Bob's keystore would be updated to:

                bobs.keystore
                ----------------
                bob - keyPair (public + private key)
                alice - trustedCertEntry (just alice's public key)
                john - trustedCertEntry (just john's public key)

                This does not pose a problem for encrypting the request from the client side since both Alice and John use Bob's public key to encrypt the message, and Bob of course uses his pirvate key to decrypt the message. But how is the response message encrypted? Bob would have to know who he is responding to and encrypt accordingly, but how would one specify this?

                • 5. Re: WS-Security: keystores and truststores
                  openyourmind

                  Hi,

                  We are having the same problem.

                  I mean Alice and John want to consume Bob's service, but Bob is xml configured to use Alice's public key for encryption.

                  How could we tell jbossws to understand who called him and to encrypt with the corresponding key.

                  Thanks for any help
                  OYM

                  • 6. Re: WS-Security: keystores and truststores

                    I have this problem too. The client part must be dynamic, not static. I want to have more than one client!
                    Sorry for my english

                    • 7. Re: WS-Security: keystores and truststores
                      memema


                      Help, I am desperate with this
                      M.

                      • 8. Re: WS-Security: keystores and truststores
                        rmartony

                        I have the same problem.

                        JBossWS apparently does not support multiple clients because the certificate used by the server to encrypt the response is specified statically in jboss-wsse-server.xml.
                        This is a big limitation.

                        A workaround to this problem is using SSL.

                        Any other ideas?

                        Thanks,
                        Rafael.

                        • 9. Re: WS-Security: keystores and truststores


                          I agree.
                          If I must share the same public/private key pair between several clients, the encryption does not have sense.
                          It is a problem of the specification or is a problem of the present implementation?
                          Thanks, Martin

                          • 10. Re: WS-Security: keystores and truststores
                            jason.greene

                            The WS-Security spec does not specify a standard or convention for dynamically encrypting based on client input. Although it could be possible to add a feature that would use the client identity to determine the certificate to use for encryption. Open one in Jira if this is what you want.

                            Otherwise your options are


                            1. Use SSL
                            2. Deploy the same service multiple times per client
                            3. Use a separate shared client key for encryption, authentication can still be validated using individual keys for signature processing.


                              -Jason


                            • 11. Re: WS-Security: keystores and truststores

                              Thanks for your reply.
                              The feature you mention is an interesting and useful one, on the contrary the XML encryption does not have sense for more than one client. To share a private key is unacceptable (a REAL private key, issued by a CA), and the multiple deploys option does not scale (for example, the incorporation of new clients cannot be dynamic).

                              • 12. Re: WS-Security: keystores and truststores
                                mageshbk

                                I have created a JIRA request here http://jira.jboss.com/jira/browse/JBWS-1814

                                • 13. Re: WS-Security: keystores and truststores
                                  cavani

                                  Hi,

                                  I am using the follow approach based on JBossWS 2.0.1:

                                  1. I didn't change distribution code

                                  2. Copy to my project (EJB where WS is configured):
                                  org.jboss.ws.extensions.security.jaxws.WSSecurityHandler
                                  org.jboss.ws.extensions.security.jaxws.WSSecurityHandlerServer
                                  org.jboss.ws.extensions.security.WSSecurityDispatcher

                                  3. Merge WSSecurityHandler and WSSecurityHandlerServer in a single source (WSSecurityHandler no more abstract and delete Server) and change invocation to my WSSecurityDispatcher copy.

                                  4. Create my own SecurityStore extending org.jboss.ws.extensions.security.SecurityStore:

                                  public class SecurityStore extends org.jboss.ws.extensions.security.SecurityStore
                                  {
                                  
                                   private KeyStore keyStore;
                                  
                                   private KeyStore trustStore;
                                  
                                   private char[] keyStorePassword;
                                  
                                   public SecurityStore() throws WSSecurityException
                                   {
                                   loadKeyStore();
                                  
                                   SPIProvider spiProvider = SPIProviderResolver.getInstance().getProvider();
                                   SecurityAdaptorFactory secAdapterfactory = spiProvider.getSPI(SecurityAdaptorFactory.class);
                                   SecurityAdaptor securityAdaptor = secAdapterfactory.newSecurityAdapter();
                                  
                                   String username = securityAdaptor.getPrincipal().toString();
                                  
                                   loadSessionKey(username);
                                   }
                                  
                                   public SecurityStore(Element element) throws WSSecurityException
                                   {
                                   loadKeyStore();
                                  
                                   Element child = Util.getFirstChildElement(element);
                                  
                                   String username = null;
                                  
                                   while (child != null)
                                   {
                                   String tag = child.getLocalName();
                                  
                                   if (tag.equals("UsernameToken"))
                                   {
                                   UsernameToken token = new UsernameToken(child);
                                   username = token.getUsername();
                                   break;
                                   }
                                  
                                   child = Util.getNextSiblingElement(child);
                                   }
                                  
                                   loadSessionKey(username);
                                   }
                                  
                                  // copy of public methods from SecurityStore
                                  
                                  


                                  where:

                                  * loadKeyStore() load server key/certificate
                                  * loadSessionKey(String username); load user certificate (all certificate has the same alias)

                                  4. Change WSSecurityDispatcher to instantiate my SecurityStore copy:
                                  * Element parameter Constructor at handleInbound
                                  * Default Constructor at handleOutbound

                                  5. use my WSSecurityHandler at standard-jaxws-endpoint-config.xml

                                  6. configure client with username tag at jboss-wsse-client.xml and:

                                   BindingProvider bindingProvider = (BindingProvider) port;
                                   Map<String, Object> reqContext = bindingProvider.getRequestContext();
                                   reqContext.put(BindingProvider.USERNAME_PROPERTY, (String) USERNAME_HERE);
                                   reqContext.put(BindingProvider.PASSWORD_PROPERTY, "");
                                  


                                  just it!

                                  it is working fine to me (user certs are in LDAP acounts accessed with JNDI - InitialDirContext).

                                  Any changes to improve security code to implement something like this out-of-box (like pluggable SecurityStore with username information)? for 2.0.2?

                                  Thanks,

                                  • 14. Re: WS-Security: keystores and truststores
                                    the_olo

                                    Hi!

                                     

                                    Does anyone know of a method for JBoss-WS that would make it search for truststore and keystore files on the classpath, not on a fixed path?

                                    I can do this currently with Spring-WS, e.g. in spring-ws-servlet.xml I can specify the following:

                                     

                                      <bean id="keystore" class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean">

                                        <property name="keyStorePassword" value="password" />

                                        <property name="keyStoreLocation" value="classpath:/wssec-server.jks" />

                                        <property name="defaultX509Alias" value="server" />

                                      </bean>

                                     

                                    This way we don't have to put the same keystores and truststores in all the WARs that compose the full enterprise application EAR.

                                     

                                    We couldn't find any similar functionality for JBoss-WS. Here are the example paths in the wsse configuration file:


                                    <jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://www.jboss.com/ws-security/config                       http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
                                      <key-store-file>META-INF/bob-sign.jks</key-store-file>   <key-store-password>password</key-store-password>   <key-store-type>jks</key-store-type>   <trust-store-file>META-INF/wsse10.truststore</trust-store-file>   <trust-store-password>password</trust-store-password>

                                     

                                     

                                     

                                    The paths are either:

                                    1. filesystem-absolute, which makes configuration, deployment and general management of server environments a nightmare: keystores have to be placed in exactly the same locations on all servers in all dev, test and production environments regardless of OS - this completely eliminates the possibility of using an OS with incompatible filesystems layout, like MS Windows, in the development chain,
                                    2. or relative to the root of the WAR archive, which requires placing keystore copies in all WARs and complicates production deployment: all cryptographic keys must be replaced by key staff, which isn't qualified to mess with the EARs and WARs inside them.
                                    1 2 Previous Next