如何使用X509证书签名xml,将摘要值和签名添加到xml模板 [英] How to sign xml with X509 cert, add digest value and signature to xml template

查看:229
本文介绍了如何使用X509证书签名xml,将摘要值和签名添加到xml模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对C#相当陌生,尤其是对X509签名非常陌生.我有一个xml模板,其中必须添加使用的证书(完成)并签署时间戳记(TS-1),二进制安全令牌和主体(id-1). 此外,我需要用这3个元素的摘要值编写(例如替换占位符)并添加签名值.

I am quite new to C# and especially new to Signing with X509. I have an xml template in which I have to add the certificate used (done) and sign the timestamp (TS-1), the binary security token and the body (id-1). Furthermore, I need to write (e.g. replace placeholders) with the digest value of these 3 elements and add the signature value.

但是,我不太了解这个概念,例如这该怎么做.我读了几个网站,例如使用x509证书签名xml文档 但是我无法使代码适应我的问题.

However, I do not really understand the concept, e.g. how to do this. I read a couple of websites, e.g. signing a xml document with x509 certificate but I cannot adapt the code to my problem.

这是我尝试过的:

public static string SignXml(string template)
{

    XmlDocument document = new XmlDocument();
    document.LoadXml(template);

        // define elements that will be signed
        XmlNode securityToken = null;
        XmlNode validityPeriod = null;
        XmlNode body = null;
        XmlNode signedInfo = null;
        XmlNode signatureValue = null;
        XmlNodeList digestTags = null;



        XmlNamespaceManager namespaces = new XmlNamespaceManager(document.NameTable);
        namespaces.AddNamespace("ns", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
        namespaces.AddNamespace("nu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
        namespaces.AddNamespace("bo", "http://schemas.xmlsoap.org/soap/envelope/");
        namespaces.AddNamespace("si", "http://www.w3.org/2000/09/xmldsig#");
        namespaces.AddNamespace("sinfo", "soapenv xd xe");

        document.LoadXml(template);
        //XmlNode idNode = document.SelectSingleNode("/My_RootNode/ns:id", namespaces);

        securityToken = document.SelectSingleNode("descendant::ns:BinarySecurityToken", namespaces);
        validityPeriod = document.SelectSingleNode("descendant::nu:Timestamp", namespaces);
        body = document.SelectSingleNode("descendant::bo:Body", namespaces);
        signedInfo = document.SelectSingleNode("descendant::si:SignedInfo", namespaces);
        signatureValue = document.SelectSingleNode("descendant::si::sinfo:SignatureValue", namespaces);
        digestTags = document.SelectNodes("descendant::si:DigestValue", namespaces);

        // add the digests (to know where to write the digests)
        String nodeName = null;
        for (int counter = 0; counter < digestTags.Count; counter++)
        {
            nodeName = digestTags[counter].FirstChild.InnerText;
            if (WebserviceConstants.PLACEHOLDER_AUTHNREQUEST_DIGEST.Equals(nodeName))
            {

                generateDigest(body, digestTags[counter]);
            }
            else if (WebserviceConstants.PLACEHOLDER_CERTIFICATE_DIGEST.Equals(nodeName))
            {

                generateDigest(securityToken, digestTags[counter]);
            }
            else if (WebserviceConstants.PLACEHOLDER_TIMESTAMP_TAG_DIGEST.Equals(nodeName))
            {

                generateDigest(validityPeriod, digestTags[counter]);
            }
        }



        SignedXml signedXml = new SignedXml(document);



    X509Certificate2 cert = new X509Certificate2();
    cert = getbase();

    signedXml.SigningKey = cert.PrivateKey;

    // Create a reference to be signed.
    Reference reference = new Reference();
    reference.Uri = "#TS-1";

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

    //canonicalize
    XmlDsigC14NTransform c14t = new XmlDsigC14NTransform();
    reference.AddTransform(c14t);

    KeyInfo keyInfo = new KeyInfo();
    KeyInfoX509Data keyInfoData = new KeyInfoX509Data(cert);
    KeyInfoName kin = new KeyInfoName();
    kin.Value = "Public key of certificate";
    RSACryptoServiceProvider rsaprovider = (RSACryptoServiceProvider)cert.PublicKey.Key;
    RSAKeyValue rkv = new RSAKeyValue(rsaprovider);
    keyInfo.AddClause(kin);
    keyInfo.AddClause(rkv);
    keyInfo.AddClause(keyInfoData);
    signedXml.KeyInfo = keyInfo;

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

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

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

    document.DocumentElement.AppendChild(
    document.ImportNode(xmlDigitalSignature, true));
    document.DocumentElement.AppendChild(document.ImportNode(xmlDigitalSignature, true));

        return document.OuterXml;
    }
}

我在问自己:

  • 如何获取摘要值以及如何将其写入相应的xml节点
  • 如何计算签名值,因为它包含"所有3个引用的签名信息?

如您所见,我缺少一些一般背景和理解.如果您能帮助我的话,那真的很酷!

As you can see, I am missing some general background and understanding. Would be really cool if you could help me out!

谢谢

推荐答案

计算签名后,您不必手动创建签名的节点,您可以调用GetXml方法(您已经在做:signedXml. GetXml()),这将返回如下内容:

You don't have to manually create the nodes of the signature, after you compute the signature you call the GetXml method (you are already doing it: signedXml.GetXml()) and this will return something like this:

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
  <SignedInfo>
    <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
    <Reference URI="">
        <Transforms>
            <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
            <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>zRSPtja5EtX7hVbyJ11EjoYTRDk=</DigestValue>
    </Reference>
  </SignedInfo>
  <SignatureValue>Ua1/WP28WzfXaxUj....</SignatureValue>
  <KeyInfo>        
    <X509Data>
        <X509Certificate>MIIF3jCCBUegAwIBAgIEPQa1....</X509Certificate>
    </X509Data>
  </KeyInfo>
</Signature>

然后,您只需要替换xml模板上的整个签名节点即可.

Then you will only have to replace the whole signature node on your xml template.

-请记住,SignedXml将为您提供该结构,现在我将回答您的问题

您的第一个问题是关于参考文献摘要值的问题吗?如果是这样,当您调用ComputeSignature方法时,它将对其进行计算并将其添加到相应的xml节点中.

Your first question is it about the digest value of your references? If so, when you call the ComputeSignature method it will calculate it and add it to the corresponding xml node.

签名值是在您计算签名时计算的,您不必自己计算.

The signature value is calculated when you compute the signature you don't have to calculate it yourself.

调用ComputeSignature方法时,将执行SignedInfo节点并对其进行摘要.您的参考文献位于此节点内,因此您将获得包含所有参考文献信息的签名值

When you call the ComputeSignature method what it does is take the SignedInfo node and digest it. Your references are inside this node so you will get the signature value containing the info of all your references

这是ComputeSignature方法如何获取signedinfo节点的摘要值的方法,它使用此值来计算签名值:

This is how the ComputeSignature method gets the digest value of the signedinfo node,using this value it calculates the signature value:

XmlElement e = this.SignedInfo.GetXml(); //get the signedinfo nodes
document.AppendChild(document.ImportNode(e, true));
Transform canonicalizationMethodObject=this.SignedInfo.CanonicalizationMethodObject;
canonicalizationMethodObject.LoadInput(document);
canonicalizationMethodObject.GetDigestedOutput(hash); //digest the signedinfo node

这篇关于如何使用X509证书签名xml,将摘要值和签名添加到xml模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆