Как проверить сертификат X509Certificate2 на цепочку X509Certificate2Collection
Я пишу парсер ответов SAML 2.0 для обработки аутентификации POST в ASP.Net(в С# и MVC, но это менее актуально).
Итак, у меня есть файл .p7b
для проверки и который может быть прочитан в X509Certificate2Collection
и примерное утверждение - ответ SAML с базовым 64 кодом.
В идеале я хочу использовать встроенный WSSecurityTokenSerializer
, но который не работает, поэтому я ищу способ, который работает.
Вместо этого я читаю XML:
// 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
Эта работа работает, но все, что она делает, это проверка того, что подпись и открытый ключ X509Certificate2
в ответе SAML совпадают. Он никоим образом не проверяет, кто это, и мне нужно сделать это, прежде чем принимать аутентификацию SAML.
Кажется, есть два способа проверить сертификат, найденный в ответе SAML - я могу сделать certificate.Verify()
, или я могу выполнить проверку с помощью подписи signedXml.CheckSignature(certificate, false)
.
Однако оба возвращают false.
Я думаю, что это потому, что они проверяются в магазине или, возможно, в Интернете (я не уверен, как проверить). Я хочу проверить их вместо X509Certificate2Collection
, извлеченных из файла .p7b
, вместо этого - сертификаты, зарегистрированные на машине, должны быть проигнорированы и проверены только сертификаты .p7b
.
Кажется, что нет способа передать X509Certificate2Collection
методам Verify
или CheckSignature
.
Является ли это правильной проверкой на ответ SAML?
Можно ли использовать сертификаты .p7b
так, как я хочу?
Ответы
Ответ 1
Пробовали ли вы использовать настраиваемый X509Chain
для поиска ExtraStore
сертификатов во время процесса проверки. Что-то вроде следующего:
// Placeholder for the certificate to validate
var targetCertificate = new X509Certificate2();
// Placeholder for the extra collection of certificates to be used
var certificates = new X509Certificate2Collection();
var chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.ExtraStore.AddRange(certificates);
bool isValidCertificate = chain.Build(targetCertificate);
В этом примере проверка отзыва также отключена, но если у вас есть онлайн или оффлайн доступ к CRL, вы можете включить ее.
ExtraStore
должен включать промежуточные сертификаты, которые не находятся в хранилище машин/пользователей. Однако доверенный корневой сертификат, возможно, должен находиться в хранилище машины или пользователя в зависимости от того, который указан в X509Chain
, потому что в противном случае вы получите сбой UntrustedRoot
. Если даже корень не может быть доступен в магазине или в магазине пользователя, вы можете попытаться подойти к полученной цепочке и гарантировать, что единственная ошибка у вас есть из-за ненадежного корня и в то же время гарантируя, что корень цепочки - это то, что вы будет рассчитываться на основе X509Certificate2Collection
, которую вы имеете для проверки.
В качестве альтернативы вы можете создать свой собственный X509CertificateValidator
, чтобы проверить сертификат, принимая только с учетом предоставленного X509Certificate2Collection
.