Aitor
Aitor

Reputation: 3429

Encrypting passwords in Crypto property files

Problem

I'm using Apache CXF 3.0.7, and read that, in the new features you have the ability to store a (BASE-64 encoded) encrypted version of the keystore password in the Crypto properties file, but I don't know how to add it, I didn't find an example of this implementation.

In the apache web says:

A typical example of the contents of a Crypto properties file (for Signature creation) is as follows:

 org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin
 org.apache.wss4j.crypto.merlin.keystore.type=jks
 org.apache.wss4j.crypto.merlin.keystore.password=security
 org.apache.wss4j.crypto.merlin.keystore.alias=wss40
 org.apache.wss4j.crypto.merlin.keystore.file=keys/wss40.jks 

Note that the password used to load the keystore is in cleartext. One of the new features of Apache WSS4J 2.0.0 is the ability to instead store a (BASE-64 encoded) encrypted version of the keystore password in the Crypto properties file. A new PasswordEncryptor interface is defined to allow for the encryption/decryption of passwords. A default implementation is now provided based on Jasypt called JasyptPasswordEncryptor, which uses "PBEWithMD5AndTripleDES".

The WSPasswordCallback class has an additional "usage" called WSPasswordCallback.PASSWORD_ENCRYPTOR_PASSWORD, which is used to return the master password for use with the PasswordEncryptor implementation. When WSS4J is loading a Crypto implementation via a properties file, and it encounters a password encrypted in the format "ENC(encoded encrypted password)", it queries a CallbackHandler for a password via this WSPasswordCallback usage tag. It is possible to pass a custom PasswordEncryptor implementation to WSS4J via the new configuration tag ConfigurationConstants.PASSWORD_ENCRYPTOR_INSTANCE ("passwordEncryptorInstance").

It is possible to pass a custom PasswordEncryptor implementation to WSS4J via the new configuration tag ConfigurationConstants.PASSWORD_ENCRYPTOR_INSTANCE ("passwordEncryptorInstance").

I guess I have to declare in my properties file something like that:

org.apache.wss4j.crypto.merlin.keystore.password=ENC(?????)

But I don't know how to encrypt my password with the default JasyptPasswordEncryptor implemented. Also, I guessthat in my CallbackHandler I'll have something like that:

if (usage==WSPasswordCallback.PASSWORD_ENCRYPTOR_PASSWORD){
                ????
    }

Solution

Ok, with the test running, I test my solution and now is working.

  1. Download the jasypt-1.9.2-dist.zip
  2. Get a Encoded password with this command encrypt input=real_keystore_password password=master_password algorithm=PBEWithMD5AndTripeDES
  3. Copy the OUTPUT (EXample: 0laAaRahTQJzlsDu771tYi)
  4. As you're using this algorithm, you need the Java Cryptography Extension (JCE) Unlimited Strength. Put in your JDK.
  5. Put the encoded output in the properties

    org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin org.apache.wss4j.crypto.merlin.keystore.type=jks org.apache.wss4j.crypto.merlin.keystore.password=ENC(0laAaRahTQJzlsDu771tYi) org.apache.wss4j.crypto.merlin.keystore.alias=my_alias org.apache.wss4j.crypto.merlin.keystore.file=/etc/cert/my_keystore.jks

  6. In the CallbackHandler, put the master_password wich you used to generated the encoded one:

    public class WsPasswordHandler implements CallbackHandler {

    @Override
    public void handle(Callback[] callbacks) throws IOException,
            UnsupportedCallbackException {
        for (Callback callback: callbacks){
            WSPasswordCallback pwdCallback= (WSPasswordCallback) callback;
            final int usage =pwdCallback.getUsage();
            if (usage==WSPasswordCallback.SIGNATURE||usage==WSPasswordCallback.DECRYPT){
                pwdCallback.setPassword("parKeyPassword");
            }
            if (usage==WSPasswordCallback.PASSWORD_ENCRYPTOR_PASSWORD){
                pwdCallback.setPassword("master_password");
            }
        }           
    }
    

    }

And this is it... Now I've to figure out how to get this working in a external local.property, with Spring, and so on.. but this is another history.. Thank you!

Upvotes: 4

Views: 4901

Answers (1)

Colm O hEigeartaigh
Colm O hEigeartaigh

Reputation: 1900

This test should help you: https://svn.apache.org/repos/asf/webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/PasswordEncryptorTest.java

You can get the encrypted password by instantiating the JasyptPasswordEncryptor with the master password, as in the test, and encrypt the keystore password. Then copy this into your crypto properties are per:

https://svn.apache.org/repos/asf/webservices/wss4j/trunk/ws-security-dom/src/test/resources/crypto_enc.properties

Colm.

Upvotes: 4

Related Questions