Hi Mike,
The problem I think is that the UsernameToken should appear before the
signature in the security header. What's happening is that the
SignatureProcessor is trying to get the key to use to verify the
signature, but it can't find it as the Username Token hasn't been
processed yet. You have:
if (secut != null)
secut.prependToHeader(secHeader);
sign.prependToHeader(secHeader);
Instead try:
sign.prependToHeader(secHeader);
if (secut != null)
secut.prependToHeader(secHeader);
BTW you're using the wrong secret key derivation algorithm in
UsernameToken. What you should be doing is something like (taken from a
unit test):
WSSecUsernameToken builder = new WSSecUsernameToken();
builder.setUserInfo("bob", "security");
builder.addDerivedKey(true, null, 1000);
builder.prepare(doc);
WSSecSignature sign = new WSSecSignature();
sign.setUsernameToken(builder);
sign.setKeyIdentifierType(WSConstants.UT_SIGNING);
sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
Document signedDoc = sign.build(doc, null, secHeader);
The "secret key" as opposed to "derived key" functionality is
non-standard, and in-secure (it sends the password in the UsernameToken
as well).
Colm.
________________________________
From: Mike [mailto:[email protected]]
Sent: 11 February 2009 12:12
To: [email protected]
Subject: WSS4J 1.5.5 UsernameToken handling
Hi again!
I have another issue when using WSS4J 1.5.5. I recently implemented
UsernameToken handling for our SOAP messages on WSS4J 1.5.4. This only
worked when I only signed the message, however when I added encryption
to the header the decryption would fail (when using 1.5.4) (as per first
message from me). Now however, after upgrading to 1.5.5, I get the
following exception when receiving a signed (no encryption) request:
java.lang.NullPointerException
at
org.apache.ws.security.processor.SignatureProcessor.verifyXMLSignature(S
ignatureProcessor.java:210)
at
org.apache.ws.security.processor.SignatureProcessor.handleToken(Signatur
eProcessor.java:85)
at
org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurity
Engine.java:326)
at
org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurity
Engine.java:243)
at
org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurity
Engine.java:196)
which points to (SignatureProcessor.java:210):
ut = utProcessor.getUt();
on my system.
Am I doing something terribly wrong?
Versions:
Wss4j 1.5.5
xml-sec 1.4.2
BouncyCastle JDK15-141
Java 1.5.0_16
Axis 1.4 1855 April 22 2006
Metro 1.4
Thanks,
Mike
Sample UT signature Code:
Utils.trace(this.getClass(), "WSS Signing SOAP Envelope");
WSSecSignature sign = new WSSecSignature();
sign.setUserInfo(alias, pw);
WSSecUsernameToken secut = getUsernameToken(pMode, event,
doc);
if (secut != null) {
sign.setUsernameToken(secut);
sign.setKeyIdentifierType (WSConstants.UT_SIGNING);
sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
Utils.debug(this.getClass(), "UsernameToken signing enabled
from ProcessingMode '" + pMode.getID() + "' using Event '" +
event.getID() + "'.");
} else {
sign.setSignatureAlgorithm(signAlgo);
sign.setSigCanonicalization(signCanonAlgo);
}
sign.setParts(getSignatureParts(pMode, event));
sign.prepare(doc, crypto, secHeader);
if (secut != null)
secut.prependToHeader(secHeader);
sign.prependToHeader(secHeader);
doc = sign.build(doc, crypto, secHeader);
Utils.trace(this.getClass(), "WSS Signed SOAP Envelope");
GetUsernameToken():
WSSecUsernameToken secut = null;
if (event != null) {
UsernameToken ut = event.getSecurity().getUsernameToken();
if (ut.getUsername().length() > 0 &&
ut.getPassword().length() > 0) {
Utils.trace(this.getClass(), "Found P-Mode
'"+pMode.getID()+"' username and password");
secut = new WSSecUsernameToken();
if (ut.isDigest())
secut.setPasswordType(WSConstants.PASSWORD_DIGEST);
else
secut.setPasswordType(WSConstants.PASSWORD_TEXT);
secut.setUserInfo(ut.getUsername(), ut.getPassword());
if (ut.isCreated())
secut.addCreated();
if (ut.isNonce())
secut.addNonce();
secut.prepare(doc);
}
}
return secut;