Установка расширенного поля метаданных 'signatureAlgorithm'
У меня проблема с получением интеграции Spring SAML для создания правильного файла метаданных для моего IdP. Мне были выданы новые сертификаты SHA256 SSL. Я прошел все шаги по созданию соответствующего хранилища ключей и полностью настроил мой файл конфигурации безопасности Spring. Я буквально нахожусь в 98% случаев, но в сгенерированном файле метаданных отсутствует одна вещь, которую я не могу понять, почему она не устанавливается.
Вот мой конфиг ExtendedMetadata для 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>
Когда я запускаю свое приложение и захожу в URI /saml/metadata, чтобы заставить Spring сгенерировать файл метаданных, который мне нужно отправить в мой IdP, алгоритм SHA256 правильно устанавливается на SignatureMethod, но значение алгоритма дочернего тега DigestMethod все еще установлено в SHA1, когда мне нужно, чтобы ТАКЖЕ было установлено значение SHA256 вместе с DigestValue, которое будет значением SHA256, а не значением SHA1.
<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>
Может кто-нибудь подсказать мне, как / что мне нужно установить, чтобы получить значение алгоритма DigestMethod равным 256? Я подумал, что поскольку он является дочерним по отношению к тегу SignedInfo, он унаследует значение signatureAlgorithm из конфигурации Extendedmetadata, но, увы, это не так.
Любая помощь будет с благодарностью. Спасибо.
РЕШЕНИЕ - На случай, если кому-то все равно
Итак, после целого дня копания я решил просто реализовать это сам. Я расширил класс ExtendedMetadata, добавив поле digestMethodAlgorithm и добавив соответствующий метод получения / установки:
/**
* 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;
}
Затем я изменил свою весеннюю конфигурацию безопасности сверху, чтобы включить это новое свойство bean-компонента, которое будет установлено в моей конфигурации MetadataGenerator:
<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>
Затем мне также пришлось внести два изменения в класс SAMLUtil. В getmetadataAsString в условии if isSignMetadata() я вытащил введенное значение для digestMethodAlgorithm, установленного в приведенной выше конфигурации, а затем дополнительно изменил метод marshallAndSignMessage, чтобы он принимал новый входной параметр, который я в дальнейшем использую, чтобы правильно установить алгоритм DigestMethod,
Внутри SAMLUtil.getMetaDataAsString, строка 572
...
String digestMethodAlgorithm = extendedMetadata.getDigestMethodAlgorithm();
element = SAMLUtil.marshallAndSignMessage(descriptor, credential, signingAlgorithm, digestMethodAlgorithm, keyGenerator);
...
Внутри SAMLUtil.marshallAndSignMessage, сразу после строки 437, я добавил / изменил следующее:
...
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);
}
...
Я перекомпилировал весь основной пакет Spring SAML с помощью Gradle, spring-security-saml-1.0.0.RELEASE, скопировал новый jar из каталога build/libs в мой проект, развернул webapp, указал мой браузер на /saml/metadata и успешно получен файл метаданных с правильной подписанной частью файла метаданных SHA256.
Я собираюсь посмотреть, что я могу сделать, чтобы передать это в репозиторий git для этого проекта, потому что я не хочу терять эту способность, так как проект делает будущие выпуски. Никогда раньше не участвовал в таком проекте с открытым исходным кодом.
<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>
3 ответа
Ситуация изменилась после ответа @VladimírSchäfer; у нас он не работал с AD FS 2.0 и SHA-256. Нам пришлось добавить дополнительные настройки, чтобы заставить его работать (см. Код ниже).
Проблема, по-видимому, заключается в библиотеке xmltooling OpenSAML, особенно в org.opensaml.xml.security.BasicSecurityConfiguration.getSignatureAlgorithmURI(Credential)
метод - вместо того, чтобы просто использовать алгоритм подписи сертификата (в нашем случае, SHA256withRSA
), он получает ключ сертификата, затем просматривает алгоритм этого ключа и использует карту зарегистрированных URI для поиска URI подписи. Если бы у них была просто карта алгоритмов подписи JCA к URI вместо ключевых алгоритмов к URI, все было бы хорошо.
Обходной путь должен зарегистрировать правильный алгоритм подписи URI с BasicSecurityConfiguration
во время весенней проводки, перезаписывая (нежелательный) URI http://www.w3.org/2000/09/xmldsig#rsa-sha1
это уже присутствует с http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
,
Мы также должны были удалить setSignatureReferenceDigestMethod()
вызов или импорт метаданных в AD FS не удастся.
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");
}
}
Вы можете настроить метод дайджеста для вычисления цифровых подписей, выполнив следующий вызов во время инициализации Spring SAML:
// Use SHA-256 signatures for RSA keys
BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration();
config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
Например, расширить по умолчанию org.springframework.security.saml.SAMLBootstrap
и добавьте код в переопределенный метод postProcessBeanFactory после вызова super:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
super.postProcessBeanFactory(beanFactory);
BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration();
config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
}
Это изменение влияет как на подписи в сгенерированных метаданных, так и на подписи в сгенерированных сообщениях SAML.
После внесения изменений в SAMLBootstrap для конфигурации глобальной безопасности я столкнулся со следующим исключением:
org.apache.xml.security.signature.XMLSignatureException: запрошенный алгоритм SHA256 с RSA не существует. Исходное сообщение было: SHA256withRSA MessageDigest недоступно в org.apache.xml.security.algorithms.MessageDigestAlgorithm.getDigestInstance(неизвестный источник) в org.apache.xml.security.algorithms.MessageDigestAlgorithm.getInstance(неизвестный источник) или в неизвестном источнике).security.signature.Reference. (Неизвестный источник) в org.apache.xml.security.signature.Manifest.addDocument (Неизвестный источник) в org.apache.xml.security.signature.XMLSignature.addDocument(Неизвестный источник)
После дальнейшего расследования выяснилось, что Apache XML Security xmlsec-1.4.3.jar
не поддерживает базовый SHA256withRSA
алгоритм.
Разрешение: использовать xmlsec-2.0.2.jar
со https://mvnrepository.com/artifact/org.apache.santuario/xmlsec/2.0.2
Этот новый кувшин решил проблему.