在 X509Data 节点中使用 SKI 而不是证书的 SAML
SAML with a SKI instead of certificate in X509Data node
我已经实现了基于SAML协议的认证机制。项目使用SAML2 library。一切正常,直到服务器上发生更改。用于响应 节点的服务器:
<ds:KeyInfo><ds:X509Data><ds:X509Certificate>Here was certificate</ds:X509Certificate></ds:X509Data></ds:KeyInfo>
但已更改为:
<ds:X509SKI>Here is Subject Key Identifier</ds:X509SKI>
SAML2 库具有可应用于服务器响应的 CheckSignature 方法:
/// <summary>
/// Checks the signature.
/// </summary>
/// <returns>True of the signature is valid, else false.</returns>
public bool CheckSignature()
{
return XmlSignatureUtils.CheckSignature(Document);
}
它指向这里:
/// <summary>
/// Verifies the signature of the XmlDocument instance using the key enclosed with the signature.
/// </summary>
/// <param name="doc">The doc.</param>
/// <returns><code>true</code> if the document's signature can be verified. <code>false</code> if the signature could
/// not be verified.</returns>
/// <exception cref="InvalidOperationException">if the XmlDocument instance does not contain a signed XML document.</exception>
public static bool CheckSignature(XmlDocument doc)
{
CheckDocument(doc);
var signedXml = RetrieveSignature(doc);
if (signedXml.SignatureMethod.Contains("rsa-sha256"))
{
// SHA256 keys must be obtained from message manually
var trustedCertificates = GetCertificates(doc);
foreach (var cert in trustedCertificates)
{
if (signedXml.CheckSignature(cert.PublicKey.Key))
{
return true;
}
}
return false;
}
return signedXml.CheckSignature();
}
最后 GetCertificates 方法如下所示:
/// <summary>
/// Gets the certificates.
/// </summary>
/// <param name="doc">The document.</param>
/// <returns>List of <see cref="X509Certificate2"/>.</returns>
private static List<X509Certificate2> GetCertificates(XmlDocument doc)
{
var certificates = new List<X509Certificate2>();
var x509CertificateNodeList = doc.GetElementsByTagName("ds:X509Certificate");
if (x509CertificateNodeList.Count == 0)
{
x509CertificateNodeList = doc.GetElementsByTagName("X509Certificate");
}
foreach (XmlNode xn in x509CertificateNodeList)
{
try
{
var xc = new X509Certificate2(Convert.FromBase64String(xn.InnerText));
certificates.Add(xc);
}
catch
{
// Swallow the certificate parse error
}
}
return certificates;
}
如您所见,库仅检查证书而不检查主题密钥标识符。我相信我可以自己实现安装的证书和提供的元素之间的 SKI 比较,但我不确定这是否是合法的方式。
Here Thomas Pornin 写道:
The Subject Key Identifier does not play a role in validation, at
least not in the algorithm which makes up section 6 of RFC 5280. It is
meant to be an help for path building
他的声明表明我无法通过比较来自服务器响应的 SKI 和安装的证书来进行验证。
RFC 5280 同理,但我没有足够的时间仔细阅读,所以我正在寻找你的帮助。
比较已安装的 X509 证书的主题密钥标识符和 SAML 响应中的主题密钥标识符是否是验证响应的正确方法?
不,如前所述,SKI 仅用于绑定链中的证书(使用密钥匹配时)。它没有提供有关证书及其详细信息的足够信息。
但是,如果客户端预装了完整的证书,客户端可以使用 SKI 找到正确的证书并使用该证书进行验证。
我已经实现了基于SAML协议的认证机制。项目使用SAML2 library。一切正常,直到服务器上发生更改。用于响应
<ds:KeyInfo><ds:X509Data><ds:X509Certificate>Here was certificate</ds:X509Certificate></ds:X509Data></ds:KeyInfo>
但已更改为:
<ds:X509SKI>Here is Subject Key Identifier</ds:X509SKI>
SAML2 库具有可应用于服务器响应的 CheckSignature 方法:
/// <summary>
/// Checks the signature.
/// </summary>
/// <returns>True of the signature is valid, else false.</returns>
public bool CheckSignature()
{
return XmlSignatureUtils.CheckSignature(Document);
}
它指向这里:
/// <summary>
/// Verifies the signature of the XmlDocument instance using the key enclosed with the signature.
/// </summary>
/// <param name="doc">The doc.</param>
/// <returns><code>true</code> if the document's signature can be verified. <code>false</code> if the signature could
/// not be verified.</returns>
/// <exception cref="InvalidOperationException">if the XmlDocument instance does not contain a signed XML document.</exception>
public static bool CheckSignature(XmlDocument doc)
{
CheckDocument(doc);
var signedXml = RetrieveSignature(doc);
if (signedXml.SignatureMethod.Contains("rsa-sha256"))
{
// SHA256 keys must be obtained from message manually
var trustedCertificates = GetCertificates(doc);
foreach (var cert in trustedCertificates)
{
if (signedXml.CheckSignature(cert.PublicKey.Key))
{
return true;
}
}
return false;
}
return signedXml.CheckSignature();
}
最后 GetCertificates 方法如下所示:
/// <summary>
/// Gets the certificates.
/// </summary>
/// <param name="doc">The document.</param>
/// <returns>List of <see cref="X509Certificate2"/>.</returns>
private static List<X509Certificate2> GetCertificates(XmlDocument doc)
{
var certificates = new List<X509Certificate2>();
var x509CertificateNodeList = doc.GetElementsByTagName("ds:X509Certificate");
if (x509CertificateNodeList.Count == 0)
{
x509CertificateNodeList = doc.GetElementsByTagName("X509Certificate");
}
foreach (XmlNode xn in x509CertificateNodeList)
{
try
{
var xc = new X509Certificate2(Convert.FromBase64String(xn.InnerText));
certificates.Add(xc);
}
catch
{
// Swallow the certificate parse error
}
}
return certificates;
}
如您所见,库仅检查证书而不检查主题密钥标识符。我相信我可以自己实现安装的证书和提供的元素之间的 SKI 比较,但我不确定这是否是合法的方式。
Here Thomas Pornin 写道:
The Subject Key Identifier does not play a role in validation, at least not in the algorithm which makes up section 6 of RFC 5280. It is meant to be an help for path building
他的声明表明我无法通过比较来自服务器响应的 SKI 和安装的证书来进行验证。
RFC 5280 同理,但我没有足够的时间仔细阅读,所以我正在寻找你的帮助。
比较已安装的 X509 证书的主题密钥标识符和 SAML 响应中的主题密钥标识符是否是验证响应的正确方法?
不,如前所述,SKI 仅用于绑定链中的证书(使用密钥匹配时)。它没有提供有关证书及其详细信息的足够信息。
但是,如果客户端预装了完整的证书,客户端可以使用 SKI 找到正确的证书并使用该证书进行验证。