How can IdP verify the signed AuthnRequest without using HTTPRedirectBinding.VerifyRequestSignature ?

I am a .NET developer and I want to know how to verify the request signature without using HTTPRedirectBinding.VerifyRequestSignature.

Remarks:
The redirect URL to IdP just contain the deflated, base64 encoded, url encoded SAML request in xml, signature with url encoded and the SigAlg which is the signature algorithm, IdP also knows the x.509 certificate of SP.

I recommend using our SAML high-level API if at all possible. This is easier to use than the low-level API.
Are you asking how to verify the signature when the SAML message hasn’t been deflated and encoded?
Could you provide some more details around what you’d like to achieve?
Thanks.

umm, I use the sample code from MSDN, but seems it generates different signature from this API HTTPRedirectBinding.CreateRequestRedirectURL

https://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signature(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2

And I modify a little bit to just

public static XmlElement SignXmlFile(XmlDocument xdoc, string SignedFileName, RSA Key, X509Certificate2 cert)
{
// Check the arguments.
if (xdoc == null)
throw new ArgumentNullException(“FileName”);
if (SignedFileName == null)
throw new ArgumentNullException(“SignedFileName”);
if (Key == null)
throw new ArgumentNullException(“Key”);

// Format the document to ignore white spaces.
xdoc.PreserveWhitespace = false;

// Create a SignedXml object.
SignedXml signedXml = new SignedXml(xdoc);

// Add the key to the SignedXml document.
signedXml.SigningKey = Key;

// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = “”;

// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);

// Add the Reference object to the Signature object.
signedXml.AddReference(reference);

// Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
//KeyInfo keyInfo = new KeyInfo();
//keyInfo.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.WholeChain));

// Get the signature object from the SignedXml object.
Signature XMLSignature = signedXml.Signature;
// Add the KeyInfo object to the Reference object.
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new RSAKeyValue((RSA)cert.PublicKey.Key));
// Add the KeyInfo object to the Reference object.
XMLSignature.KeyInfo = keyInfo;;

// Compute the signature.
signedXml.ComputeSignature();

// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();

// Append the element to the XML document.
xdoc.DocumentElement.AppendChild(xdoc.ImportNode(xmlDigitalSignature, true));

if (xdoc.FirstChild is XmlDeclaration)
{
xdoc.RemoveChild(xdoc.FirstChild);
}

// Save the signed XML document to a file specified
// using the passed string.
XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));
xdoc.WriteTo(xmltw);
xmltw.Close();
return xmlDigitalSignature;
}public static XmlElement SignXmlFile(XmlDocument xdoc, string SignedFileName, RSA Key, X509Certificate2 cert)
{
// Check the arguments.
if (xdoc == null)
throw new ArgumentNullException(“FileName”);
if (SignedFileName == null)
throw new ArgumentNullException(“SignedFileName”);
if (Key == null)
throw new ArgumentNullException(“Key”);
// Format the document to ignore white spaces.
xdoc.PreserveWhitespace = false;
// Create a SignedXml object.
SignedXml signedXml = new SignedXml(xdoc);
// Add the key to the SignedXml document.
signedXml.SigningKey = Key;
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = “”;
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Add the Reference object to the Signature object.
signedXml.AddReference(reference);
// Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
//KeyInfo keyInfo = new KeyInfo();
//keyInfo.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.WholeChain));
// Get the signature object from the SignedXml object.
Signature XMLSignature = signedXml.Signature;
// Add the KeyInfo object to the Reference object.
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new RSAKeyValue((RSA)cert.PublicKey.Key));
// Add the KeyInfo object to the Reference object.
XMLSignature.KeyInfo = keyInfo;;
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
xdoc.DocumentElement.AppendChild(xdoc.ImportNode(xmlDigitalSignature, true));
if (xdoc.FirstChild is XmlDeclaration)
{
xdoc.RemoveChild(xdoc.FirstChild);
}
// Save the signed XML document to a file specified
// using the passed string.
XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));
xdoc.WriteTo(xmltw);
xmltw.Close();
return xmlDigitalSignature;
}

And I extract the signature value by the following code,


XmlNodeList lst = xmlDigitalSignature.GetElementsByTagName(“SignatureValue”);
if (lst.Count == 1)
{
string signature = lst[0].InnerXml; // Extract the signature value
}


In HTTP-Redirect Binding, we don’t need to embed the signature in the request xml before deflation and encoding. In the following example, just deflate and encode the raw xml.

http://localhost/SAML2IdentityProvider/SAML/SSOService.aspx?SAMLRequest=7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ%2Fff%2Fz9cZmQBbPbOStrJniGAqsgfP358Hz8iHjfZolw9Ol638%2BWr%2FBet86ZNz55%2B9tHv%2F%2Bnewd7B%2BUG2fXB%2BP9%2Fef3D%2BYHtyPt3ZPt97uLP%2F6Wzn04OHex%2BlP5nXTVEtP%2Ftob7zzUXrWNOv8bNm02bKlj3Z2DrZ39rf37r%2FZ2Xu0%2B%2Bmj3d2f%2Bih9Sj0Uy6zlt%2BZtu3p0925ZTbNyXjXt3dfHXzzfO5vly7Zor1%2FW1WUxy2v%2B9O7r11%2B%2BzuvLYpqPs2b17qP0WVVPc0b8s4%2FOs7LJgcDLrGmKy9x%2BQjDaalqVT4rlrFhefPbRul4%2BqrKmaB4ts0XePGqnjwD%2BEQ3g0UQaNY%2B%2B%2FebNy%2B2XX75%2B81F63DR5DWxPqmWzXuS1InG2nOXvPvtoZ7jFV6%2BeD41QW4QDHILDw%2F09FLfPCP%2Ff%2FV7GI6CfPAb62U7pH0ChHzQS%2BteMhX71R9O2dTFZt7n0QQ16w3m3KJfNI2aLzdRaKWk%2FOmImesSzX3vvb349M8P96Oh2RHp81%2BvmSBn3BcE9e%2FqyKovpdXpcltXVSZ1nLTFAW69p%2Fu8eyWshix%2F9Pw%3D%3D&RelayState=e51b87b4-3a09-4997-8dd5-4abb6cb70cb0&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=gO%2BnC83zB0mGO0td8ccPRqiVlbykfTI2zoz%2F88V8ZKG1Gtrm%2Fva%2B%2BXhhw%2BllYgvyyxtt1vkWxLsGPNDW9Zj4ZXhkan37AntHu6cWXqEXhNrWTRcTVzkRft9%2FCPG5UaVVV9SFkf0%2FfnhVCyL1uARwtJYtvf%2F5WaqFVnrfGpjqGQU%3D

When I compare the signature value with using HTTPRedirectBinding.CreateRequestRedirectURL, they are different, anything I miss or do wrongly ?

I modify the SignXmlFile to return the element and extract the signature value and url-encoded it, in order to put it in url, &Signature={url-encoded signature value}

We support the HTTP-Redirect binding including signature generation and verification. This is handled automatically for you if you use the high-level SAML API.
If you use the low-level API then you’ll find methods for HTTP-Redirect binding signature generation and verification.
You don’t need to implement this yourself.
The MSDN code you reference uses the .NET framework’s SignedXml class for XML signature generation and verification.
This is very different from the signatures used with the HTTP-Redirect binding.
A SAML message sent using the HTTP-Redirect binding should not include an XML signature as the resultant URL will be too long for some or most browsers.
That’s why HTTP-Redirect binding signatures are generated using a different algorithm.
If you wish to know the precise details of these signatures I suggest taking a look at the SAML Bindings specification.
However, as I said, you don’t need to worry about these as we have implemented them. You simply need to call the appropriate API.

Yes, I know the request xml should not include part.
So I try to apply MSDN reference code and extract out the value in , then do url-encoded and put it in the redirect URL.
Do you mean the signature value in redirect url (e.g. &Signature={value} ) isn’t same as the xml signature ? So what is the difference between them ?

The two signature algorithms are completely different. For the specific details of the HTTP-binding signature algorithm I suggest you take a look at the SAML v2.0 Bindings specification.
Are you trying to implement this yourself?
If you use our component then HTTP-binding signature generation and verification is included and you don’t have to worry about the details.

I’ve read the specification, yes, the signature here is not equal to xml signature, the signature is computed as follow, suppose no relaystate is used

“SAMLRequest=value1&SigAlg=value2”

value1 is deflated, base64 encoded and url encoded
value2 is url encoded

Then I use the following code but still the result is still not equal, I am not worry about the library but I just want to know more about the mechanism.

X509Certificate2 cert = new X509Certificate2(keyfile, pass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
RSACryptoServiceProvider rsaKey = (RSACryptoServiceProvider)cert.PrivateKey;
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)signingKey;
byte[] signature = rsa.SignData(Encoding.UTF8.GetBytes(“SAMLRequest=value1&SigAlg=value2”), new SHA1CryptoServiceProvider());
string signature = HttpUtility.UrlEncode(Convert.ToBase64String(signature));

Are you saying you don’t want to use our library but need assistance implementing this yourself? If so, I’m afraid we don’t offer this type of assistance.

Thanks for help. Now I know more about the implementation inside.