通过GET方法对SAML身份验证请求的签名验证失败 [英] Signature Validation for a SAML Authn Request via GET method fails
问题描述
我尝试了很多解决方案,但徒劳无功.这就是我按照 https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf :
I tried a lot of solutions but in vain. This is what i am doing following guidlines set by https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf:
-
STEPS
STEPS
- 定义身份验证请求,然后对base64进行编码,最后对它进行Url编码.让我们称之为AR
- URL对RelayState进行编码.让我们称之为RS
- 网址对签名算法字符串进行编码.让我们称之为SA
- 因此现在要签名的字符串变为 SAMLRequest = AR& RelayState = RS& SigAlg = SA
- 现在,我使用私钥(服务提供商私钥)对在步骤4中获得的字符串进行签名.6,我得到的结果签名,以64为基数进行编码,然后通过URL对其进行编码.因此,我得到了base64和url编码的签名.让我们称之为SG
- 现在,我将在步骤6中获得的签名附加到步骤4中的查询字符串.所以最终的查询字符串变成 SAMLRequest = AR& RelayState = RS& SigAlg = SA& Signature = SG
一切正常,但签名验证失败!
All this works fine but the signature validation is failing !
Here's my code which is similar to the code found here https://github.com/Sustainsys/Saml2/blob/v0.21.2/Kentor.AuthServices/WebSSO/Saml2RedirectBinding.cs#L53-L68
protected void btnSendAuthRequest_Click(object sender, EventArgs e)
{
string authRequest = txtInput.Text;
//authRequest = authRequest.TrimEnd('\r', '\n');
authRequest = DeflateBase64UrlEncode(authRequest);
string spPrivateKey= txtKey.Text;
string relayState = HttpUtility.UrlEncode("https://example.com/pages/home.aspx");
string qs = "SAMLRequest=" + authRequest + "&RelayState=" + relayState;
qs = AddSignature(qs, spPrivateKey);
txtOutput.Text = qs;
}
public string AddSignature(string queryString, string PrivateKeyNoHeaders)
{
RSACryptoServiceProvider tmpRsa = RSAKeyTests.RSAKeyUtils.DecodePrivateKeyInfo(Convert.FromBase64String(PrivateKeyNoHeaders));
string signingAlgorithmUrl = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
queryString += "&SigAlg=" + HttpUtility.UrlEncode(signingAlgorithmUrl);
var signatureDescription = (SignatureDescription)CryptoConfig.CreateFromName(signingAlgorithmUrl);
HashAlgorithm hashAlg = signatureDescription.CreateDigest();
hashAlg.ComputeHash(Encoding.UTF8.GetBytes(queryString));
AsymmetricSignatureFormatter asymmetricSignatureFormatter =
signatureDescription.CreateFormatter(
((RSACryptoServiceProvider)tmpRsa));
//.GetSha256EnabledRSACryptoServiceProvider());
// Is the signature failing because of above ?
byte[] signatureValue = asymmetricSignatureFormatter.CreateSignature(hashAlg);
queryString += "&Signature=" + HttpUtility.UrlEncode(Convert.ToBase64String(signatureValue));
return queryString;
}
private string DeflateBase64UrlEncode(string input)
{
var inputs = string.Format(input, Guid.NewGuid());
var bytes = Encoding.UTF8.GetBytes(inputs);
using (var output = new MemoryStream())
{
using (var zip = new DeflateStream(output, CompressionMode.Compress))
{
zip.Write(bytes, 0, bytes.Length);
}
var base64 = Convert.ToBase64String(output.ToArray());
return HttpUtility.UrlEncode(base64);
}
}
推荐答案
CryptoConfig.createFromName(...)
CryptoConfig.createFromName(...)
doesn't know about http://www.w3.org/2000/09/xmldsig#rsa-sha1
as the digest+signing algorithm. If CryptoConfig.createFromName()
is not returning null, whatever algorithm is registered for http://www.w3.org/2000/09/xmldsig#rsa-sha1
might not be RSA-SHA1. Here's an explicit implementation of SignatureDescription
with RSA and SHA1:
public class RSASHA1SignatureDescription : SignatureDescription {
public RSASHA1SignatureDescription() {
KeyAlgorithm = "System.Security.Cryptography.RSA";
DigestAlgorithm = "System.Security.Cryptography.SHA1Cng";
FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter";
DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter";
_hashAlgorithm = "SHA1";
}
public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) {
AsymmetricSignatureDeformatter item = (AsymmetricSignatureDeformatter) CryptoConfig.CreateFromName(DeformatterAlgorithm);
item.setKey(key);
item.SetHashAlgorithm(_hashAlgorithm);
return item;
}
public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key) {
AsymmetricSignatureFormatter item = (AsymmetricSignatureFormatter) CryptoConfig.CreateFromName(FormatterAlgorithm);
item.setKey(key);
item.SetHashAlgorithm(_hashAlgorithm);
return item;
}
private string _hashAlgorithm;
}
另一种可能性是,但是您正在验证签名,而不希望rsa-sha1(许多身份提供程序通过配置禁止rsa-sha1)或验证不正确.尝试向真实的IdP(例如Okta或Salesforce)进行注册,并在那里进行验证.
The other possibility is that however you're validating the signature doesn't want rsa-sha1 (many identity providers prohibit rsa-sha1 via configuration) or the validation is incorrect. Try registering with a real IdP such as Okta or Salesforce and validate there.
这篇关于通过GET方法对SAML身份验证请求的签名验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!