I am writing a web service that receives an encrypted SAML assertion. Before the SAML assertion was encrypted it could be verified.
When my service decrypts the EncryptedAssertion it can not verify the assertion signature
To look into why that is, I created a small test that:
- Creates a signed Assertion (that can be verified) - assertion1
- Verified the signature on assertion1 - this test passes
- Encrypts assertion1 to get an EncryptedAssertion
- Decrypts the EncryptedAssertion to get back an Assertion - assertion2
- Verifies the signature on assertion2 - this test fails
If I compare the assertion1 and assertion2 nodes there is only one difference. In Assertion1 the xmldsig namespace is declared both in the Assertion root element and again in the ds:Signature element, in Assertion2 the xmldsig namespace declaration on the Signature element has been removed.
XML-wise this is a perfectly valid transformation and the XML is still valid. My problem is that when this alteration is made the signature is no longer valid since the signature on the Assertion has taken the now missing prefix declaration into account.
Is there a way I can instruct the OpenSAML Encrypter/Decrypter to not 'improve' on the received XML, and just give back what was used as input to the encrypter initially?
Changing the client that constructs the XML containing two declarations of the xmldsig namespace is not really an option for us. Well it is, but the client for this service is developed by another company and if possible we would prefer to make our service robust to this kind of problems with the input.
Here is my test code that encrypts assertion1:
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);
}
}
This is the test code that decrypts the 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);
}
This is the beginning of 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>
This is the beginning of assertion2 - notice that compared to assertion1 the xmlns:ds declaration on the Signature node is missing:
<?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>
Update: This is the exception I get when attempting to verify the signature on assertion2 (when the xmlns:ds is not there after decryption). When calling decrypter.setRootInNewDocument(true) as suggested in the answer the validate call completes successfully:
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