Problem verifying signature on encrypted & signed message.

Hi,
I’ve got an IdP set up on Azure using ADFS. I’ve two instances there - one which will sign the reply and one which signs and encrypts it.
When I try to process the assertions at my SP the signed one is OK but the encrypted one always returns false on the verify (I’ve checked the decrypted Xml visually and it looks OK).
I’m on an evaluation copy of ComponentSpace - version 2.6.0.19.
I’ve copied the relevant code below - if anyone has any ideas they’d be appreciated.
Regards
Paul
(If I change it so it’s using the key in the assertion rather than a stored key it also fails).


X509Certificate2 x509Certificate = new X509Certificate2(Encoding.UTF8.GetBytes(_ssoMetaData.IP.SigningCertificateData), (string)null, X509KeyStorageFlags.MachineKeySet);

// decrypt and verify any encrypted Assertions
if (samlResponse.GetEncryptedAssertions().Count > 0)
{
// Load the private key.
X509Certificate2 decryptionKey = new X509Certificate2(_ssoMetaData.SP.CertificateLocation, _ssoMetaData.SP.CertificatePassword);
foreach (var encryptedAssertion in samlResponse.GetEncryptedAssertions())
{
var key = decryptionKey.PrivateKey.ToXmlString(false);
// Decrypt the encrypted assertion.
var decryptedAssertion = encryptedAssertion.Decrypt(decryptionKey.PrivateKey).ToXml();
if (SAMLAssertionSignature.IsSigned(decryptedAssertion))
{
if (!SAMLAssertionSignature.Verify(decryptedAssertion, x509Certificate))
{
throw new System.ApplicationException(“The SAML response signature failed to verify.”);
}
}
}
}
else
{
var samlAssertion = samlResponse.GetSignedAssertions().FirstOrDefault();
if (samlAssertion != null)
{
if (SAMLAssertionSignature.IsSigned(samlAssertion))
{
if (!SAMLAssertionSignature.Verify(samlAssertion, x509Certificate))
{
throw new System.ApplicationException(“The SAML response assertion failed to verify the signature.”);
}
}
}
}

[quote]
pyates - 4/5/2017
Hi,
I've got an IdP set up on Azure using ADFS. I've two instances there - one which will sign the reply and one which signs and encrypts it.
When I try to process the assertions at my SP the signed one is OK but the encrypted one always returns false on the verify (I've checked the decrypted Xml visually and it looks OK).
I'm on an evaluation copy of ComponentSpace - version 2.6.0.19.
I've copied the relevant code below - if anyone has any ideas they'd be appreciated.
Regards
Paul
(If I change it so it's using the key in the assertion rather than a stored key it also fails).


X509Certificate2 x509Certificate = new X509Certificate2(Encoding.UTF8.GetBytes(_ssoMetaData.IP.SigningCertificateData), (string)null, X509KeyStorageFlags.MachineKeySet);

// decrypt and verify any encrypted Assertions
if (samlResponse.GetEncryptedAssertions().Count > 0)
{
// Load the private key.
X509Certificate2 decryptionKey = new X509Certificate2(_ssoMetaData.SP.CertificateLocation, _ssoMetaData.SP.CertificatePassword);
foreach (var encryptedAssertion in samlResponse.GetEncryptedAssertions())
{
var key = decryptionKey.PrivateKey.ToXmlString(false);
// Decrypt the encrypted assertion.
var decryptedAssertion = encryptedAssertion.Decrypt(decryptionKey.PrivateKey).ToXml();
if (SAMLAssertionSignature.IsSigned(decryptedAssertion))
{
if (!SAMLAssertionSignature.Verify(decryptedAssertion, x509Certificate))
{
throw new System.ApplicationException("The SAML response signature failed to verify.");
}
}
}
}
else
{
var samlAssertion = samlResponse.GetSignedAssertions().FirstOrDefault();
if (samlAssertion != null)
{
if (SAMLAssertionSignature.IsSigned(samlAssertion))
{
if (!SAMLAssertionSignature.Verify(samlAssertion, x509Certificate))
{
throw new System.ApplicationException("The SAML response assertion failed to verify the signature.");
}
}
}
}

[/quote]

Think I may have resolved this - rather than using encryptedAssertion.Decrypt(decryptionKey.GetRSAPrivateKey()).ToXml() I've changed it to encryptedAssertion.DecryptToXml(decryptionKey.GetRSAPrivateKey()) and that seems to be working.
Thanks to anyone who's already had a look.

Cheers

Paul



Hi Paul
Thanks for the update.
You’re using the SAML low-level API. I recommend using the SAML high-level API if possible as it’s simpler to use. You’ll find example projects under the Examples\SSO\HighLevelAPI folder. There’s also documentation on the API and SAML configuration in our Developer Guide PDF.
Regarding the issue you saw, the EncryptedAssertion.Decrypt method decrypts the SAML assertion and deserializes it to a SAMLAssertion object.
The SAMLAssertion.ToXml method doesn’t guarantee the XML will be exactly the same as the original XML.
That’s why you should call EncryptedAssertion.DecryptToXML instead so the original XML is preserved.
You can then verify the signature of this XML before deserializing it to a SAMLAssertion object.

[quote]
ComponentSpace - 4/5/2017
Hi Paul
Thanks for the update.
You're using the SAML low-level API. I recommend using the SAML high-level API if possible as it's simpler to use. You'll find example projects under the Examples\SSO\HighLevelAPI folder. There's also documentation on the API and SAML configuration in our Developer Guide PDF.
Regarding the issue you saw, the EncryptedAssertion.Decrypt method decrypts the SAML assertion and deserializes it to a SAMLAssertion object.
The SAMLAssertion.ToXml method doesn't guarantee the XML will be exactly the same as the original XML.
That's why you should call EncryptedAssertion.DecryptToXML instead so the original XML is preserved.
You can then verify the signature of this XML before deserializing it to a SAMLAssertion object.
[/quote]

Hi. used high-level API. ADFS is IdP. Our web App is SP.
From IdP received samlp:Response with section EncryptedAssertion
On our side we read response with next method.
SAMLServiceProvider.ReceiveSSO(Request, out isInResponseTo, out partnerIdP, out userName,
out attributes,
out targetUrl);

But userName is empty without errors in log.
If i'm not mistaken setting WantAssertionEncrypted in PartnerIdentityProviderConfiguration tels that assertion from SP will be encrypted.
Which setting responsible for "Assertion is encrypted" configuration?

Metadata from ADFS contains 2 kinds of cert: and
We set to setting PartnerCertificateFile in PartnerIdentityProviderConfiguration value from 'signing'. Can it be an issue?

How to set different cert for encryption and signing?


example of response

<?xml version="1.0" encoding="utf-16"?>
<samlp:Response ID=“_2615666b-a227-4796-accf-cf7dbdf8a709” Version=“2.0” IssueInstant=“2018-02-22T14:18:19.051Z” Destination=“<a href=“https://ourapp.com/Account/AssertionConsumerService/1"”>https://ourapp.com/Account/AssertionConsumerService/1” Consent=“urn:oasis:names:tc:SAML:2.0:consent:unspecified” InResponseTo=“_00efc197-1f3c-4bfc-8d0d-ca493f5e6b04” xmlns:samlp=“urn:oasis:names:tc:SAML:2.0:protocol”>
http://clientserver.com/adfs/services/trust
samlp:Status
<samlp:StatusCode Value=“urn:oasis:names:tc:SAML:2.0:status:Success” />
</samlp:Status>

<xenc:EncryptedData Type=“<a href=“http://www.w3.org/2001/04/xmlenc#Element””>http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc=“”>http://www.w3.org/2001/04/xmlenc#“>
<xenc:EncryptionMethod Algorithm=”<a href=“http://www.w3.org/2001/04/xmlenc#aes256-cbc”“>http://www.w3.org/2001/04/xmlenc#aes256-cbc” />
<KeyInfo xmlns=“”>http://www.w3.org/2000/09/xmldsig#“>
<e:EncryptedKey xmlns:e=”“>http://www.w3.org/2001/04/xmlenc#”>
<e:EncryptionMethod Algorithm=“”>http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod Algorithm=“<a href=“http://www.w3.org/2000/09/xmldsig#sha1"”>http://www.w3.org/2000/09/xmldsig#sha1” />
</e:EncryptionMethod>

<ds:X509Data xmlns:ds=“”>http://www.w3.org/2000/09/xmldsig#“>
ds:X509IssuerSerial
ds:X509IssuerNameOU=Web Dev, O=Company LLC, L=Chicago, S=Illinois, C=US</ds:X509IssuerName>
ds:X509SerialNumber17121932065278751738</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>

<e:CipherData>
<e:CipherValue>tZQiWpQeNw3PzkRcpP1iLfH4+odA3/wsR5BQgq5l1YPHC32VbHVgP38nNkfmm61DbB00S8ls0sNMbj+jfTCUr8oGXsGDiIAFVrKRc0bcDwrrJQuWeZ8Ov0xitr0Vtjhfgp/ehMW3ENWClkxx3vWhJsVoCrthqZVGXKz5X4ml+OTNJ8gSWAD/UZbFa++YRFl31rVofqmJQ2oyquIEwZdOYf+WdLPcXzaa7fnX8xCf+Bu6npZ1d9Ta0mRl+3lF3iVsMD6hd/3eDKyQXM4rarfEv3QQdmgymp44XlQyvL+EgrVuMVxoiVbxqAyTh8CuyQ+lZFYAvVJzuo9rIKUQnRvwsw==</e:CipherValue>
</e:CipherData>
</e:EncryptedKey>

xenc:CipherData
xenc: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</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>

</samlp:Response>



configuration

new PartnerIdentityProviderConfiguration()
{
Name = “<a href=“http://server.com/adfs/services/trust",">http://server.com/adfs/services/trust”,
WantSAMLResponseSigned = false,
WantAssertionSigned = false,
WantAssertionEncrypted = false,
DisableAudienceRestrictionCheck = true,
ForceAuthn = provider.ForceAuthn,
SignLogoutRequest = true,
SignLogoutResponse = true,
WantLogoutRequestSigned = false,
WantLogoutResponseSigned = false,
SignAuthnRequest = false,
PartnerCertificateFile = “idp.cert”,
UseEmbeddedCertificate = false,
LocalCertificateFile = “sp_cert.pfx”,
LocalCertificatePassword = ‘password’,
SingleSignOnServiceUrl =”<a href=“https://server.com/adfs/ls/””>https://server.com/adfs/ls/"
});

By default ADFS signs the SAML assertion rather than the SAML response.
You should set WantAssertionSigned = “true”.
The PartnerCertificateFile is the signing certificate from the IdP metadata.
The encryption certificate in the IdP metadata can be ignored as it isn’t used.
If you specify an encryption certificate in the relying party properties (ie under the Encryption tab), ADFS will encrypt the SAML assertion.
The encryption certificate is the SP’s certificate.
If you don’t want the SAML assertion encrypted then remove the encryption certificate from the relying party’s properties in ADFS.
If SAMLServiceProvider.ReceiveSSO returns without throwing an exception this means the decryption was successful.
If the userName parameter is null you’re missing a claim rule in ADFS to create a SAML NameID.
Please refer to section 10.4 of our Developer Guide PDF for information on using the ADFS claim rule wizard.
Typically you map the Active Directory User-Principal-Name to the SAML NameID.