/// <summary> /// Creates a KeyVault signed certficate from signing request. /// </summary> internal async Task <X509Certificate2> SigningRequestAsync(byte[] certificateRequest, string issuerCertificateName) { var pkcs10CertificationRequest = new Pkcs10CertificationRequest(certificateRequest); if (!pkcs10CertificationRequest.Verify()) { throw new ArgumentException("CSR signature invalid."); } var info = pkcs10CertificationRequest.GetCertificationRequestInfo(); var notBefore = DateTime.UtcNow.AddDays(-1); var certBundle = await _keyVaultServiceClient.GetCertificateAsync(issuerCertificateName).ConfigureAwait(false); var signingCert = new X509Certificate2(certBundle.Cer); var publicKey = KeyVaultCertFactory.GetRSAPublicKey(info.SubjectPublicKeyInfo); return(await KeyVaultCertFactory.CreateSignedCertificate( info.Subject.ToString(), 2048, notBefore, notBefore.AddMonths(12), 256, signingCert, publicKey, new KeyVaultSignatureGenerator(_keyVaultServiceClient, certBundle.KeyIdentifier.Identifier, signingCert) )); }
public async Task <X509Certificate2> CreateCACertificateAsync( string id, string subject, DateTime notBefore, DateTime notAfter, int keySize, int hashSize, CancellationToken ct = default) { try { // delete pending operations await _keyVaultClient.DeleteCertificateOperationAsync(_vaultBaseUrl, id); } catch { // intentionally ignore errors } string caTempCertIdentifier = null; try { //// policy self signed, new key var policySelfSignedNewKey = CreateCertificatePolicy(subject, keySize, true, false); var tempAttributes = CreateCertificateAttributes(DateTime.UtcNow.AddMinutes(-10), DateTime.UtcNow.AddMinutes(10)); var createKey = await _keyVaultClient.CreateCertificateAsync( _vaultBaseUrl, id, policySelfSignedNewKey, tempAttributes, null, ct) .ConfigureAwait(false); CertificateOperation operation; do { await Task.Delay(1000); operation = await _keyVaultClient.GetCertificateOperationAsync(_vaultBaseUrl, id, ct); } while (operation.Status == "inProgress" && !ct.IsCancellationRequested); if (operation.Status != "completed") { throw new Exception("Failed to create new key pair."); } var createdCertificateBundle = await _keyVaultClient.GetCertificateAsync(_vaultBaseUrl, id).ConfigureAwait(false); var caCertKeyIdentifier = createdCertificateBundle.KeyIdentifier.Identifier; caTempCertIdentifier = createdCertificateBundle.CertificateIdentifier.Identifier; // policy unknown issuer, reuse key var policyUnknownReuse = CreateCertificatePolicy(subject, keySize, false, true); var attributes = CreateCertificateAttributes(notBefore, notAfter); var tags = CreateCertificateTags(id, false); // create the CSR var createResult = await _keyVaultClient.CreateCertificateAsync( _vaultBaseUrl, id, policyUnknownReuse, attributes, tags, ct) .ConfigureAwait(false); if (createResult.Csr == null) { throw new Exception("Failed to read CSR from CreateCertificate."); } // decode the CSR and verify consistency var pkcs10CertificationRequest = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest(createResult.Csr); var info = pkcs10CertificationRequest.GetCertificationRequestInfo(); if (createResult.Csr == null || pkcs10CertificationRequest == null || !pkcs10CertificationRequest.Verify()) { throw new Exception("Invalid CSR."); } // create the self signed root CA cert var publicKey = KeyVaultCertFactory.GetRSAPublicKey(info.SubjectPublicKeyInfo); var signedcert = await KeyVaultCertFactory.CreateSignedCertificate( subject, (ushort)keySize, notBefore, notAfter, (ushort)hashSize, null, publicKey, new KeyVaultSignatureGenerator(this, createdCertificateBundle.KeyIdentifier.Identifier, null), true); // merge Root CA cert with var mergeResult = await _keyVaultClient.MergeCertificateAsync( _vaultBaseUrl, id, new X509Certificate2Collection(signedcert)); return(signedcert); } catch (KeyVaultErrorException kex) { Console.WriteLine($"Failed to create new Root CA certificate: {kex}"); throw; } finally { if (caTempCertIdentifier != null) { try { // disable the temp cert for self signing operation var attr = new CertificateAttributes() { Enabled = false }; await _keyVaultClient.UpdateCertificateAsync(caTempCertIdentifier, null, attr); } catch { // intentionally ignore error } } } }