首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何验证HTTP重定向绑定的SAML签名

如何验证HTTP重定向绑定的SAML签名
EN

Stack Overflow用户
提问于 2017-01-04 14:47:57
回答 6查看 17.2K关注 0票数 9

我正在通过HTTP接收SAML请求--重定向绑定SAML请求的内容,如下所示

{"SigAlg"=>"http://www.w3.org/2000/09/xmldsig#rsa-sha1",

它还具有一个签名值。

WkDaGzC6vPTlzh+EnFA5/8IMmV7LviyRh2DA5EHF0K0nl+xzBlKfNCYRnunpwoEvGhereGdI5xBpv+mc9IguiCaLZSZjDh6lIDdpvctCnmSNzORqzWQwQGeZ9vjgtCLjUn35VZLNs3WgEqbi2cL+ObrUDS2gV1XvBA3Q3RRhoDmi+XE89Ztnd1cNpR3XdA+EL2ENbMI2XAD9qSgMufUJY/3GBBpT7Vg1ODtPxBudq+sXrgPh/+WtUUitLkkfC8tdRTCS1EZPv+h27I5g/VNza23Xl8w2HdAuYP0F2FjREo8VV2aUtaOUd/jAF9+bfkGV93y1PzFttLxdBbFoxp6qBg==

但我不明白如何证明这个签名是正确的。

关于SAML绑定https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf的3.4.4.1节

代码语言:javascript
运行
复制
To construct the signature, a string consisting of the concatenation of the RelayState (if present),
SigAlg, and SAMLRequest (or SAMLResponse) query string parameters (each one URLencoded)
is constructed in one of the following ways (ordered as below):
SAMLRequest=value&RelayState=value&SigAlg=value
SAMLResponse=value&RelayState=value&SigAlg=value

我试过这种方法,但是

  • 我使用私钥生成的签名与我从SP收到的签名不匹配。(张贴在上面)
  • 而且,我无法使用私钥解密签名消息(假设签名是使用与其联合的公共创建的)。

代码语言:javascript
运行
复制
<samlp:LogoutRequest ID="_36167d94-d868-4c04-aee3-8bbd4ed91317" Version="2.0" IssueInstant="2017-01-05T16:21:55.704Z" Destination="https://werain.me/" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"><Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">urn:federation:MicrosoftOnline</Issuer><NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">4948f6ce-4e3b-4538-b284-1461f9379b48</NameID><samlp:SessionIndex>_eafbb730-b590-0134-a918-00d202739c81</samlp:SessionIndex></samlp:LogoutRequest>

这里有什么帮助吗。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2017-01-04 17:24:52

SAML身份验证消息是带有嵌入(信封) XMLDSig签名或压缩编码签名的XML文档。

包络XMLDSign签名

代码语言:javascript
运行
复制
<samlp:LogoutRequest>
    <...saml message...> 
    <ds:Signature>
         <ds:SignedInfo />
         <ds:SignatureValue /> 
         <ds:KeyInfo /> 
    </ds:Signature> 
</samlp:LogoutRequest>

<ds:SignatureValue>包含签名、<ds:SignedInfo>签名数据和消息引用,<ds:KeyInfo>通常包含带有签名者身份的X509Certificate或对该证书的引用。

压缩编码在中的应用

代码语言:javascript
运行
复制
SAMLRequest=value&RelayState=value&SigAlg=value&Signature=value

,其中每个值都被url编码。

代码语言:javascript
运行
复制
SAMLRequest=urlencode(base64(<samlp:LogoutRequest> <...saml message...> </samlp:LogoutRequest>))

并利用SigAlg算法对查询字符串算法的级联进行签名。

代码语言:javascript
运行
复制
Signature = urlencode( base64 ( SigAlg ("SAMLRequest=value&RelayState=value&SigAlg=value")))

SAML消息的数字签名

SAML消息使用颁发者(SP)的私钥进行数字签名(而不是加密),并且可以使用SP的公钥进行验证。SAML响应必须使用标识提供者( IdP )的私钥签名,SP可以使用IdP的公钥验证消息。

如果您充当IdP,并且要验证SP的SAML请求,则需要:

  • 验证数字签名:使用SP的公钥验证签名与签名消息匹配,以确保签名者的身份和消息没有被更改
  • 授权请求:验证签名者的身份是否可以执行请求的操作。通常,您必须将证书的序列号或主题与预先存在的列表匹配,或者验证证书是由受信任的证书颁发机构颁发的。
  • 生成SAML响应:使用SAML数据生成一条XML消息,并使用您的私钥签名将其发送给SP

大多数编程语言都支持XMLDsig签名,但在您的示例中使用的是压缩的encoding,这是SAML绑定的一个特定特性,因此如果您的SAML库不支持它,则必须手动验证签名。根据规格说明的说法,这些或多或少都是要遵循的步骤。

代码语言:javascript
运行
复制
 //get params from query string 
String samlrequest = getQueryParam("SAMLRequest");
String relaystate = getQueryParam("RelayState");
String sigalg = getQueryParam("SigAlg");
String signature = getQueryParam("Signature");


//The signature
byte signature[] = URLDecoder.decode(Base64.getDecoder().decode(signature ), "UTF-8");

//The signed data. build the following string checking if RelayState is null
//SAMLRequest=samlrequest&RelayState=relaystate&SigAlg=sigalg
byte signedData[] = concat(samlrequest,relaystate,sigalg);

//The signature algorithm could be "SHA1WithRSA" or "SHA1withDSA" depending on sigalg is http://www.w3.org/2000/09/xmldsig#rsa-sha1 or http://www.w3.org/2000/09/xmldsig#dsa-sha1 
String signatureAlgorithm = extractSignatureAlgorithm(sigalg);

//get the public key of the SP. It must be registered before this process
PublicKey publicKey = ...

//Verify the signature
Signature sig = Signature.getInstance(signatureAlgorithm);
sig.initVerify(publicKey);
sig.update(signedData); 
boolean verifies = sig.verify(signature);  
票数 14
EN

Stack Overflow用户

发布于 2018-04-01 13:33:59

我试着用上面的答案,但没有成功。

然后,阅读文档和一些时间,我可以成功地用Java验证签名,快速的答案是:

代码语言:javascript
运行
复制
final String samlRequest = request.getParameter("SAMLRequest");
final String relayState = request.getParameter("RelayState");
final String sigAlg = request.getParameter("SigAlg");
final String signature = request.getParameter("Signature");

FileInputStream fis = new FileInputStream(new File("path-to-service-provider-x509-certificate"));

CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(fis);

// ps: java.net.URLEncoder;
String query = "SAMLRequest=" + URLEncoder.encode(samlRequest, "UTF-8");
query += "&RelayState=" +URLEncoder.encode(relayState, "UTF-8");
query += "&SigAlg=" + URLEncoder.encode(sigAlg, "UTF-8");

// ps: org.opensaml.xml.util.Base64
byte[] signatureBytes = Base64.decode(signature);

org.apache.xml.security.Init.init();
Signature sig = Signature.getInstance("SHA1withRSA"); // or other alg (i, e: SHA256WithRSA or others)
sig.initVerify(cert.getPublicKey());
sig.update(query.getBytes());
Boolean valid = sig.verify(signatureBytes);
票数 2
EN

Stack Overflow用户

发布于 2018-11-22 11:06:51

SAML2.0签名根据绑定(POST或重定向)进行不同的验证。如果使用POST绑定,则在SAML XML中验证签名。如果使用重定向绑定,则使用签名验证查询字符串。

此LogoutRequest是通过重定向绑定发送的。下面的C#示例代码是从ITfoxtec.Identity.Saml2组件中复制的,并演示了如何验证签名。

代码语言:javascript
运行
复制
var queryString = request.QueryString;
var signatureValue = Convert.FromBase64String(request.Query["Signature"]);

var messageName = "SAMLRequest";
var signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
var signatureValidationCertificate = new X509Certificate2("path-to-service-provider-x509-certificate");

var saml2Sign = new Saml2SignedText(signatureValidationCertificate, signatureAlgorithm);
if (saml2Sign.CheckSignature(Encoding.UTF8.GetBytes(new RawSaml2QueryString(queryString, messageName).SignedQueryString), signatureValue))
{
    // Signature is valid.
}
else
{
    throw new InvalidSignatureException("Signature is invalid.");
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41466641

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档