Как диагностировать / исправить сбой проверки дайджеста подписи в ответе веб-службы?

#spring-boot #spring-ws #ws-security #wss4j

#весенняя загрузка #spring-ws #ws-безопасность #wss4j #ws-security

Вопрос:

Я использую wss4jSecurityInterceptor для действий по проверке и обеспечению безопасности в моем веб-сервисе. Сообщения SOAP туда и обратно защищены подписью, шифрованием и меткой времени. Проблема, с которой я сталкиваюсь, заключается в том, что получатель не может проверить мою подпись ответа и получает следующую ошибку:

oracle.wsm.security.Исключение SecurityException: WSM-00061: сбой проверки дайджеста подписи. Системное свойство xml.debug.verify должно быть включено для получения подробной информации о вычислениях дайджеста на этапе проверки (обратите внимание, что xml.debug.verify замедляет проверку подписи для очень больших сообщений).

Вот код, который я использую для выполнения действий по проверке и обеспечению безопасности:

 @EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
    private static Log log = LogFactory.getLog(WebServiceConfig.class);
    @Bean
    public KeyStoreCallbackHandler securityCallbackHandler() {
        KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
        callbackHandler.setPrivateKeyPassword("changeit");
        return callbackHandler;
    }
@Bean
public Wss4jSecurityInterceptor securityInterceptor() throws Exception {
    Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
    // validate incoming request
    securityInterceptor.setValidationActions("Timestamp Signature Encrypt");
    securityInterceptor.setValidationSignatureCrypto(getCryptoFactoryBean().getObject());
    securityInterceptor.setValidationDecryptionCrypto(getCryptoFactoryBean().getObject());
    securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());

    // encrypt the response
    securityInterceptor.setSecurementEncryptionUser("client_pub"); // alias of client public key
    securityInterceptor.setSecurementEncryptionParts("{Content}{}Body");

    securityInterceptor.setSecurementEncryptionKeyIdentifier("DirectReference");
    securityInterceptor.setSecurementEncryptionCrypto(getCryptoFactoryBean().getObject());

    // sign the response
    securityInterceptor.setSecurementSignatureAlgorithm(WSS4JConstants.RSA_SHA1);
    securityInterceptor.setSecurementSignatureDigestAlgorithm(WSS4JConstants.SHA1);
    securityInterceptor.setSecurementSignatureKeyIdentifier("DirectReference");
    securityInterceptor.setSecurementActions("Encrypt Signature Timestamp");
    securityInterceptor.setSecurementUsername("secret"); // alias of the private key
    securityInterceptor.setSecurementPassword("changeit");
    securityInterceptor.setSecurementSignatureCrypto(getCryptoFactoryBean().getObject());

    return securityInterceptor;
}
@Bean
public CryptoFactoryBean getCryptoFactoryBean() throws IOException {
    CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
    cryptoFactoryBean.setKeyStorePassword("changeit");
    cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("cert/myKeystore.jks"));
    return cryptoFactoryBean;
}

@Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        try {
            interceptors.add(securityInterceptor());
        } catch (Exception e) {
            throw new RuntimeException("could not initialize security interceptor");
        }
    }

@Bean
public ServletRegistrationBean<MessageDispatcherServlet> registerMessageDispatcherServlet(
        ApplicationContext context) {

    MessageDispatcherServlet messageDispatcherServlet = new MessageDispatcherServlet();
    messageDispatcherServlet.setApplicationContext(context);
    messageDispatcherServlet.setTransformWsdlLocations(true);
    return new ServletRegistrationBean<MessageDispatcherServlet>(messageDispatcherServlet, "/ws/*");
}
  

Принимающая сторона подозревает, что ошибка вызвана тем фактом, что сертификат, отправленный как, был поврежден последовательностью символов возврата каретки. Вот как это выглядит:

   <wsse:BinarySecurityToken
    EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
    ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
    wsu:Id="X509-124b3a03-73e3-4838-a254-f20883ff4184">MIIG1zCCBb gAwIBAgIRAIVi4APh2tBtAAAAAFDvSXwwDQYJKoZIhvcNAQELBQAwgboxCzAJBgNVamp;#13;
    BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Quamp;#13; bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1amp;#13; dGhvcml6ZWQgdXNlIG9ubHkxLjAsBgNVBAMTJUVudHJ1c3QgQ2VydGlmaWNhdGlvbiBBdXRob3Jpamp;#13;
    dHkgLSBMMUswHhcNMTkwMzIyMTY1ODA5WhcNMjAwMzIyMTcyODA4WjCBgjELMAkGA1UEBhMCVVMxamp;#13; EzARBgNVBAgTCkNhbGlmb3JuaWExETAPBgNVBAcTCEJlcmtlbGV5MS4wLAYDVQQKEyVMYXdyZW5jamp;#13; ZSBCZXJrZWxleSBOYXRpb25hbCBMYWJvcmF0b3J5MRswGQYDVQQDExJtc2cudWNwLWl0LmxibC5namp;#13;
    b3YwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9fSfO1cKz1D34dQaQF1ScY0eEGALmamp;#13; s3hkRRWMYPWTH8gZRpfP4iFLF9Sx09vagGFHUrru1xf8BnVyB2CsZnvHtE bDrK4kp4hQpO8aXqfamp;#13; VEpn SpY38aQDfZUqjRK6HJM5qxF/2xjNKSw41MPkXALK04yga07IwSUE GpPt8i2noQPKKJufzfamp;#13;
    guA8Plmsnf9uNcpxFezNXC1k HQBKeO0V CZ4K5FKyckq64eT8VWbawF5CFoNigtbxTuHHClECV0amp;#13; VrzNNf5jj/cpymwOu51ljnPhGEY/f73DlEBZg8jpFcDSnAyYyJH2GFgz2wa0TiOpdxItTWHMXalbamp;#13; YtDH9VvRAgMBAAGjggMMMIIDCDAdBgNVHREEFjAUghJtc2cudWNwLWl0LmxibC5nb3YwggF/Bgoramp;#13;
    BgEEAdZ5AgQCBIIBbwSCAWsBaQB2AFWB1MIWkDYBSuoLm1c8U/DA5Dh4cCUIFy jqh0HE9MMAAABamp;#13; aaZyHvYAAAQDAEcwRQIhAJtC0LBFOfupRDy6BOvRrH6pAlvAJFFUWxMbbSRV59nOAiB/c2D5VOwSamp;#13; aBeC4czjDjUAAfeunN/npVLyX7i6v69aLgB3AId1v dZfPiMQ5lfvfNu/1aNR1Y2/0q1YMG06v9eamp;#13;
    oIMPAAABaaZyHwQAAAQDAEgwRgIhAJj/g/g UjWaoHCl7ldHG08zuUrL8XbAkR8Op4G //nvAiEAamp;#13; sLoq29TrwnOtWa O1 PRHCCllKD22yeKxdMUNrR2Pu0AdgCyHgXMi6LNiiBOh2b5K7mKJSBna9r6amp;#13; cOeySVMt74uQXgAAAWmmch7YAAAEAwBHMEUCIBVGxbR2c/ByOtfDRMlpIFPRYA5 dGkB4zJ7tjQ6amp;#13;
    moYYAiEAmFbeJdg9rCZt6qUqhRH2mxJlotRjp mZmiHyRFmulykwDgYDVR0PAQH/BAQDAgWgMB0Gamp;#13; A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Jsamp;#13; LmVudHJ1c3QubmV0L2xldmVsMWsuY3JsMEsGA1UdIAREMEIwNgYKYIZIAYb6bAoBBTAoMCYGCCsGamp;#13;
    AQUFBwIBFhpodHRwOi8vd3d3LmVudHJ1c3QubmV0L3JwYTAIBgZngQwBAgIwaAYIKwYBBQUHAQEEamp;#13; XDBaMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAzBggrBgEFBQcwAoYnaHR0amp;#13; cDovL2FpYS5lbnRydXN0Lm5ldC9sMWstY2hhaW4yNTYuY2VyMB8GA1UdIwQYMBaAFIKicHTdvFM/amp;#13;
    z3vU981/p2DGCky/MB0GA1UdDgQWBBRzakStBRG3O6NBdLt1XUkvwwKn4jAJBgNVHRMEAjAAMA0Gamp;#13; CSqGSIb3DQEBCwUAA4IBAQAqt00w3oV4XgcdhcanJdgY/SUCtmN9I4jdras8vRson wK6WJy6Em8amp;#13; EF5wyRDLOwUD75Rm9Ak23lKjYOcDTWQGG3YXrYh7xe3J8C plEY1NAwNPXflCzxkDcdJ4pX0LDfjamp;#13;
    aC5FniAvKJ9ET7ZQvpCjBRd7wgOrkuhf3YjCFC3hM4E6D7cGb6DEhCh9nOy e9woQ/C1LnDil3NXamp;#13; Vgqk3PMZYkUeHjxqItnDcOAeJaeqsAUiTxZbC8sQQ9ae/CPahghgSWEwL7tMrAH4nGT3yeBQl0I9amp;#13; O7H9xWj0ooQ8Wt6nO7pq64X5uc7W6iA3/1Of5uCntmMrsqPlvSscP6QVuPw6</wsse:BinarySecurityToken>
  

Мое хранилище ключей находится в формате PKCS, и я также преобразовал его в jks. Нет кубиков. Сертификаты в хранилище ключей отлично проверяются с помощью команды openssl, поэтому я знаю, что они хороши.

Я делаю свои сборки на Mac и развертываю на CentOS. Я также скопировал исходные тексты в CentOS и запустил сборку там. Опять же, это не имело никакого значения.

Кто-нибудь сталкивался с этой проблемой и решал ее? Был бы признателен за любую помощь!

Большое спасибо!

Комментарии:

1. РЕДАКТИРОВАТЬ: последовательность символов возврата каретки «amp; # 13;» была опущена из текста моего исходного сообщения. Скорее всего, был заменен фактическим возвратом каретки!

Ответ №1:

библиотека xmlsec обновлена до 2.1.3. wss4j-ws-security-dom обновлена до 2.2.3

Подробности: проблема была узкой и очень неясной. Я не вернул все, что я сделал, к тому, как это было, чтобы увидеть, вернется ли проблема, но мог бы сделать это легко. Мы используем spring-ws-security и WSS4Jfrom от apache для выполнения действий по проверке и обеспечению безопасности. Обе библиотеки включают xmlsec.jar который обеспечивает эту функциональность. Фактически wss4j включает его дважды, поскольку он также встраивает opensaml , который, в свою очередь, содержит xmlsec. Spring-ws-security также содержит свой собственный xmlsec. Все они разные версии. Проблема с возвратом каретки сообщается для версий xmlsec 2.1.0 и выше.

https://issues.apache.org/jira/browse/SANTUARIO-482

https://issues.apache.org/jira/browse/SANTUARIO-494

Я обновил wss4j до версии 2.2.3 (где это якобы исправлено), а также добавил исправленную версию xmlsec.jar непосредственно для пущей убедительности.

Надеюсь, это поможет кому-то еще. 🙂