在xml签名文件中拆分base64签名值

时间:2014-11-26 16:13:08

标签: c# xml base64 xml-signature xml-dsig

我正在尝试签署一些XML文件,我设法做得很好,但我找不到检查签名的方法,接收器服务接受它(xml),但它在签名上发现错误

我已检查过Web服务的文档,他们说,签名值每行最多可包含76个字符,每次加载或编辑xml文件时都必须保留.whitespace。

这是我输出的xml文件(为了安全起见我编辑了一些值) puu.sh/d6lwC/25eb2a0d02.png(注意两个签名值是如何是一条没有间距的长行。

我认为这应该是这样的: puu.sh/d6lCV/48b0cc0cd7.png

根据服务文档,这是xml文件: puu.sh/d6ltJ/bd8e25a4b4.png

这是我的签名代码

     SignedXml signedXml = new SignedXml(xmldocument);
        signedXml.SigningKey = certificado.PrivateKey;
        Signature XMLSignature = signedXml.Signature;
        Reference reference = new Reference();
        reference.Uri = referenciaUri;
        XMLSignature.SignedInfo.AddReference(reference);
        KeyInfo keyInfo = new KeyInfo();
        keyInfo.AddClause(new RSAKeyValue((RSA)certificado.PrivateKey));
        keyInfo.AddClause(new KeyInfoX509Data(certificado));
        XMLSignature.KeyInfo = keyInfo;
        signedXml.ComputeSignature();
        XmlElement xmlDigitalSignature = signedXml.GetXml();
        xmldocument.DocumentElement.SelectSingleNode(para).AppendChild(xmldocument.ImportNode(xmlDigitalSignature, true));    

我的问题是:

如何在不损坏xml本身的其他核心值的情况下轻松分割签名值的行,以便通过该更改使Web服务能够正确读取和验证xml文件的签名?

先谢谢,原谅我糟糕的英语。

编辑:我发现了这个问题 https://stackoverflow.com/questions/24916486/how-to-do-enveloped-rsa-sha1-digital-signature-of-xml-data-using-php

他以某种方式来解决我的问题,通过php用块分割base64值和76长度用这段代码

// Base64 encoding
$SignatureValue = rtrim(chunk_split(base64_encode($SignatureValue_bruto), 76));    

我怎样才能用c#实现这个目标?

2 个答案:

答案 0 :(得分:1)

有点旧,但我觉得让dotNet为你做这样的工作要简单得多:

var bytes = Convert.FromBase64String(str);
return Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);

答案 1 :(得分:0)

好的!你可以试试这个:-) 添加以下代码

    public static string base64_encode(string str)
    {
        return System.Convert.ToBase64String(Encoding.UTF8.GetBytes(str));
    }

    public static string chunk_split(string str, int len)
    {
        var strings = new List<string>();
        var div = str.Length % len;
        var remainder = len - div * len;

        if (div == 1)
        {
            return string.Join("", str.Take(len));
        }

        for (var j = 0; j < div; j++)
        {
            var s = string.Join("", str.Skip(j * len).Take(len));
            if (!string.IsNullOrEmpty(s))
                strings.Add(s);
        }

        if (remainder > 0)
        {
            var s = string.Join("", str.Skip(div * len).Take(remainder));
            if (!string.IsNullOrEmpty(s))
                strings.Add(s);
        }

        return string.Join(Environment.NewLine, strings.ToArray());
    }

    public static string rtrim(string input)
    {
        while (input.EndsWith(Environment.NewLine))
            input = input.Remove(input.Length - Environment.NewLine.Length);

        return input.TrimEnd(' ');
    }

然后只需使用

chunk_split(base64_encode(strstr), 76);

编辑您可以使用此功能修复文档的签名。我不知道我还能帮助你:P

    public static void UpdateXmlSignature(string filename)
    {
        // Load the target xml, the xml file with the certificate
        var doc = XDocument.Load(filename);
        var cert = doc.XPathSelectElement("//X509Data/X509Certificate");
        if (cert != null)
        {
            var updatedValue = rtrim(chunk_split(base64_encode(cert.Value), 76));
            cert.Value = updatedValue;
        }

        // Overwrite the old file
        doc.Save(filename);
    }

这将要求所有代码都到位。