Reputation: 3429
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.
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
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
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:
Colm.
Upvotes: 4