Skip to Content.
Sympa Menu

mace-opensaml-users - Re: Classes needed for validating a saml assertion with a public key

Subject: OpenSAML user discussion

List archive

Re: Classes needed for validating a saml assertion with a public key


Chronological Thread 
  • From: "Håkon Sagehaug" <>
  • To:
  • Subject: Re: Classes needed for validating a saml assertion with a public key
  • Date: Wed, 16 Jan 2008 15:29:08 +0100
  • Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:sender:to:subject:in-reply-to:mime-version:content-type:references:x-google-sender-auth; b=r66fXiKCMFy5qbkt1w0zTjayZRJBknCpBwJvMGLsXztDMu1CfSegPG6jkAlveAdik1DGVWy11edMMobsfFV3hpD6ybsCJobOwkSrixW/Q6eI41csrQBx0bB6TJeASV1bsODOmRVZnLHaprEQkoYU3Gsvj0sMMwuz4t6MHNvpXVk=



2008/1/15, Brent Putman <>:
Sorry for the delay in replying... see below


Håkon Sagehaug wrote:

Note these trust engines are primarily for cases where you just want to
establish trust of a key/cert that has been presented, where any crypto
has already been performed (so e.g. establish trust of a client TLS
cert).  If what you're trying to do is validate an XML or raw/blob
signature, there are SignatureTrustEngine impls that do the signature
validation and then establish trust using similar mechanisms and logic
(explicit key vs. PKIX).  Those are in the signature and signature.impl
packages in java-xmltooling.  It wasn't quite clear from your question
what you wanted to do (i.e. validate the Assertions's signature?).

I was not sure about that when I wrote this either, but now it seems that I need to verify the signature from the public key inside the assertion and verify that the public key is among the trusted host certificated located in the trusted files director.

Ok, I thought you might have been wanting to validate a holder-of-key SubjectConfirmation or something.  Also, when  you said directory, I wasn't sure whether you meant filesystem directory or LDAP directory.

Ok, so if you want to validate an XML signature against a set of trusted keys you know (possess) in advance, and you want the highest level API possible, then you probably want to use the ExplicitKeySignatureTrustEngine.  This requires a CredentialResolver to resolve the trusted Credentials (trusted keys/certs you possess, owned by the remote peers which are doing the signing), and a KeyInfoCredentialResolver, to resolve the signing key hint from the Signature/KeyInfo (if present).

A default config of a KeyInfoCredentialResolver, which handles the common cases (inline RSA and DSA KeyValues and X509Certificates) can be obtained from:
org.opensaml.Configuration.getGlobalSecurityConfiguration().getDefaultKeyInfoCredentialResolver().

For the trusted CredentalResolver you need one that holds or resolves the trusted certs.  You could either write an impl of our CredentialResolver interface that reads the certs in from your filesystem directory and returns populated Credential objects (that's going to give you the most flexibility and possibly more efficiency), or you could take an easier route and just read in and process your certs into Java X509Certificate objects however you want, transform each into a Credential (a BasicX509Credential in reality), populate a List<Credential> and create a StaticCredentialResolver or CollectionCredentialResolver with that list.

The difference between the static one and the collection one is that the collection one actually evaluates any evaluable Criteria which are passed as input to the trust engine (see below), as where the static one doesn't - it always just returns the Credentials that were passed into the constructor.

You then just instantiate the trust engine like so:

SignatureTrustEngine trustEngine = new ExplicitKeySignatureTrustEngine(trustedCredResolver, keyInfoCredResolver);
       



Then when you need to evaluate an assertion's Signature token:

CriteriaSet criteriaSet = new CriteriaSet();
// here add whatever criteria are necessary to the set, e.g. the entity ID of the signer
       
Signature signature = assertion.getSignature();
       
if (trustEngine.validate(signature, criteriaSet)) {
    // signature was valid and signed by a trusted key
} else {
    // signature was either not valid
    // or was not signed by a trusted key
}


The Criteria you add to the CriteriaSet as input to the resolver is resolver-specific.  If you use the StaticCredentialResolver, you can just pass in an empty set b/c criteria aren't evaluated (the static List of credentials is always returned).  If you use the CollectionCredentialResolver you might want to add an EntityIDCriteria so you only resolve credentials for that entity ID, but that only works if the Credentials in the trusted set have the entityID property on them populated.  If you do your own impl of a CredentialResolver then it's completely up to you what criteria are required.

For example, when using the MetadataCredentialResolver to resolve trusted credentials from SAML 2 metadata, you must specify an EntityIDCriteria and MetadataCriteria (the latter scopes the SAML metadata role descriptor and protocol) and optionally a UsageCriteria, which constrains the types of KeyDescriptors from which to resolve keys (signing vs encryption).


Now my host cert either have the extension .pem or hash_value.0, because I looed at the FilesystemCredentialResolver but the extension accepted there does not mach what I got, I think.


No, it doesn't exactly match what you need, and it's also currently unimplemented and I doubt it will be for 2.0.  Probably for 2.1.


Is there a another way or doing the same thing, loading all the certificates from a directory?

No, not really, but writing an impl of CredentialResolver to do this should be pretty easy.  However, you may need to decide on mechanisms or conventions  for storing and populating the entity ID and maybe key names and/or usage info (signing vs. encryption) for the credentials in the filesystem directory, so as to populate the info on the Credential properties.  Depends on what you want the resolver to support.


Of course you could also just avoid all this by using SAML metadata for storing your peer keys, and then use the MetadataCredentialResolver.  That's exactly the kind of thing that metadata is for .  :-)



I guess I could go through the trusted directory create java x509Cerfiticate, then create opensaml credentials from these and use this to validate the public key contained in the saml assertion



If you wanted a lower level API than the trust engines, you could just create a set of Credentials from your trusted certs and use the SignatureValidator directly - which merely handles the cryptographic validation of the ds:Signature.  The trust would be implicitly established since you know the certs are trusted.  You could optionally short-circuit which Credentials/keys to evaluate by using validation key (hint!) as provided by the ds:KeyInfo.    And this is in fact exactly what the ExplicitKeySignatureTrustEngine does.  If just has a more complex API because the trust engines are designed for a broader variety of use cases.

Hi

Thanks for all the replays. So the *TrustEngines does both the trust evaluation of the keyInfo element and validating the signature inside the ds:signatureValue element. I've tried the approach with SignatureValidator, after I've checked that I trust the x509Certificate inside keyInfo,
and done

SignatureValidator validator = new SignatureValidator(x509Credential);
where x509Credential is made from the info inside keyINfo

and tried did

validator.validate(samlAssertion.getSignature())

but I always get this back

WARN  o.a.xml.security.signature.Reference - Verification failed for URI "#_05d3afc2-0e55-482e-a2b6-1533fa17f109"
DEBUG o.o.xml.signature.SignatureValidator - Signature did not validate against the credential's key


HTH,
Brent




--
Håkon Sagehaug
Research Assistant
Parallab
Bergen Center for Computational Science (BCCS)
UNIFOB AS (University of Bergen Research Company)


Archive powered by MHonArc 2.6.16.

Top of Page