Problems with validating signatures in OpenSAML 3.0

Lasse Højgaard lash at stibosystems.com
Wed Sep 7 08:25:37 EDT 2016


Hi list,

My system is acting as the SP in this case.
I'm trying to validate the signature of incoming assertions, with the public key from the IdP's metadata.

Metadata looks like this:
<EntityDescriptor entityID="REDACTED"><IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><KeyDescriptor use="signing"><ds:KeyInfo><ds:X509Data><ds:X509Certificate>
MIIDkDCCAnigAwIBAgIBBzANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJOTDEQMA4GA1UEBxMH
VVRSRUNIVDETMBEGA1UEChMKUExVU1JFVEFJTDEXMBUGA1UECxMOSU5GUkFTVFJVQ1RVVVIxFDAS
BgNVBAMTC1BMVVMtUm9vdC1QMB4XDTEyMDYwNTA4MjA1N1oXDTE3MDYwNDA4MjA1N1owNzELMAkG
A1UEBhMCTkwxEzARBgNVBAoTClBMVVNSRVRBSUwxEzARBgNVBAMTClBsdXNGZWRJRFAwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxmpGiELeunhLJ5hRW0WXj0S4HGSW3xnQoqaOg0Duj
xA4IH54PqbADSifHI8sFs3RNU8YAhh3hjHDF/im12EN7X4JeSLA/OElqL9HPCuSSYBjgftVe7C20
ccDvkQCKensqRNE+eZWkkzxs6oNNOeizXzRIlFfBAot4Dv1k6sT4jvPNrU7rNPX64Vt2kwzMkDcx
cTqz15f00ymlVsCH5SXYdRBJieVXB08Ij0u+OacZTfH/TUXIdEOsagl0Bf8M5c0gus5NnT6SBna8
TP9Hnnc7KxQoS0Va9AcHmtWPT7NopoygptQ+DcCwvi+TgWlveNTL0XHXqugOfCs2ZGOk8/rnAgMB
AAGjezB5MAsGA1UdDwQEAwIE8DATBgNVHSUEDDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQUWJKwr+Te
Uub5xs0N3EAA75HgfewwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5wbHVzcmV0YWlsLm5s
L3BsdXNwcm9kLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAKytqqAoIS90gi/cl6lX96i8clpEbNSTa
XkNmUoa8Rv3q59w9Mmh2M3XgqP71XIuiLBvdkjmRTET+Yeoszutk1vsOkiuzZzIOfIl8t0x113Ck
Krj3TQCkuifvLUBkofcxovP6vDUaPxNMWHOt8UBSJ2spDynDNHpqmpMEvGbjMAo8taNXEhhmicZB
QUQNgVB1BXMyPr9OeGIxMBWcpaQKcwpcpzcEgObVK9jJaDkPh8P9N8T8nfuRW0jf8lg2/MzPu4c0
bcibooKY39qPSTvIIEHtXFsxKDcQLLw0sMk6ehYQ435Z4LRITErXCGnYjrcMAU6E74Un/LI3+LO0
eZkg9w==
                    </ds:X509Certificate></ds:X509Data></ds:KeyInfo></KeyDescriptor><KeyDescriptor use="encryption"><ds:KeyInfo><ds:X509Data><ds:X509Certificate>
MIIDkDCCAnigAwIBAgIBBzANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJOTDEQMA4GA1UEBxMH
VVRSRUNIVDETMBEGA1UEChMKUExVU1JFVEFJTDEXMBUGA1UECxMOSU5GUkFTVFJVQ1RVVVIxFDAS
BgNVBAMTC1BMVVMtUm9vdC1QMB4XDTEyMDYwNTA4MjA1N1oXDTE3MDYwNDA4MjA1N1owNzELMAkG
A1UEBhMCTkwxEzARBgNVBAoTClBMVVNSRVRBSUwxEzARBgNVBAMTClBsdXNGZWRJRFAwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxmpGiELeunhLJ5hRW0WXj0S4HGSW3xnQoqaOg0Duj
xA4IH54PqbADSifHI8sFs3RNU8YAhh3hjHDF/im12EN7X4JeSLA/OElqL9HPCuSSYBjgftVe7C20
ccDvkQCKensqRNE+eZWkkzxs6oNNOeizXzRIlFfBAot4Dv1k6sT4jvPNrU7rNPX64Vt2kwzMkDcx
cTqz15f00ymlVsCH5SXYdRBJieVXB08Ij0u+OacZTfH/TUXIdEOsagl0Bf8M5c0gus5NnT6SBna8
TP9Hnnc7KxQoS0Va9AcHmtWPT7NopoygptQ+DcCwvi+TgWlveNTL0XHXqugOfCs2ZGOk8/rnAgMB
AAGjezB5MAsGA1UdDwQEAwIE8DATBgNVHSUEDDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQUWJKwr+Te
Uub5xs0N3EAA75HgfewwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5wbHVzcmV0YWlsLm5s
L3BsdXNwcm9kLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAKytqqAoIS90gi/cl6lX96i8clpEbNSTa
XkNmUoa8Rv3q59w9Mmh2M3XgqP71XIuiLBvdkjmRTET+Yeoszutk1vsOkiuzZzIOfIl8t0x113Ck
Krj3TQCkuifvLUBkofcxovP6vDUaPxNMWHOt8UBSJ2spDynDNHpqmpMEvGbjMAo8taNXEhhmicZB
QUQNgVB1BXMyPr9OeGIxMBWcpaQKcwpcpzcEgObVK9jJaDkPh8P9N8T8nfuRW0jf8lg2/MzPu4c0
bcibooKY39qPSTvIIEHtXFsxKDcQLLw0sMk6ehYQ435Z4LRITErXCGnYjrcMAU6E74Un/LI3+LO0
eZkg9w==
                    </ds:X509Certificate></ds:X509Data></ds:KeyInfo><EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"><xenc:KeySize>128</xenc:KeySize></EncryptionMethod></KeyDescriptor>

MetadataResolver:
HTTPMetadataResolver httpMetadataResolver = new HTTPMetadataResolver(httpClient, IDP_METADATA_ENDPOINT);
httpMetadataResolver.setParserPool(XMLObjectProviderRegistrySupport.getParserPool());
httpMetadataResolver.setId(IdentityProviderMetadata.class.getName());
httpMetadataResolver.setRequireValidMetadata(IDP_REQUIRE_VALID_METADATA);
httpMetadataResolver.initialize();
idpEntityDescriptor = httpMetadataResolver.resolveSingle(new CriteriaSet(new EntityIdCriterion(IDP_ENTITY_ID)));
metadataResolver = httpMetadataResolver;


I build a SignatureSigningTrustEngine like this:

public SignatureTrustEngine getSignatureTrustEngine() throws ComponentInitializationException{
	BasicRoleDescriptorResolver basicRoleDescriptorResolver = new BasicRoleDescriptorResolver(getMetadataResolver());
	MetadataCredentialResolver mcr = new MetadataCredentialResolver();
	KeyInfoCredentialResolver keyInfoCredentialResolver = DefaultSecurityConfigurationBootstrap.buildBasicInlineKeyInfoCredentialResolver();
	mcr.setRoleDescriptorResolver(basicRoleDescriptorResolver);
	mcr.setKeyInfoCredentialResolver(keyInfoCredentialResolver);
	mcr.initialize();
	ExplicitKeySignatureTrustEngine trustEngine = new ExplicitKeySignatureTrustEngine(mcr, keyInfoCredentialResolver);
	SignatureTrustEngine sigTrustEngine = trustEngine;
	return sigTrustEngine;
}

Retrieve the MessageContext: 
private MessageContext getMessageContextFromPostRequest(HttpServletRequest req) {
	HTTPPostDecoder decoder = new HTTPPostDecoder();
	decoder.setParserPool(XMLObjectProviderRegistrySupport.getParserPool());
	decoder.setHttpServletRequest(req);
	try {
		decoder.initialize();
	} catch (ComponentInitializationException e) {
		logger.log(Level.SEVERE, "Exception occurred while initializing HTTPPostDecoder", e);
		throw new SAMLRuntimeException(e);
	}

	try {
		decoder.decode();
	} catch (MessageDecodingException e) {
		logger.log(Level.SEVERE, "Exception occurred while decoding Response", e);
		throw new SAMLRuntimeException(e);
	}
	logger.log(Level.FINE, "Successfully decoded SAML messageContext");
	return decoder.getMessageContext();
}

Assertion a = ((Response) messageContext.getMessage()).getAssertions().get(0); 

Validation happens like this:


public void validateResponse(Assertion assertion) throws ComponentInitializationException, SignatureException, SecurityException {
	logger.log(Level.FINEST, "Trying to validate signature of response");
	IdentityProviderMetadata metadataProvider = IdentityProviderMetadata.getInstance();
	if (!assertion.isSigned()) {
		logger.log(Level.SEVERE, "assertion not signed", assertion);
		throw new SAMLRuntimeException("The SAML assertion was not signed");
	}
	SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
	profileValidator.validate(assertion.getSignature());
	
	logger.log(Level.FINEST, "Profilevalidation completed"); // successful
	

	SignatureTrustEngine signatureTrustEngine = metadataProvider.getSignatureTrustEngine();

	CriteriaSet criteriaSet = new CriteriaSet();
	criteriaSet.add( new EntityIdCriterion(assertion.getIssuer().getValue()) );
	criteriaSet.add(new RoleDescriptorCriterion(metadataProvider.getMetadata().getIDPSSODescriptor(SAMLConstants.SAML20P_NS)));
	criteriaSet.add( new UsageCriterion(UsageType.SIGNING) );

	try {
		if (!signatureTrustEngine.validate(assertion.getSignature(), criteriaSet)) {
			// failure happens here
			throw new SecurityException("Signature was either invalid or signing key could not be established as trusted");
		}
	} catch (SecurityException e) {
		// Indicates processing error evaluating the signature
		e.printStackTrace();
	}
}

The received assertion-signature looks like this:

   <saml:Assertion 
        xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
        ID="s29f459001f8ea76a3530240ee8a5f44c7da94b42d" 
        IssueInstant="2016-09-06T13:56:32Z" 
        Version="2.0">
        <saml:Issuer>https://idpt.plus.nl:443/opensso</saml:Issuer>
        <ds:Signature 
            xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
                <ds:CanonicalizationMethod 
                    Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                <ds:SignatureMethod 
                    Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                <ds:Reference 
                    URI="#s29f459001f8ea76a3530240ee8a5f44c7da94b42d">
                    <ds:Transforms>
                        <ds:Transform 
                            Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                        <ds:Transform 
                            Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    </ds:Transforms>
                    <ds:DigestMethod 
                        Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                    <ds:DigestValue>KooY30OgC9PkE4FFbe+
                        1PoUn1RU=
                    </ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>
aF0Le/4XVMTjBVtYtaP4crIgpDFKl2Rz1b5Jxk5t8ov6kNjFjS63SUJDzjvFsR0ZsnFW0DL4Fyuu
70tTt9mm71eafjqKTTwvILRGuOcbI91ZstY4f8ckQi6vb5pIfN8zn3WDyKVnFtmsbd8c63TXVmqR
zsE/PDGYah5Rnur5Gw942EeXcb20OwSuOItim5NYysP5VP116zHIAf1KaMznjNStk0u55s3XQmUY
1IrHDNY6lcv2v7kx7raeYumE++ygNogkOREQ/AoWzzAd9k323FY/z4uZBxaK0e6Ei2F8Vr+05YkJ

                ma4iRLfjAoXIgDQzlXf0QWLRXHZj3Uq2kjhOZg==

            </ds:SignatureValue>
            <ds:KeyInfo>
                <ds:X509Data>
                    <ds:X509Certificate>
MIIDkDCCAnigAwIBAgIBBzANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJOTDEQMA4GA1UEBxMH
VVRSRUNIVDETMBEGA1UEChMKUExVU1JFVEFJTDEXMBUGA1UECxMOSU5GUkFTVFJVQ1RVVVIxFDAS
BgNVBAMTC1BMVVMtUm9vdC1QMB4XDTEyMDYwNTA4MjA1N1oXDTE3MDYwNDA4MjA1N1owNzELMAkG
A1UEBhMCTkwxEzARBgNVBAoTClBMVVNSRVRBSUwxEzARBgNVBAMTClBsdXNGZWRJRFAwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxmpGiELeunhLJ5hRW0WXj0S4HGSW3xnQoqaOg0Duj
xA4IH54PqbADSifHI8sFs3RNU8YAhh3hjHDF/im12EN7X4JeSLA/OElqL9HPCuSSYBjgftVe7C20
ccDvkQCKensqRNE+eZWkkzxs6oNNOeizXzRIlFfBAot4Dv1k6sT4jvPNrU7rNPX64Vt2kwzMkDcx
cTqz15f00ymlVsCH5SXYdRBJieVXB08Ij0u+OacZTfH/TUXIdEOsagl0Bf8M5c0gus5NnT6SBna8
TP9Hnnc7KxQoS0Va9AcHmtWPT7NopoygptQ+DcCwvi+TgWlveNTL0XHXqugOfCs2ZGOk8/rnAgMB
AAGjezB5MAsGA1UdDwQEAwIE8DATBgNVHSUEDDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQUWJKwr+Te
Uub5xs0N3EAA75HgfewwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5wbHVzcmV0YWlsLm5s
L3BsdXNwcm9kLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAKytqqAoIS90gi/cl6lX96i8clpEbNSTa
XkNmUoa8Rv3q59w9Mmh2M3XgqP71XIuiLBvdkjmRTET+Yeoszutk1vsOkiuzZzIOfIl8t0x113Ck
Krj3TQCkuifvLUBkofcxovP6vDUaPxNMWHOt8UBSJ2spDynDNHpqmpMEvGbjMAo8taNXEhhmicZB
QUQNgVB1BXMyPr9OeGIxMBWcpaQKcwpcpzcEgObVK9jJaDkPh8P9N8T8nfuRW0jf8lg2/MzPu4c0
bcibooKY39qPSTvIIEHtXFsxKDcQLLw0sMk6ehYQ435Z4LRITErXCGnYjrcMAU6E74Un/LI3+LO0

                        eZkg9w==

                    </ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </ds:Signature>

The error seems to be in the actual byte comparison for the RSA-SHA1 algorithm.
However! I was able to successfully validate the assertion using the online tool: https://www.samltool.com/validate_response.php 

What am I doing wrong? 

I'm at my wits' end. Any hints will be greatly appreciated!

Lasse Højgaard
Consultant

Stibo Systems A/S
  |  8270  |  Højbjerg  |  Denmark
T +45 89 39 13 23  |  M +45 20 42 45 96
lash at stibosystems.com  |  



More information about the dev mailing list