Estoy escribiendo un analizador de respuestas SAML 2.0 para manejar la autenticación POST en ASP.Net (en C# y MVC, pero eso es menos relevante).Cómo verificar un X509Certificate2 contra una cadena X509Certificate2Collection
Así que tengo un archivo .p7b
para validar con y que se puede leer en un X509Certificate2Collection
y una afirmación de muestra - una respuesta SAML codificada en base 64.
Idealmente quiero usar el construido en WSSecurityTokenSerializer
, pero that fails, entonces estoy buscando una manera que funcione.
estoy leyendo el código XML directamente en su lugar:
// get the base 64 encoded SAML
string samlAssertionRaw = GetFromHttpRequest();
// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml(samlAssertionRaw);
// use a namespace manager to avoid the worst of xpaths
var ns = new XmlNamespaceManager(assertion.NameTable);
ns.AddNamespace("samlp", @"urn:oasis:names:tc:SAML:2.0:protocol");
ns.AddNamespace("saml", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
// get the signature XML node
var signNode = assertion.SelectSingleNode(
"/samlp:Response/saml:Assertion/ds:Signature", ns);
// load the XML signature
var signedXml = new SignedXml(assertion.DocumentElement);
signedXml.LoadXml(signNode as XmlElement);
// get the certificate, basically:
// signedXml.KeyInfo.OfType<KeyInfoX509Data>().First().
// Certificates.OfType<X509Certificate2>().First()
// but with added checks
var certificate = GetFirstX509Certificate(signedXml);
// check the key and signature match
if (!signedXml.CheckSignature(certificate, true))
{
throw new SecurityException("Signature check failed.");
}
// go on and read the SAML attributes from the XML doc
que funciona mucho, pero todo lo que está haciendo es comprobar que la firma y la clave pública X509Certificate2
en el partido de la respuesta SAML. De ninguna manera verifica de quién es, y debo hacerlo antes de aceptar la autenticación SAML.
Parece haber dos formas de verificar el certificado encontrado en la respuesta de SAML: puedo hacer certificate.Verify()
o puedo hacer el control con la firma signedXml.CheckSignature(certificate, false)
.
Sin embargo ambos devuelven falso.
Creo que esto se debe a que están siendo revisados en la tienda de máquinas o posiblemente en línea (no estoy seguro de cómo verificar). Quiero verificarlos contra el X509Certificate2Collection
recuperado del archivo .p7b
en su lugar - los certificados registrados en la máquina deben ignorarse y solo deben verificarse los certificados .p7b
.
No parece haber ninguna forma de pasar el X509Certificate2Collection
a los métodos Verify
o CheckSignature
.
¿Es esta la comprobación correcta de la respuesta de SAML?
¿Hay alguna forma de utilizar los certificados .p7b
de la manera que quiero?
¿Qué hace GetFirstX509Certificate? – theycallmemorty
Hice una pregunta similar aquí: http://security.stackexchange.com/questions/3905/verify-saml-response-is-from-a-trusted-source pero finalmente terminé en su publicación porque estoy teniendo el mismo problema con CheckSignature – theycallmemorty
@theycallmemorty - Intento explicar en los comentarios, pero hace 'signedXml.KeyInfo [0] .Certificates [0] como X509Certificate2', pero con controles y conversiones. – Keith