Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
804 views
in Technique[技术] by (71.8m points)

spring security - Setting the ExtendedMetadata 'signingAlgorithm' field

I'm having an issue getting the Spring SAML integration to generate the correct metadata file for my IdP. I was issued new SHA256 SSL certs. I've gone through all of the steps to create the appropriate keyStore and have my Spring security configuration file all set. I am literally like 98% of the way there but there is one thing missing in the generated metadata file that I can't for the life of me figure out why it's not getting set.

Here is my ExtendedMetadata config for MetadataGeneratorFilter:

<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
    <bean class="org.springframework.security.saml.metadata.MetadataGenerator">
        <property name="entityId" value="urn:myentityidhere"/>
        <property name="entityBaseURL" value="https://${saml.url}"/>
        <property name="extendedMetadata">
            <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
                <property name="signMetadata" value="true"/>
                <property name="signingAlgorithm" value="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
                <property name="alias" value="ceo"/>
                <property name="signingKey" value="${saml.sp.alias}"/>
                <property name="encryptionKey" value="${saml.sp.alias}"/>
            </bean>
        </property>
    </bean>
</constructor-arg>

When I run my app and go to the /saml/metadata URI to get Spring to generate the metadata file I need to send to my IdP, the SHA256 algo gets correctly set on the SignatureMethod, but the child DigestMethod tag's algorithm value is still set to SHA1, when I need that ALSO set to SHA256 along with the DigestValue to be a SHA256 value and not a SHA1 value.

<ds:SignedInfo>
    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
    <ds:Reference URI="#urn_myentityidhere">
        <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>xxxxxxx</ds:DigestValue>
    </ds:Reference>
</ds:SignedInfo>

Can someone guide me in how/what I need to set to get the DigestMethod algorithm value set to 256 also? I figured since it is a child of the SignedInfo tag, it would inherit the signingAlgorithm value from the Extendedmetadata config, but alas it is not.

Any help would be GREATLY appreciated. Thanks so much.

SOLUTION - In case anyone cares

So, after a day's worth of digging, I decided to just implement this myself. I extended the ExtendedMetadata class by adding the field, digestMethodAlgorithm and added the appropriate getter/setters:

/**
 * Algorithm used for creation of digest method of this entity. At the moment only used for metadata signatures.
 * Only valid for local entities.
 */
private String digestMethodAlgorithm;

/**
 * Returns digest method algorithm value
 * @return String
 */
public String getDigestMethodAlgorithm()
{
    return digestMethodAlgorithm;
}

/**
 * Sets the digest method algorithm to use when signing the SAML messages.
 * This can be used, for example, when a strong algorithm is required (e.g. SHA 256 instead of SHA 128).
 * If this property is null, then the {@link org.opensaml.xml.Configuration} default algorithm will be used instead.
 *
 * Value only applies to local entities.
 *
 * At the moment the value is only used for signatures on metadata.
 *
 * Typical values are:
 * http://www.w3.org/2001/04/xmlenc#sha1
 * http://www.w3.org/2001/04/xmlenc#sha256
 * http://www.w3.org/2001/04/xmlenc#sha384
 * http://www.w3.org/2001/04/xmlenc#sha512
 * http://www.w3.org/2001/04/xmlenc#ripemd160
 *
 * @param digestMethodAlgorithm The new digest method algorithm to use
 * @see org.opensaml.xml.signature.SignatureConstants
 */
public void setDigestMethodAlgorithm(String digestMethodAlgorithm)
{
    this.digestMethodAlgorithm = digestMethodAlgorithm;
}

Then I modified my spring security configuration from above to include this new bean property to be set in my MetadataGenerator config:

<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
    <bean class="org.springframework.security.saml.metadata.MetadataGenerator">
        <property name="entityId" value="urn:myentityidhere"/>
        <property name="entityBaseURL" value="https://${saml.url}"/>
        <property name="extendedMetadata">
            <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
                <property name="signMetadata" value="true"/>
                <property name="signingAlgorithm" value="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
                <property name="digestMethodAlgorithm" value="http://www.w3.org/2001/04/xmlenc#sha256"/>
                <property name="alias" value="ceo"/>
                <property name="signingKey" value="${saml.sp.alias}"/>
                <property name="encryptionKey" value="${saml.sp.alias}"/>
            </bean>
        </property>
    </bean>
</constructor-arg>

Then I also had to make two changes to the SAMLUtil class. In getmetadataAsString, in the isSignMetadata() if-clause, I pulled out the injected value for the digestMethodAlgorithm set by the config above and then further modified the marshallAndSignMessage method to accept a new input parameter which I further use to get the DigestMethod algo set properly.

Inside of SAMLUtil.getMetaDataAsString, line 572

...
String digestMethodAlgorithm = extendedMetadata.getDigestMethodAlgorithm();
element = SAMLUtil.marshallAndSignMessage(descriptor, credential, signingAlgorithm, digestMethodAlgorithm, keyGenerator);
...

Inside of SAMLUtil.marshallAndSignMessage, right after line 437, I add/changed the following:

...
BasicSecurityConfiguration secConfig = null;

if (digestMethodAlgorithm != null)
{
    secConfig = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration();

    secConfig.setSignatureReferenceDigestMethod(digestMethodAlgorithm);
}

try {
    SecurityHelper.prepareSignatureParams(signature, signingCredential, secConfig, keyInfoGenerator);
} catch (org.opensaml.xml.security.SecurityException e) {
    throw new MessageEncodingException("Error preparing signature for signing", e);
}
...

I recompiled the entire Spring SAML core package via Gradle, spring-security-saml-1.0.0.RELEASE, copied the new jar from the build/libs directory to my project, deployed the webapp, pointed my browser to /saml/metadata and successfully got the metadata file with the correct SHA256 signed portion of the metadata file.

I'm going to see what I can do about getting this committed to the git repo for this project because I don't want to lose this ability as the project does future releases. Never contributed to an open-source project like this before.

<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#urn_myentityidhere">
    <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/2001/04/xmlenc#sha256"/>
    <ds:DigestValue>xxxxxx</ds:DigestValue>
</ds:Reference>

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Things seem to have changed since the @VladimírSch?fer answer; it did not work for us with AD FS 2.0 and SHA-256. We had to add an extra setting to get it to work (see code, below).

The problem appears to be in OpenSAML's xmltooling library, specifically the org.opensaml.xml.security.BasicSecurityConfiguration.getSignatureAlgorithmURI(Credential) method - instead of just using the signature algorithm of the certificate (in our case, SHA256withRSA), it gets the key of the certificate, then looks at the algorithm of that key and uses a map of registered URIs to look up a signature URI. If they'd just have a map of JCA signature algorithms to URIs, instead of key algorithms to URIs, it would all be fine.

The workaround is to register the correct signature algorithm URI with BasicSecurityConfiguration during Spring wiring, overwriting the (undesirable) URI http://www.w3.org/2000/09/xmldsig#rsa-sha1 that's already present with http://www.w3.org/2001/04/xmldsig-more#rsa-sha256.

We also had to remove the setSignatureReferenceDigestMethod() call, or importing metadata into AD FS would fail.

import org.opensaml.Configuration;
import org.opensaml.xml.security.BasicSecurityConfiguration;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.security.saml.SAMLBootstrap;

public class CustomSamlBootstrap extends SAMLBootstrap {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
super.postProcessBeanFactory(beanFactory); BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration(); config.registerSignatureAlgorithmURI("RSA", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); } }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...