-->

Azure KeyVault how to load X509Certificate? [dupli

2019-09-10 05:05发布

问题:

This question already has an answer here:

  • How to serialize and deserialize a PFX certificate in Azure Key Vault? 4 answers

I uploaded a Certificate to Azure KeyVault and obtained "all" access to it using an application registered into the Active Directory. That all works fine. Now I need to load the obtained key into an X509Certificate to be able to use it as a client certificate for calling a 3rdparty legacy SOAP webservice. As far as I know I can only use a X509Certificate to call that webservice.

It does not matter if I upload it as a Key or Secret? I have tried both.

var clientId = "...."
var clientSecret = "...."

..
var token = authenticationContext.GetAccessToken(resource, adCredential);
var keyClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(token));
KeyBundle key = keyClient.GetKeyAsync("https://mycertifcates.vault.azure.net/keys/MyCertificate/123456789");

So far so good, I got a KeyBundle as a result and it seems like I can convert it to a Base64String, but whatever I try I end up with exceptions :(

1st attempt I tried:

            var publicKey = Convert.ToBase64String(key.Key.N);
            var cert = X509Certificate.FromBase64String(publicKey);

System.Security.Cryptography.CryptographicException {"Cannot find the requested object.\r\n"}

Ahhhh

2nd attempt, loading it into an RSACryptoServiceProvider, but what to do with that? Results into the same exception and I'm not even able to get the private key if I want to

        var rsaCryptoProvider = new RSACryptoServiceProvider();
        var rsaParameters = new RSAParameters()
        {
            Modulus = key.Key.N,
            Exponent = key.Key.E
        };
        rsaCryptoProvider.ImportParameters(rsaParameters);
        var cspBlob = rsaCryptoProvider.ExportCspBlob(false);

        // what to do with the cspBlob ?
        var publicKey = Convert.ToBase64String(cspBlob);

No private key as well, the public key is different. Ofcourse this does not work either.

3rd attempt

I uploaded it as a Secret Certificate ContentType using the management portal.

            var secret = helper.GetSecret("https://myCertificate.vault.azure.net/secrets/MyCertificate/1234567890");

            var value = secret.Value;

            // Now I got the secret.. works flawless
            // But it crash with the same exception at .Import
            var exportedCertCollection = new X509Certificate2Collection();
            exportedCertCollection.Import(Convert.FromBase64String(value));
            var cert2 = exportedCertCollection.Cast<X509Certificate2>().Single(s => s.HasPrivateKey);

System.Security.Cryptography.CryptographicException {"Cannot find the requested object.\r\n"}

Any suggestion is welcome.

I need the pfx including private key, looking at the tracelog

ystem.Net Information: 0 : [37880] SecureChannel#23107755 - Left with 1 client certificates to choose from. System.Net Information: 0 : [37880] SecureChannel#23107755 - Trying to find a matching certificate in the certificate store. System.Net Information: 0 : [37880] SecureChannel#23107755 - Locating the private key for the certificate: [Subject]

回答1:

To answer my own question (I asked it too quickly I guess)

It turns out that this question was in fact a duplicate, but I did not understand it at first. The fact is that the Azure Management Portal is limited. For now uploading a certificate can only be done by using a powershell (or other code for that matter).

https://stackoverflow.com/a/34186811/578552

The 3rd attempt code works fine for the X509Certificate2

        var secret = helper.GetSecret("https://myCertificate.vault.azure.net/secrets/MyCertificate/1234567890");

        var exportedCertCollection = new X509Certificate2Collection();
        exportedCertCollection.Import(Convert.FromBase64String(secret.Value));
        var cert2 = exportedCertCollection.Cast<X509Certificate2>().Single(s => s.HasPrivateKey);