PowerShell验证SAML签名的XML

时间:2016-03-22 20:22:33

标签: .net xml powershell saml xml-dsig

我们最近遇到了一个问题,即IdP不信任我们的RP / SP的SAML 2.0注销请求签名。我们正在寻找其他方法来验证SAML请求签名,因为IdP和samltool.com都抱怨签名验证。下面是我们用来检查签名数据的示例答案,可以根据签名进行验证。

1 个答案:

答案 0 :(得分:2)

为SHA256添加必需的类型和定义

Add-Type -AssemblyName System.Security

# Add SHA-256 per http://stackoverflow.com/questions/30759119/verifying-xml-signature-in-powershell-with-pem-certificate
Add-Type @'
        public class RSAPKCS1SHA256SignatureDescription : System.Security.Cryptography.SignatureDescription
            {
                public RSAPKCS1SHA256SignatureDescription()
                {
                    base.KeyAlgorithm = "System.Security.Cryptography.RSACryptoServiceProvider";
                    base.DigestAlgorithm = "System.Security.Cryptography.SHA256Managed";
                    base.FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter";
                    base.DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter";
                }

                public override System.Security.Cryptography.AsymmetricSignatureDeformatter CreateDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key)
                {
                    System.Security.Cryptography.AsymmetricSignatureDeformatter asymmetricSignatureDeformatter = (System.Security.Cryptography.AsymmetricSignatureDeformatter)
                        System.Security.Cryptography.CryptoConfig.CreateFromName(base.DeformatterAlgorithm);
                    asymmetricSignatureDeformatter.SetKey(key);
                    asymmetricSignatureDeformatter.SetHashAlgorithm("SHA256");
                    return asymmetricSignatureDeformatter;
                }
            }
'@
$RSAPKCS1SHA256SignatureDescription = New-Object RSAPKCS1SHA256SignatureDescription
[System.Security.Cryptography.CryptoConfig]::AddAlgorithm($RSAPKCS1SHA256SignatureDescription.GetType(), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256")

在请求中未包含证书的情况下验证SAML 2.0 HTTP-POST请求:

$saml = "insert real saml request here"

$decoded = [System.Convert]::FromBase64String($saml)
$stream = [System.IO.MemoryStream]::new($decoded, 0, $decoded.length)

$xml = New-Object System.Xml.XmlDocument
$xml.PreserveWhitespace = $true
$xml.Load($stream)

$signed = New-Object System.Security.Cryptography.Xml.SignedXml -ArgumentList $xml
$signed.LoadXml($xml.DocumentElement.Assertion.Signature)

$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new("C:\Users\username\Desktop\idp.cer")

$keyinfo = [System.Security.Cryptography.Xml.KeyInfo]::new()
$clause = [System.Security.Cryptography.Xml.KeyInfoX509Data]::new($cert)
$keyinfo.AddClause($clause)

$signed.KeyInfo = $keyinfo

$signed.CheckSignature()

修改XML,因此无法在上面的示例中验证签名:

$xml.Response.Assertion.Subject.NameID.'#text' = 'asdasdasd'

$signed = New-Object System.Security.Cryptography.Xml.SignedXml -ArgumentList $xml
$signed.LoadXml($xml.DocumentElement.Assertion.Signature)

$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new("C:\Users\username\Desktop\idp.cer")

$keyinfo = [System.Security.Cryptography.Xml.KeyInfo]::new()
$clause = [System.Security.Cryptography.Xml.KeyInfoX509Data]::new($cert)
$keyinfo.AddClause($clause)

$signed.KeyInfo = $keyinfo

$signed.CheckSignature()

使用请求中包含的证书验证SAML 2.0 HTTP-POST请求:

$saml = "insert example saml request here"
$decoded = [System.Convert]::FromBase64String($saml)
$stream = [System.IO.MemoryStream]::new($decoded, 0, $decoded.length)

$xml = New-Object System.Xml.XmlDocument
$xml.PreserveWhitespace = $true
$xml.Load($stream)

$signed = New-Object System.Security.Cryptography.Xml.SignedXml -ArgumentList $xml
$signed.LoadXml($xml.DocumentElement.Signature)
$signed.CheckSignature()

修改XML,因此无法在上面的示例中验证签名:

$xml.LogoutRequest.NameID.'#text' = "dasdasd"

$signed = New-Object System.Security.Cryptography.Xml.SignedXml -ArgumentList $xml
$signed.LoadXml($xml.DocumentElement.Signature)


# Should return false since we modified the data
$signed.CheckSignature()

希望如果他们需要完成相同的任务,这可以节省其他人一些时间。如果您有任何意见或建议,请告诉我。

谢谢!