ComputeSignature和手动生成的哈希是不同的

时间:2018-06-14 10:57:30

标签: c# xml cryptography digital-signature sha256

我正在使用数字签名创建请求xml。以下是我的代码。

CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");

        var exportedKeyMaterial = cert.PrivateKey.ToXmlString( /* includePrivateParameters = */ true);
        var key = new RSACryptoServiceProvider(new CspParameters(24 /* PROV_RSA_AES */));
        key.PersistKeyInCsp = false;
        key.FromXmlString(exportedKeyMaterial);

        string tokenId = string.Format("X509-{0}", Guid.NewGuid());
        string signatureId = string.Format("SIG-{0}", Guid.NewGuid());
        string tokenRefId = string.Format("STR-{0}", Guid.NewGuid());
        string kiId = string.Format("KI-{0}", Guid.NewGuid());
        string bodyId = string.Format("id-{0}", Guid.NewGuid());

        XmlNamespaceManager ns = new XmlNamespaceManager(xmlDoc.NameTable);
        ns.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
        ns.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
        ns.AddNamespace("wsa", "http://schemas.xmlsoap.org/ws/2004/08/addressing");
        ns.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

        XmlElement body = xmlDoc.DocumentElement.SelectSingleNode(@"//soapenv:Body", ns) as XmlElement;
        if (body == null)
            throw new ApplicationException("No body tag found");

        body.SetAttribute("id", bodyId);

        SignedXml signedXml = new SignedXml(body);
        signedXml.Signature.Id = signatureId;
        signedXml.SigningKey = key;
        signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

        KeyInfo keyInfo = new KeyInfo();
        keyInfo.Id = kiId;

        SecurityTokenReference tokenRef = new SecurityTokenReference();
        tokenRef.ValueType = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";
        tokenRef.RelativeReference = tokenId;
        tokenRef.Id = tokenRefId;

        // Add Security Token reference
        keyInfo.AddClause(tokenRef);
        signedXml.KeyInfo = keyInfo;

        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

        XmlDsigExcC14NTransform canMethod = (XmlDsigExcC14NTransform)signedXml.SignedInfo.CanonicalizationMethodObject;
        canMethod.InclusiveNamespacesPrefixList = "soap";

        Reference reference = new Reference();
        reference.Uri = string.Format("#{0}", bodyId);
        reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";

        reference.AddTransform(new Microsoft.Web.Services3.Security.Xml.XmlDsigExcC14NTransform());
        signedXml.AddReference(reference);

        signedXml.ComputeSignature();

XmlElement signedElement = signedXml.GetXml();

 string hash = CalculateDigestOfBody(body);

public string CalculateDigestOfBody(XmlElement xmlDoc)
        {
            SHA256 algo = new SHA256CryptoServiceProvider();
            byte[] byteHash = algo.ComputeHash(Encoding.UTF8.GetBytes(xmlDoc.OuterXml));
            string hashString = Convert.ToBase64String(byteHash);

            return hashString;
        }

这会生成以下soap标题

<Signature Id="SIG-44779d9b-7d39-4c27-877b-a6de1d9365fc" xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
    <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
        <InclusiveNamespaces PrefixList="soap" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" />
    </CanonicalizationMethod>
    <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
    <Reference URI="#id-98b3d734-ee46-49bb-aee8-c151d41defe5">
        <Transforms>
            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <DigestValue>..</DigestValue>
    </Reference>
</SignedInfo>
<SignatureValue>..</SignatureValue>

当我比较ComputeSignature的摘要值和手动计算的散列/摘要时,它们不相等。

根据我的理解,他们应该是平等的,因为两者都是按身体计算的。

我在这里缺少什么。

1 个答案:

答案 0 :(得分:0)

对于那些对答案感兴趣的人:

调用ComputeSignature方法后,切勿更改正文或签名信息元素。另外,尽量不要在soap的子代中更改任何内容:手动添加标题。

以下是我做错的代码。评论完美无缺。

signedElement.Prefix = "ds";
signedElement.FirstChild.Prefix = "ds";
signedElement.FirstChild.FirstChild.Prefix = "ds";

我在ComputeSignature下面添加了这些行。之后我试图手动计算摘要。因此,两个摘要都无法匹配。

消化输入的任何变化都会改变摘要。