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: Brent Putman <>
  • To:
  • Subject: Re: signature validation in OpenSAML2
  • Date: Fri, 07 Dec 2007 13:57:45 -0500

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,
>
>



Archive powered by MHonArc 2.6.16.

Top of Page