0

I am trying to sign some XML files, which i managed to do fine, yet i can't find a way to check the signature, the receiver service accepts it fine (the xml), but it finds error on the signature.

I have checked the documentation of the web service and they said, signature values can have UP to 76 characters per line, and i must preserve.whitespace everytime i load or edit the xml file.

This is my xml file once outputted (i edited some values for security) puu.sh/d6lwC/25eb2a0d02.png (notice how the two signature values are a long line without spacing.

This is how i think it should look: puu.sh/d6lCV/48b0cc0cd7.png

This is the xml file as should be as per service documentation: puu.sh/d6ltJ/bd8e25a4b4.png

Here's my signing code

     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));    

My question is:

How can i split the lines of the signature value easily without damaging other core values of the xml itself, so with that change making the webservice being able to read and validate correctly the signature of the xml file?

Thanks in advance, and forgive my crappy english.

Edit: I found this question https://stackoverflow.com/questions/24916486/how-to-do-enveloped-rsa-sha1-digital-signature-of-xml-data-using-php

he somehow manged to solve my problem via php splitting the base64 value by chunks and 76 length with this code

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

how can i achieve that with c#?

Community
  • 1
  • 1
Glas
  • 169
  • 1
  • 3
  • 12
  • I found this code and implemented it but i can't split the total of the base64 string http://puu.sh/d6mtC/4f7306e9b9.png – Glas Nov 26 '14 at 16:26
  • Perhaps start at looking on what those php functions really do and then do it in c# :-) rtrim trims the right side of a string. Chunk_split splits a string every 76th character (defined by the input parameter) and the base64_encode is just a simple base64 encoding. :-) combine it and you will get your answer! – Zerratar Nov 26 '14 at 16:29
  • Karl, I am on that, but i am not sure if it will works http://puu.sh/d6omi/e931d1a79d.png – Glas Nov 26 '14 at 16:56

2 Answers2

1

A little old, but I think is much simpler to let dotNet do the work for you like this:

var bytes = Convert.FromBase64String(str);
return Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
Jose
  • 26
  • 4
0

Alright! You can try this :-) Add the following code

    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(' ');
    }

and then just use

chunk_split(base64_encode(strstr), 76);

EDIT You could use this function to fix the signature of the document. I don't know how else I can help you :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);
    }

this will require that all code is in place.

Zerratar
  • 1,229
  • 11
  • 10
  • I am checking it right now `string.Join("", str.Take(len)); string.Join("", str.Skip(j * len).Take(len)); string.Join("", str.Skip(div * len).Take(remainder)); ` Gives me a invalid argument error, trying to debug if you wanna have a laugh, here's the awful code i made. http://pastebin.com/5Rs64X0v – Glas Nov 26 '14 at 19:17
  • i am using exactly .NET Framework 3.5 as the entire solution uses VFP 2008, http://puu.sh/d6zv6/326a5fb6bb.png yep, looks like it's 3.5 also http://puu.sh/d6zxa/5e13bebb97.png – Glas Nov 26 '14 at 19:26
  • I managed to get it to work, now i am fighting with these lines can you give me a hand? I am not used to XML usage http://pastebin.com/Na05WqVs Fixing this should solve all my trouble. – Glas Nov 26 '14 at 19:38
  • Can't you just use xmldocument.DocumentElement.SelectSingleNode(para).AppendChild(xmlDigitalSignature) ? – Zerratar Nov 26 '14 at 19:42
  • can't insert specified node as secondary valid element of this node, beacuse the specified node is incorrect http://puu.sh/d6Bec/50e5387aa6.png – Glas Nov 26 '14 at 19:54
  • i managed to fix this, but i found another problem with the replacement. I made a new thread for it. http://stackoverflow.com/questions/27158035/replace-string-with-another-string-does-not-work Many thanks for the help, you've solved this one though. Regards – Glas Nov 26 '14 at 20:10