0

I'm currently trying to sign an xml document using a provided p12 file, and I've managed to sign it I suppose, but after sending the document via SOAP, the response I always get is "Invalid Signature". The result xml itself has the same arhitecture as the one provided in the operators example - therefore the only thing that could be faulty is my signature value. What bothers me most is that setting the SignatureMethod and DigestMethod in my code is based purely on placing a couple of URI values - therefore my question is - am I doing it right (since I have to use SHA1, not the default SHA256)?. The method used for signing the XML :

P.S. The uidCert param creation is as follows : X509Certificate2 uidCert = new X509Certificate2("file.p12", "pass");

public static XDocument SignXml(XmlDocument xmlDoc, X509Certificate2 uidCert)
    {
        RSA rsaKey = (RSA)uidCert.PrivateKey;

        // Check arguments. 
        if (xmlDoc == null)
            throw new ArgumentException("xmlDoc");
        if (rsaKey == null)
            throw new ArgumentException("Key");

        // Create a SignedXml object.
        SignedXml signedXml = new SignedXml(xmlDoc);

        // Add the key to the SignedXml document.
        signedXml.SigningKey = rsaKey;
        signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;


        // Specify a canonicalization method.
        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;


        // Create a reference to be signed.
        Reference reference = new Reference();
        reference.Uri = "#billId";
        reference.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
        // Add an enveloped transformation to the reference.
        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(env);
        reference.AddTransform(new XmlDsigExcC14NTransform());
        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);


        // Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
        KeyInfo keyInfo = new KeyInfo();

        KeyInfoX509Data clause = new KeyInfoX509Data();
        clause.AddCertificate(uidCert);
        clause.AddIssuerSerial(uidCert.IssuerName.Name, uidCert.SerialNumber);
        keyInfo.AddClause(clause);

        signedXml.KeyInfo = keyInfo;

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

        // Get the XML representation of the signature and save 
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();
        // Append the element to the XML document.
        xmlDoc.GetElementsByTagName("tns:BillRequest").Item(0).AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

        return ToXDocument(xmlDoc);
    }

Any assistance is greatly appreciated, since I'm not really an expert neither on XML nor digital signatures. And oh by the way, on the side note - How could one place the X509IssuerSerial tag after the X509Certificate tag on the signature???

Ivor
  • 1
  • 2
  • See if following helps : https://stackoverflow.com/questions/46722997/saml-assertion-in-a-xml-using-c-sharp/46724392 – jdweng Nov 23 '20 at 09:27
  • @jdweng I'm not really sure how that applies to my specific question since they used the default SHA256 for that specific example? or am I missing something? – Ivor Nov 23 '20 at 12:44
  • Actually, my bad they are using the SHA1, but it used to be default for X509 if I'm not wrong... – Ivor Nov 23 '20 at 12:53
  • Depends on type of certificate. SSL, TLS 1.0, TLS 1.1 are not longer being used because hackers found was of breaking the encryption. So since June this year it is recommended to used only TLS 1.2 or TLS 1.3. See Wiki to see which encryption modes are used with different versions of SSL/TLS : https://en.wikipedia.org/wiki/Transport_Layer_Security – jdweng Nov 23 '20 at 12:58
  • @jdweng thanks for pointing that out, the my documentation requires for me to use TLS 1.1 or 1.2 which I have not been using so far, but still it also requires SHA1 for encryption which I don't know if I'm setting this way ergo problem not solved :( – Ivor Nov 23 '20 at 15:01
  • I do not think TLS 1.0 will work any more since Microsoft disabled 1.0 on Servers with the security push in June. The Wiki site does say SHA1 will work with TLS 1.2. So I would first get only TLS 1.2 working. Then try 1.1 afterwards. I would add to code : ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; Later you can try : SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11; – jdweng Nov 23 '20 at 15:10
  • @jdweng I did add TLS 1.2 with exactly that code, still no results - neither with TLS 1.2 nor TLS 1.1 – Ivor Nov 24 '20 at 08:04
  • There are five reasons forfailure 1)You are not using TLS 1.2,Use sniffer to check 2)The certificate is not compatible with TLS 1.2 3) Certificate is not loaded properly in client or server. A TLS Certificate block from server to client with names of the certificate the server uses.Client matches these names with the ones in the store. The certificate has to be loaded in both machine and user store 4) A Proxy is being used. Normally when proxy fails it is after 30 second timeout occurs. So if you get an exception after 30 seconds it is normally a proxy 5) Operating System doesn't support 1.2 – jdweng Nov 24 '20 at 09:23
  • 1) I'm definitely using TLS 1.2, I even tried with TLS 1.1 (checked with Wireshark)... 2) It has to be since the documentation specifically requires it 3) Possible, but how could I know 4) No proxy is in use 5) The OS supports both TLS 1.1 and TLS 1.2 – Ivor Nov 24 '20 at 12:46
  • Still how does this answer the question of - Am I setting the encryption methods for digest and signature correctly in the code provided?? @jdweng – Ivor Nov 24 '20 at 12:47
  • I think I found issue (See : http://www.w3.org/2000/09/xmldsig#rsa-sha1). Your digest is using sha1 and not rsa-sha1. The MSDN Reference Source shows all the string http values. – jdweng Nov 24 '20 at 13:30
  • I included the wrong link : https://referencesource.microsoft.com/#System.Security/system/security/cryptography/xml/signedxml.cs,09af1da42ffa471f – jdweng Nov 24 '20 at 14:08
  • I've tried with rsa-sha1, and it breaks the code - although its worth noting that in their documentation sha1 is used for digest and rsa-sha1 for the signature method... – Ivor Nov 25 '20 at 08:57
  • The http webpages seen to be the same for both sha1 and rsa-sha1. I used Beyond Compare to check. The XML page is text so I would open with notepad and check if the document looks good. Make sure the name of the key is correct (sha1 and not sha256). Does code work with sha256? I think you key in uidCert may of been generated wrong. How did you generate the key? – jdweng Nov 25 '20 at 09:39
  • The code works with SHA256, but not with rsa-sha256 on digest... The code used to genereate uidCert is `X509Certificate2 uidCert = new X509Certificate2("file.p12", "pass");` as seen above and the key is extracted with `RSA rsaKey = (RSA)uidCert.PrivateKey;` also as seen above. – Ivor Nov 25 '20 at 12:38
  • The Encryption mode that you use to verify the signed document has to be the same as the one that generated the document. So the document was signed with SA256 and not RSA-SHA256. So why are you trying to verify with the wrong algorithm? – jdweng Nov 25 '20 at 12:46
  • Could you please elaborate, where am I signing the document with SHA256 above? Where do I even set the encryption mode for verification ? Note - I need to use SHA1 which I hope I'm currently doing with the code above ? – Ivor Nov 25 '20 at 12:50
  • You are getting a good signed document that you are trying to verify. The digest has to match the type of certificate. So you can either parse the document and get the type of certificate (encryption mode) or you can try different digests until you get one that validates. I do not know you requirements. You need to verify the certificate against the encryption algorithm that was used to generate the certificate. Not against SHA1. If certificate is failing then you need to find out why somebody gave you a certificate that was not SHA1 if the requirement was SHA1. – jdweng Nov 25 '20 at 13:27
  • I'm currently in the process of communicating that with the provider, but they claim everything is alright with the cert. By the way I think you misunderstood what I meant when I said that it works with sha256 - the code runs and generates the xml, the signature is still not valid. I was saying that with rsa-sha256 I get an exception (specifcally `System.Security.Cryptography.CryptographicException: Could not create hash algorithm object.`) – Ivor Nov 26 '20 at 08:28

0 Answers0