Недействительная подпись при создании сертификата с помощью BouncyCastle с внешним ключом Azure KeyVault (HSM) - PullRequest
9 голосов
/ 05 августа 2020

Я пытаюсь создать сертификат, самоподписанный KeyPair, хранящийся в Azure KeyVault.

Мой конечный результат - сертификат с недействительной подписью :

введите описание изображения здесь

Создание параметров сертификата:

     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("CN=Test Root CA");

     certGen.SetSerialNumber(serialNumber);
     certGen.SetIssuerDN(selfSignedCA); //Self Signed
     certGen.SetNotBefore(startDate);
     certGen.SetNotAfter(expiryDate);
     certGen.SetSubjectDN(selfSignedCA);
      

Получение ссылки на сохраненный ключ Azure KeyVault (сервис, подобный HSM):

    //Create a client connector to Azure KeyVault
    var keyClient = new Azure.Security.KeyVault.Keys.KeyClient(
         vaultUri: new Uri("https://xxxx.vault.azure.net/"),
         credential: new ClientSecretCredential(
             tenantId: "xxxx", //Active Directory
             clientId: "xxxx", //Application id?
             clientSecret: "xxxx"
             )
         );

        var x = keyClient.GetKey("key-new-ec"); //Fetch the reference to the key

ключ успешно получен. Затем я пытаюсь сгенерировать объект ECPublicKeyParameters с ключевыми данными publi c:

    X9ECParameters x9 = ECNamedCurveTable.GetByName("P-256");
    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

Следующим шагом является создание сертификата, подписанного с помощью ключа. Я реализовал новый объект ISignatureFactory , который должен подписывать с помощью функции внешней подписи KeyVault:

      AzureKeyVaultSignatureFactory customSignatureFactory = new AzureKeyVaultSignatureFactory(1);
      Org.BouncyCastle.X509.X509Certificate cert = certGen.Generate(customSignatureFactory);

Это мой собственный AzureKeyVaultSignatureFactory :

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("https://xxxx.vault.azure.net/keys/key-new-ec/xxxx"),
                    credential: new ClientSecretCredential(

                          tenantId: "xxxx", //Active Directory
                          clientId: "xxxx", //Application id?
                          clientSecret: "xxxx"
                          )
                );

                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 => "SHA-256withECDSA";
    }

    public object AlgorithmDetails => new AlgorithmIdentifier(X9ObjectIdentifiers.ECDsaWithSha256, DerNull.Instance);
}

Затем конвертирую и записываю сертификат в файл:

 //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(@"test-signed2.cer", encoded); //-this is good!

Что я делаю не так? Может быть, построения ECCurve из X / Y недостаточно?

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...