title: Invalid signature when creating a certificate using BouncyCastle with an external Azure KeyVault (HSM) Key
body: <p>I'm trying to generate a certificate self-signed by a KeyPair stored in Azure KeyVault.</p>
  <p>My end result is a certificate with an <strong>invalid signature</strong>:</p>
  <p><a href="https://i.stack.imgur.com/b6HpS.png" rel="noreferrer"><img src="https://i.stack.imgur.com/b6HpS.png" alt="enter image description here" /></a></p>
  <p>Generating the certificate parameters:</p>
  <pre><code>     DateTime startDate = DateTime.Now.AddDays(-30);
       DateTime expiryDate = startDate.AddYears(100);
  
       BigInteger serialNumber = new BigInteger(32, new Random());
       X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
  
       X509Name selfSignedCA = new X509Name(&quot;CN=Test Root CA&quot;);
  
       certGen.SetSerialNumber(serialNumber);
       certGen.SetIssuerDN(selfSignedCA); //Self Signed
       certGen.SetNotBefore(startDate);
       certGen.SetNotAfter(expiryDate);
       certGen.SetSubjectDN(selfSignedCA);
        
  </code></pre>
  <p>Fetching a reference to the Azure KeyVault stored key (HSM like service):</p>
  <pre><code>    //Create a client connector to Azure KeyVault
      var keyClient = new Azure.Security.KeyVault.Keys.KeyClient(
           vaultUri: new Uri(&quot;https://xxxx.vault.azure.net/&quot;),
           credential: new ClientSecretCredential(
               tenantId: &quot;xxxx&quot;, //Active Directory
               clientId: &quot;xxxx&quot;, //Application id?
               clientSecret: &quot;xxxx&quot;
               )
           );
  
          var x = keyClient.GetKey(&quot;key-new-ec&quot;); //Fetch the reference to the key
  </code></pre>
  <p>The key is successfully retrieved.
  I then try to generate a <strong>ECPublicKeyParameters</strong> object with the key's public data:</p>
  <pre><code>    X9ECParameters x9 = ECNamedCurveTable.GetByName(&quot;P-256&quot;);
      Org.BouncyCastle.Math.EC.ECCurve curve = x9.Curve;
  
      var ecPoint = curve.CreatePoint(new Org.BouncyCastle.Math.BigInteger(1, x.Value.Key.X), new Org.BouncyCastle.Math.BigInteger(1, x.Value.Key.Y));
      ECDomainParameters dParams = new ECDomainParameters(curve, ecPoint, x9.N);
      ECPublicKeyParameters pubKey = new ECPublicKeyParameters(ecPoint, dParams);
  
      certGen.SetPublicKey(pubKey); //Setting the certificate's public key with the fetched one
  </code></pre>
  <p>Next step is generating a certificate signed with the key. I implemented a new <strong>ISignatureFactory</strong> object that should sign with an external signature function of KeyVault:</p>
  <pre><code>      AzureKeyVaultSignatureFactory customSignatureFactory = new AzureKeyVaultSignatureFactory(1);
        Org.BouncyCastle.X509.X509Certificate cert = certGen.Generate(customSignatureFactory);
  </code></pre>
  <p>This is my custom <strong>AzureKeyVaultSignatureFactory</strong>:</p>
  <pre><code>public class AzureKeyVaultSignatureFactory : ISignatureFactory
  {
      private readonly int _keyHandle;
  
      public AzureKeyVaultSignatureFactory(int keyHandle)
      {
          this._keyHandle = keyHandle;
      }
  
      public IStreamCalculator CreateCalculator()
      {
          var sig = new CustomAzureKeyVaultDigestSigner(this._keyHandle);
  
          sig.Init(true, null);
  
          return new DefaultSignatureCalculator(sig);
      }
  
      internal class CustomAzureKeyVaultDigestSigner : ISigner
      {
          private readonly int _keyHandle;
          private byte[] _input;
  
          public CustomAzureKeyVaultDigestSigner(int keyHandle)
          {
              this._keyHandle = keyHandle;
          }
  
          public void Init(bool forSigning, ICipherParameters parameters)
          {
              this.Reset();
          }
  
          public void Update(byte input)
          {
              return;
          }
  
          public void BlockUpdate(byte[] input, int inOff, int length)
          {
              this._input = input.Skip(inOff).Take(length).ToArray();
          }
  
          public byte[] GenerateSignature()
          {
              //Crypto Client (Specific Key)
              try
              {
  
                  //Crypto Client (Specific Key)
                  CryptographyClient identitiesCAKey_cryptoClient = new CryptographyClient(
                      keyId: new Uri(&quot;https://xxxx.vault.azure.net/keys/key-new-ec/xxxx&quot;),
                      credential: new ClientSecretCredential(
  
                            tenantId: &quot;xxxx&quot;, //Active Directory
                            clientId: &quot;xxxx&quot;, //Application id?
                            clientSecret: &quot;xxxx&quot;
                            )
                  );
  
                  SignResult signResult = identitiesCAKey_cryptoClient.SignData(SignatureAlgorithm.ES256, this._input);
                  return signResult.Signature;
  
  
              }
              catch (Exception ex)
              {
  
                  throw ex;
              }
  
              return null;
          }
  
          public bool VerifySignature(byte[] signature)
          {
              return false;
          }
  
          public void Reset() { }
  
          public string AlgorithmName =&gt; &quot;SHA-256withECDSA&quot;;
      }
  
      public object AlgorithmDetails =&gt; new AlgorithmIdentifier(X9ObjectIdentifiers.ECDsaWithSha256, DerNull.Instance);
  }
  </code></pre>
  <p>Then I convert and write the certificate to a file:</p>
  <pre><code> //convert to windows type 2 and get Base64 
   X509Certificate2 cert2 = new X509Certificate2(DotNetUtilities.ToX509Certificate(cert));
   byte[] encoded = cert2.GetRawCertData();
   string certOutString = Convert.ToBase64String(encoded);
   System.IO.File.WriteAllBytes(@&quot;test-signed2.cer&quot;, encoded); //-this is good!
  </code></pre>
  <p>What am I doing wrong? Maybe constructing the ECCurve from X/Y is not enough?</p>
  <p>Thanks!</p>