title: Verify BouncyCastle ECDsa signature with .NET libraries ECDsaCng
body: <p>An existing system generated signatures using Bouncy Castle (.NET) and I need to verify these existing signatures using the Microsoft ECDsaCng class. </p>
  
  <p>Consider the following code that attempts to do this:</p>
  
  <pre><code>   public static void InterchangeTest()
  {
      //AsymmetricCipherKeyPair bKeyPair_0 = Crypto.GenerateEcdsaKey();
      String sPassPhrase = "bob is your uncle";
      byte[] bPassPhrase = new UTF8Encoding(false).GetBytes(sPassPhrase);
  
      int SaltBitSize = 128;
      int EcdsaBitLength = 521;
  
      byte[] bSalt = new byte[SaltBitSize / 8];
      new SecureRandom().NextBytes(bSalt);
  
      if (EcdsaBitLength != 192 &amp;&amp; EcdsaBitLength != 256 &amp;&amp; EcdsaBitLength != 521)
      {
          throw new ArgumentException("Invalid EcdsaBitLength length () " + EcdsaBitLength + " ECDSA supports 192, 256, and 521 bit lengths.");
      }
  
      string curveName = "P-" + EcdsaBitLength.ToString();
      X9ECParameters ecP = NistNamedCurves.GetByName(curveName);
      ECDomainParameters ecSpec = new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
      IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDH");
      g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
      AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair();
  
      ECPrivateKeyParameters mPrivateKey = (ECPrivateKeyParameters)aKeyPair.Private;
      ECPublicKeyParameters mPublicKey = (ECPublicKeyParameters)aKeyPair.Public;
  
      byte[] bPrivateKey = ((ECPrivateKeyParameters)aKeyPair.Private).D.ToByteArray();
  
      String SignerName = "SHA-256withECDSA";
      ISigner bSigner = SignerUtilities.GetSigner(SignerName);
      bSigner.Init(true, aKeyPair.Private);
      bSigner.BlockUpdate(bPassPhrase, 0, bPassPhrase.Length);
      byte[] bouncySignature = bSigner.GenerateSignature();
  
      ISigner bVerifier = SignerUtilities.GetSigner(SignerName);
      bVerifier.Init(false, aKeyPair.Public);
      bVerifier.BlockUpdate(bPassPhrase, 0, bPassPhrase.Length);
      bool passed = bVerifier.VerifySignature(bouncySignature);
      Console.WriteLine("Verified with Bouncy: " + passed);
  
      var xmlImport = "&lt;ECDSAKeyValue xmlns='http://www.w3.org/2001/04/xmldsig-more#'&gt;\n"
      + "  &lt;DomainParameters&gt;\n"
      + "    &lt;NamedCurve URN='urn:oid:1.3.132.0.35' /&gt;\n"
      + "  &lt;/DomainParameters &gt;\n"
      + "   &lt;PublicKey &gt;\n"
      + "     &lt;X Value='" + ((ECPublicKeyParameters)aKeyPair.Public).Q.X.ToBigInteger().ToString() + "' xsi:type='PrimeFieldElemType' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' /&gt;\n"
      + "     &lt;Y Value='" + ((ECPublicKeyParameters)aKeyPair.Public).Q.Y.ToBigInteger().ToString() + "' xsi:type='PrimeFieldElemType' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' /&gt;\n"
      + "  &lt;/PublicKey &gt;\n"
      + " &lt;/ECDSAKeyValue&gt;";
  
      //using (StreamWriter outputFile = new StreamWriter(@"C:\Dev\x2.txt"))
      //{
      //    outputFile.WriteLine(xmlImport);
      //}
  
      ECDsaCng eccImporter = new ECDsaCng();
      eccImporter.FromXmlString(xmlImport, ECKeyXmlFormat.Rfc4050);
  
      Console.WriteLine("hash algorithm = " + eccImporter.HashAlgorithm + " Probably " + CngAlgorithm.Sha256);
      Console.WriteLine("Signature algorithm = " + eccImporter.SignatureAlgorithm + " Probably ECDsa");
      Console.WriteLine("After import, key size = " + eccImporter.KeySize + " probably 521");
  
      try
      {
          if (eccImporter.VerifyData(bPassPhrase, bouncySignature))
          {
              Console.WriteLine("Verified the signature from bouncy castle using .NET");
          }
      }
      catch (CryptographicException e)
      {
          // "The parameter is incorrect"
          Console.WriteLine("Did not verify bouncy signature with .NET because: " + e.Message);
      }
  
  
      CngKey msKey = CngKey.Create(CngAlgorithm.ECDsaP521, null, new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowPlaintextArchiving });
      ECDsaCng ms_ecdsaCNG = new ECDsaCng(msKey);
  
      String xmlExport = ms_ecdsaCNG.ToXmlString(ECKeyXmlFormat.Rfc4050);
  
      eccImporter = new ECDsaCng();
      eccImporter.FromXmlString(xmlExport, ECKeyXmlFormat.Rfc4050);
  
      byte[] ms_SignedData = ms_ecdsaCNG.SignData(bPassPhrase);
      Console.WriteLine("Verify .NET signature with .NET: " + ms_ecdsaCNG.VerifyData(bPassPhrase, ms_SignedData));
      Console.WriteLine("Verify .NET signature with imported .NET: " + eccImporter.VerifyData(bPassPhrase, ms_SignedData));
  
      //Console.WriteLine();
      //Console.WriteLine(xmlExport);
      //Console.WriteLine();
  
  }
  </code></pre>
  
  <p>Everything works fine until I attempt to verify the signature in with the Microsoft classes, at which point it generates an exception stating that the Parameter is incorrect.</p>
  
  <p>any thoughts?</p>