我正在通过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节
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
我试过这种方法,但是
<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>
这里有什么帮助吗。
发布于 2017-01-04 17:24:52
SAML身份验证消息是带有嵌入(信封) XMLDSig签名或压缩编码签名的XML文档。
包络XMLDSign签名
<samlp:LogoutRequest>
<...saml message...>
<ds:Signature>
<ds:SignedInfo />
<ds:SignatureValue />
<ds:KeyInfo />
</ds:Signature>
</samlp:LogoutRequest>
<ds:SignatureValue>
包含签名、<ds:SignedInfo>
签名数据和消息引用,<ds:KeyInfo>
通常包含带有签名者身份的X509Certificate或对该证书的引用。
压缩编码在中的应用
SAMLRequest=value&RelayState=value&SigAlg=value&Signature=value
,其中每个值都被url编码。
SAMLRequest=urlencode(base64(<samlp:LogoutRequest> <...saml message...> </samlp:LogoutRequest>))
并利用SigAlg
算法对查询字符串算法的级联进行签名。
Signature = urlencode( base64 ( SigAlg ("SAMLRequest=value&RelayState=value&SigAlg=value")))
SAML消息的数字签名
SAML消息使用颁发者(SP)的私钥进行数字签名(而不是加密),并且可以使用SP的公钥进行验证。SAML响应必须使用标识提供者( IdP )的私钥签名,SP可以使用IdP的公钥验证消息。
如果您充当IdP,并且要验证SP的SAML请求,则需要:
大多数编程语言都支持XMLDsig签名,但在您的示例中使用的是压缩的encoding,这是SAML绑定的一个特定特性,因此如果您的SAML库不支持它,则必须手动验证签名。根据规格说明的说法,这些或多或少都是要遵循的步骤。
//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);
发布于 2018-04-01 13:33:59
我试着用上面的答案,但没有成功。
然后,阅读文档和一些时间,我可以成功地用Java验证签名,快速的答案是:
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);
发布于 2018-11-22 11:06:51
SAML2.0签名根据绑定(POST或重定向)进行不同的验证。如果使用POST绑定,则在SAML XML中验证签名。如果使用重定向绑定,则使用签名验证查询字符串。
此LogoutRequest是通过重定向绑定发送的。下面的C#示例代码是从ITfoxtec.Identity.Saml2组件中复制的,并演示了如何验证签名。
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.");
}
https://stackoverflow.com/questions/41466641
复制相似问题