Skip to Content.
Sympa Menu

mace-opensaml-users - Re: signature validation in OpenSAML2

Subject: OpenSAML user discussion

List archive

Re: signature validation in OpenSAML2


Chronological Thread 
  • From: Chad La Joie <>
  • To:
  • Subject: Re: signature validation in OpenSAML2
  • Date: Tue, 11 Dec 2007 08:02:08 +0100
  • Organization: SWITCH

I wouldn't be surprised if your SOAP container is changing the message in some fashion. Axis, at least at one point, had a nasty habit of screwing with namespace prefixs before it sent out a message, this then invalidated any signature that it didn't control. Such problems tend to be very difficult to detect.

Kenny Pearce wrote:
I am able to validate the signature on the client side, and I've
verified that the message looks the same on the client side and on the
server side, when printed out from java using SOAPMessage.writeTo(). I
set the rootLogger to DEBUG, and got tons of output, most of which
doesn't mean anything to me, but this part looked like it might be
relevant:

----------------
2007-12-10 15:50:35.725 DEBUG - Attempting to validate signature using
key from supplied credential
2007-12-10 15:50:35.729 DEBUG - Creating XMLSignature object
2007-12-10 15:50:35.729 DEBUG - verify 1 References
2007-12-10 15:50:35.734 DEBUG - I am not requested to follow nested
Manifests
2007-12-10 15:50:35.734 DEBUG - setElement("ds:Reference", "")
2007-12-10 15:50:35.734 DEBUG - setElement("ds:Transforms", "")
2007-12-10 15:50:35.735 DEBUG - Request for URI
http://www.w3.org/2000/09/xmldsig#sha1
2007-12-10 15:50:35.735 DEBUG - I was asked to create a ResourceResolver
and got 0
2007-12-10 15:50:35.735 DEBUG - extra resolvers to my existing 4
system-wide resolvers
2007-12-10 15:50:35.735 DEBUG - check resolvability by class
org.apache.xml.security.utils.resolver.implementations.ResolverFragment
2007-12-10 15:50:35.735 DEBUG - State I can resolve reference:
"#pg4R25EQ0Xvj.tCuFMTsb"
2007-12-10 15:50:35.735 DEBUG - getElementByIdType() Search for ID
pg4R25EQ0Xvj.tCuFMTsb
2007-12-10 15:50:35.735 DEBUG - getElementByIdUsingDOM() Search for ID
pg4R25EQ0Xvj.tCuFMTsb
2007-12-10 15:50:35.735 DEBUG - I could find an Element using the simple
getElementByIdUsingDOM method: saml:Assertion
2007-12-10 15:50:35.736 DEBUG - Try to catch an Element with ID
pg4R25EQ0Xvj.tCuFMTsb and Element was [saml:Assertion: null]
2007-12-10 15:50:35.736 DEBUG - setElement("ds:Transform", "")
2007-12-10 15:50:35.736 DEBUG - Preform the (0)th
http://www.w3.org/2000/09/xmldsig#enveloped-signature transform
2007-12-10 15:50:35.736 DEBUG - setElement("ds:Transform", "")
2007-12-10 15:50:35.736 DEBUG - setElement("ec:InclusiveNamespaces", "")
2007-12-10 15:50:35.737 INFO - Verification successful for URI
"#pg4R25EQ0Xvj.tCuFMTsb"
2007-12-10 15:50:35.737 DEBUG - The Reference has Type 2007-12-10 15:50:35.737 DEBUG - SignatureMethodURI =
http://www.w3.org/2000/09/xmldsig#rsa-sha1
2007-12-10 15:50:35.737 DEBUG - Create URI
"http://www.w3.org/2000/09/xmldsig#rsa-sha1"; class "class
org.apache.xml.security.algorithms.implementations.SignatureBaseRSA
$SignatureRSASHA1"
2007-12-10 15:50:35.737 DEBUG - Request for URI
http://www.w3.org/2000/09/xmldsig#rsa-sha1
2007-12-10 15:50:35.737 DEBUG - Created SignatureDSA using SHA1withRSA
2007-12-10 15:50:35.737 DEBUG - jceSigAlgorithm = SHA1withRSA
2007-12-10 15:50:35.737 DEBUG - jceSigProvider = SunRsaSign
2007-12-10 15:50:35.738 DEBUG - PublicKey = Sun RSA public key, 512 bits
modulus:
11917871527246057771552089994960395089648245713568677534401387968986688360812296227814709715932744936657696959516727964652299195519294629634916966166224953
public exponent: 65537
2007-12-10 15:50:35.739 DEBUG - Signature did not validate against the
credential's key
----------------

None of this looks like an explanation of the validation failure to me.
Any ideas? Is there something else I should be looking for in the rest
of the output?

Thanks.

On Fri, 2007-12-07 at 13:57 -0500, Brent Putman wrote:
Hi Kenny,
What you're doing there looks functionally correct, no obvious problems
that I can see. No, you don't need to do anything to the Credential in
order to validate, all that's needed within the Credential for the
signing and validation operations are the key(s).

So the obvious observation would be, assuming that you're seeing it fail
in an actual client/server exchange, is that the document really is
getting changed somehow in transit, and that's breaking the signature. So this is a SAML token attached within a WS-Security header? For
example, something in the serialization on the client and/or
deserialization and unmarshalling process on the server, could be
changing whitespace, namespaces, etc. Have you tried running the same
signing and validation code inside a single JVM process (unit test or
whatever) one immediately after the other, to see if that is
succeeding? If so, then that's your answer.

On the server (validation) side, it might be helpful to get a log trace
on DEBUG minimally from packages org.opensaml.xml.security,
org.opensaml.xml.signature and in particular org.apache.xml.security. The Apache lib is what is actually doing the validation operation. That
should provide more details on exactly why it is failing.

Some other observations, not directly related to your problem:
The entityId member on the credential is intended to be the owning
entity ID of the Credential's key. The getID from the SAML object is
the Assertion ID or Request/Response message ID. Those are 2 totally
different things, so you shouldn't be calling Credential#setEntityId
like that. But like I said, you don't need to set the entityID on the
Credential at all, it's not relevant here.

FYI, there's a utility method org.opensaml.xml.security.SecurityHelper#getSimpleCredential that can
build the credential with the key(s) if you already have keys and just
need a Credential. Ordinarily we resolve Credentials from a
CredentialResolver, though.

For your production code KeyInfo handling, you may want to take a look
at the KeyInfoCredentialResolver so that you don't hardcode assumptions
about what kind of keys are being used (i.e. might have an
X509Data/X509Certificate rather than a KeyValue).

Also be aware that this approach doesn't in any way handle establishing
that you trust the key used by the signer. If you are not otherwise
handling that outside of what you illustrate here, you might want to
take a look at the SignatureTrustEngine impls we have, which both
cryptographically validate the Signature as you're doing here as well as
establish trust of the signing key based on various approaches (known
trusted credentials and PKIX).

--Brent



Kenny Pearce wrote:
Hi again,
I've written a (relatively) simple test application, for trying to use
OpenSAML2 in WSS with JAX-WS. To simplify things, I tried just having
the client generate a KeyPair and put the public key in the KeyInfo
element, so that the server could pull it out and use it to validate the
signature. I've verified that the public key the server is pulling out
matches the one the client is putting in, but the signature is being
reported as invalid. I'm signing like this:


-----------------------
Signature sig =
((XMLObjectBuilder<Signature>)buildFact.getBuilder(Signature.DEFAULT_ELEMENT_NAME)).buildObject(Signature.DEFAULT_ELEMENT_NAME);

BasicCredential cred = new BasicCredential();
cred.setEntityId(saml.getID());

cred.setPrivateKey(keys.getPrivate());
cred.setPublicKey(keys.getPublic());

sig.setSigningCredential(cred);
sig.setSignatureAlgorithm(RSA_ALG);

sig.setCanonicalizationAlgorithm("http://www.w3.org/TR/2001/REC-xml-c14n-20010315";);

KeyInfo inf =
((XMLObjectBuilder<KeyInfo>)buildFact.getBuilder(KeyInfo.DEFAULT_ELEMENT_NAME)).buildObject(KeyInfo.DEFAULT_ELEMENT_NAME);
KeyInfoHelper.addPublicKey(inf, keys.getPublic());

sig.setKeyInfo(inf);

saml.setSignature(sig);

[snip]

Element elem =
Configuration.getMarshallerFactory().getMarshaller(saml).marshall(saml);
Signer.signObject(saml.getSignature());
-----------------------


And I'm validating like this:

-----------------------
BasicCredential cred = new BasicCredential();
try{
cred.setPublicKey(KeyInfoHelper.getKey(saml.getSignature().getKeyInfo().getKeyValues().get(0)));
}catch(Exception e){
throw new ValidationException("Could not get public
key", e);
}
cred.setEntityId(saml.getID());
SignatureValidator sigval = new SignatureValidator(cred);
sigval.validate(saml.getSignature());
-----------------------

The very last line of the snippet above throws a ValidationException
saying that the signature is invalid. Am I doing something wrong? Do I
need to set more fields of the BasicCredential before I can validate?

Thanks,


--
SWITCH
Serving Swiss Universities
--------------------------
Chad La Joie, Software Engineer, Security
Werdstrasse 2, P.O. Box, 8021 Zurich, Switzerland
phone +41 44 268 15 75, fax +41 44 268 15 68
,
http://www.switch.ch



Archive powered by MHonArc 2.6.16.

Top of Page