3

我正在编写一个接收加密 SAML 断言的 Web 服务。在 SAML 断言被加密之前,它可以被验证。

当我的服务解密 EncryptedAssertion 时,它无法验证断言签名

为了研究为什么会这样,我创建了一个小测试:

  1. 创建一个签名的断言(可以验证) - assertion1
  2. 验证 assertion1 上的签名 - 此测试通过
  3. 加密 assertion1 以获得 EncryptedAssertion
  4. 解密 EncryptedAssertion 以取回 Assertion - assertion2
  5. 验证 assertion2 上的签名 - 此测试失败

如果我比较 assertion1 和 assertion2 节点,则只有一个区别。在 Assertion1 中,xmldsig 命名空间在 Assertion 根元素和 ds:Signature 元素中都声明,在 Assertion2 中 Signature 元素上的 xmldsig 命名空间声明已被删除。

就 XML 而言,这是一个完全有效的转换,并且 XML 仍然有效。我的问题是,当进行此更改时,签名不再有效,因为断言上的签名已将现在缺少的前缀声明考虑在内。

有没有一种方法可以指示 OpenSAML 加密器/解密器不要对接收到的 XML 进行“改进”,而只是将最初用作加密器的输入返回?

更改构造包含两个 xmldsig 名称空间声明的 XML 的客户端对我们来说并不是一个真正的选择。是的,但是该服务的客户端是由另一家公司开发的,如果可能的话,我们希望使我们的服务能够应对这种输入问题。

这是我加密断言1的测试代码:

public static EncryptedAssertion encryptAssertion(Assertion assertion, Credential credential) {
    EncryptionParameters encParams = new EncryptionParameters();
    encParams.setAlgorithm(EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128);

    KeyEncryptionParameters kekParams = new KeyEncryptionParameters();
    kekParams.setEncryptionCredential(credential);
    kekParams.setAlgorithm(EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP);
    KeyInfoGeneratorFactory kigf =
            Configuration.getGlobalSecurityConfiguration()
                    .getKeyInfoGeneratorManager().getDefaultManager()
                    .getFactory(credential);
    kekParams.setKeyInfoGenerator(kigf.newInstance());

    Encrypter samlEncrypter = new Encrypter(encParams, kekParams);
    samlEncrypter.setKeyPlacement(Encrypter.KeyPlacement.INLINE);

    try {
        return samlEncrypter.encrypt(assertion);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

这是解密 EncryptedAssertion 的测试代码:

public static Assertion decryptEncryptedAssertion(EncryptedAssertion encryptedAssertion, Credential credentials) throws DecryptionException {
        StaticKeyInfoCredentialResolver staticKeyResolver = new StaticKeyInfoCredentialResolver(credentials);
        InlineEncryptedKeyResolver inlineEncryptedKeyResolver = new InlineEncryptedKeyResolver();

        Decrypter decrypter = new Decrypter(null, staticKeyResolver, inlineEncryptedKeyResolver);

        return decrypter.decrypt(encryptedAssertion);
}

这是 assertion1 的开始:

<?xml version="1.0" encoding="UTF-8"?><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_ede6280e-d094-4b74-a67a-e70bbec6f3e9" IssueInstant="2014-06-23T09:42:33.970Z" Version="2.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameidformat:entity">https://sts.sundhed.dk</saml2:Issuer>
   <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <ds:SignedInfo>

这是 assertion2 的开始 - 请注意,与 assertion1 相比,Signature 节点上的 xmlns:ds 声明缺失:

<?xml version="1.0" encoding="UTF-8"?><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_ede6280e-d094-4b74-a67a-e70bbec6f3e9" IssueInstant="2014-06-23T09:42:33.970Z" Version="2.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameidformat:entity">https://sts.sundhed.dk</saml2:Issuer>
   <ds:Signature>
      <ds:SignedInfo>

更新:这是我在尝试验证 assertion2 上的签名时遇到的异常(当解密后 xmlns:ds 不存在时)。当按照答案中的建议调用decrypter.setRootInNewDocument(true) 时,验证调用成功完成:

org.opensaml.xml.validation.ValidationException: Unable to evaluate key against signature
    at org.opensaml.xml.signature.SignatureValidator.validate(SignatureValidator.java:74)
    at dk.itst.oiosaml.sp.model.OIOSamlObject.verifySignature(OIOSamlObject.java:239)
    at dk.medicinkortet.idws.impl.EncryptedAssertionHandlerImplTest.testDecrypt(EncryptedAssertionHandlerImplTest.java:152)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.apache.xml.security.signature.MissingResourceFailureException: The Reference for URI #_944e39b7-37e2-4cd1-baba-865fb17f645b has no XMLSignatureInput
Original Exception was org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
Original Exception was org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
Original Exception was org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
Original Exception was org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
    at org.apache.xml.security.signature.Manifest.verifyReferences(Manifest.java:414)
    at org.apache.xml.security.signature.SignedInfo.verify(SignedInfo.java:256)
    at org.apache.xml.security.signature.XMLSignature.checkSignatureValue(XMLSignature.java:728)
    at org.opensaml.xml.signature.SignatureValidator.validate(SignatureValidator.java:69)
    ... 34 more
Caused by: org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
Original Exception was org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
Original Exception was org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
Original Exception was org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
    at org.apache.xml.security.signature.Reference.calculateDigest(Reference.java:732)
    at org.apache.xml.security.signature.Reference.verify(Reference.java:775)
    at org.apache.xml.security.signature.Manifest.verifyReferences(Manifest.java:336)
    ... 37 more
Caused by: org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
Original Exception was org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
Original Exception was org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
    at org.apache.xml.security.signature.Reference.dereferenceURIandPerformTransforms(Reference.java:604)
    at org.apache.xml.security.signature.Reference.calculateDigest(Reference.java:706)
    ... 39 more
Caused by: org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
Original Exception was org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
    at org.apache.xml.security.signature.Reference.getContentsBeforeTransformation(Reference.java:419)
    at org.apache.xml.security.signature.Reference.dereferenceURIandPerformTransforms(Reference.java:597)
    ... 40 more
Caused by: org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID _944e39b7-37e2-4cd1-baba-865fb17f645b
    at org.apache.xml.security.utils.resolver.implementations.ResolverFragment.engineResolveURI(ResolverFragment.java:85)
    at org.apache.xml.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:298)
    at org.apache.xml.security.signature.Reference.getContentsBeforeTransformation(Reference.java:417)
    ... 41 more
4

1 回答 1

3

以下可能会解决您的问题:

  • 确保正确认可OpenSAML 附带的库
  • 创建您的 Decrypter 并将 rootInNewDocument 属性设置为 true:

    解密器.setRootInNewDocument(true);

于 2014-06-23T17:29:30.440 回答