title: Digital signature verification error for accessing webservice
body: <p>I need to send a digital signature as one the parameters to an external webservice. </p>
  
  <p>The steps to create as per documentation is :</p>
  
  <ol>
  <li>Create a <code>DOM</code> representation of the <code>XML</code> data</li>
  <li>Create a canonicalised representation of the <code>DOM</code> data. The canonicalised representation should follow the form described in <a href="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" rel="nofollow">http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments</a>;</li>
  <li>Create the signature <code>RSA</code> encryption of the <code>SHA1</code> digest of the canonicalised representation. The signature is encrypted using the Participant‟s private key;</li>
  <li>Encode the binary signature into a base64-encoded string</li>
  <li>Place the Signature string in the <code>SOAP</code> message <code>ReqDigSig</code> element;</li>
  <li>Store the XML data as it may be needed later to support Non-Repudiation of the submitted XML data.</li>
  </ol>
  
  <p>I have used the following code:</p>
  
  <pre><code>private string SignXML(X509Certificate2 Cert, string data)
      {
          XmlDocument xmlDoc = new XmlDocument();
          xmlDoc.PreserveWhitespace = false;
          xmlDoc.LoadXml(data);
  
          XmlDsigC14NWithCommentsTransform t = new XmlDsigC14NWithCommentsTransform();
          t.LoadInput(xmlDoc);
          Stream s = (Stream)t.GetOutput(typeof(Stream));
  
          SHA1 sha1 = SHA1.Create();
          byte[] hash = sha1.ComputeHash(s);
  
  
          RSACryptoServiceProvider rsaKey =
          (RSACryptoServiceProvider)Cert.PrivateKey;
          RSAParameters rsaPrivateParams = rsaKey.ExportParameters(true);
          rsaKey.ImportParameters(rsaPrivateParams);
          byte[] signature =  rsaKey.Encrypt(hash, false);
  
          return Convert.ToBase64String(signature);
      }
  </code></pre>
  
  <p>But the response from the webservice says digital signature verification error.</p>
  
  <p>is the code above as per the description in the documentation?
  How would i verify if the digital signaature is valid? is there any online tool?</p>
  
  <p>[Post edited as follows]
   I have tried using the following. I have verified the signature and it returns true. But fails from the webservice end. What is the difference among signData, signHash and the rsaPKCsignatureformatter classes' createsignature method?</p>
  
  <pre><code>        var document = Encoding.UTF8.GetBytes(Reqdata);
  
          XmlDocument xmlDoc = new XmlDocument();
          xmlDoc.PreserveWhitespace = false;
          xmlDoc.LoadXml(Reqdata);
  
          //trial with XmlDsigC14NWithCommentsTransform class
          XmlDsigC14NWithCommentsTransform t = new XmlDsigC14NWithCommentsTransform();
          t.LoadInput(xmlDoc);
          Stream s = (Stream)t.GetOutput(typeof(Stream));
  
          //trial with SignedXML class
          SignedXml signedXml = new SignedXml(xmlDoc);
          signedXml.SignedInfo.CanonicalizationMethod =
          SignedXml.XmlDsigC14NWithCommentsTransformUrl;
          document = Encoding.UTF8.GetBytes(signedXml.ToString());
  
          byte[] hashedDocument;
  
          using (var sha1 = SHA1.Create())
          {
              //hashedDocument = sha1.ComputeHash(document);
              hashedDocument = sha1.ComputeHash(s);
          }
  
          var digitalSignature = new DigitalSignature();
          digitalSignature.AssignNewKey();
  
          byte[] signature = digitalSignature.SignData(hashedDocument);
          string finalsignature = Convert.ToBase64String(signature) ;
          byte[] finalSignveri = Convert.FromBase64String(finalsignature);
          bool verified = digitalSignature.VerifySignature(hashedDocument, finalSignveri);
  </code></pre>
  
  <p>and the digital signature class is as follows:</p>
  
  <pre><code>public class DigitalSignature
  {
      private RSAParameters publicKey;
      private RSAParameters privateKey;
  
      public void AssignNewKey()
      {
          using (var rsa = new RSACryptoServiceProvider())
          {
              rsa.PersistKeyInCsp = false;
              publicKey = rsa.ExportParameters(false);
              privateKey = rsa.ExportParameters(true);
          }
      }
  
      public byte[] SignData(byte[] hashOfDataToSign)
      {
          using (var rsa = new RSACryptoServiceProvider())
          {
              rsa.PersistKeyInCsp = false;
              rsa.ImportParameters(privateKey);
  
              var rsaFormatter = new RSAPKCS1SignatureFormatter(rsa);
              rsaFormatter.SetHashAlgorithm("SHA1");
  
              return rsaFormatter.CreateSignature(hashOfDataToSign);
          }
      }
  
      public bool VerifySignature(byte[] hashOfDataToSign, byte[] signature)
      {
          using (var rsa = new RSACryptoServiceProvider())
          {
              rsa.ImportParameters(publicKey);
  
              var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
              rsaDeformatter.SetHashAlgorithm("SHA1");
  
              return rsaDeformatter.VerifySignature(hashOfDataToSign, signature);
          }
      }   
  }
  </code></pre>
  
  <p>Could you please let me know what data are you specifically looking for in wsdl?  Sorry i am unable to provide the complete wsdl information here.</p>
  
  <p>The error returned is i believe user handled and states "Digital signature verification error"</p>
  
  <p>[Redited]</p>
  
  <p>Please find below a snippet of the code that generates digital signature in java. This was sent by the third party for reference. I am not a java developer. Could someone let me know if the C#code that i have written corresponds to the Java code? if not, please let me know where i am going wrong.</p>
  
  <pre><code>private static String createDigitalSignature(Key key, byte[] data) {
  
      byte[] signature = null;
  
      try {
          // Initialize xml-security library
          org.apache.xml.security.Init.init();
  
          // Build DOM document from XML data
          DocumentBuilderFactory dfactory = DocumentBuilderFactory
                  .newInstance();
          dfactory.setNamespaceAware(true);
          dfactory.setValidating(true);
          DocumentBuilder documentBuilder = dfactory.newDocumentBuilder();
          // This is to throw away all validation errors
          documentBuilder
                  .setErrorHandler(new org.apache.xml.security.utils.IgnoreAllErrorHandler());
          Document doc = documentBuilder
                  .parse(new ByteArrayInputStream(data));
  
          // Build canonicalized XML from document
          Canonicalizer c14n = Canonicalizer
                  .getInstance("http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments");
          byte[] canonBytes = c14n.canonicalizeSubtree(doc);
  
          // Initialize signing object with SHA1 digest and RSA encryption
          Signature rsa = Signature.getInstance("SHA1withRSA");
  
          // Set private key into signing object
          rsa.initSign((PrivateKey) key);
  
          // Generate signature
          rsa.update(canonBytes);
          signature = rsa.sign();
      } catch (Exception ex) {
          System.out.println("Exception occurred in createDigitalSignature: "
                  + ex.toString());
          System.exit(-1);
      }
  
      // Base64 encode signature
      BASE64Encoder b64e = new BASE64Encoder();
      String signatureString = b64e.encode(signature);
  
      return signatureString;
  }
  </code></pre>