/// <inheritdoc/>
        public async Task <Certificate> ImportCertificateAsync(string certificateName,
                                                               Certificate certificate, Key privateKey, CancellationToken ct)
        {
            if (string.IsNullOrEmpty(certificateName))
            {
                throw new ArgumentNullException(nameof(certificateName));
            }
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }
            if (privateKey == null)
            {
                certificate = certificate.Clone();
                certificate.IssuerPolicies = null;
                await _certificates.AddCertificateAsync(certificateName, certificate, null, ct);

                return(certificate);
            }
            try {
                var password  = Guid.NewGuid().ToString();
                var pfxBase64 = certificate.ToPfx(privateKey, password).ToBase64String();
                // Import bundle
                var bundle = await _keyVaultClient.ImportCertificateAsync(_vaultBaseUrl,
                                                                          certificateName, pfxBase64, password,
                                                                          CreateCertificatePolicy(certificate, true, _keyStoreIsHsm),
                                                                          CreateCertificateAttributes(certificate.NotBeforeUtc,
                                                                                                      certificate.NotAfterUtc - certificate.NotBeforeUtc, certificate.NotAfterUtc),
                                                                          null, ct);

                try {
                    var result = CertificateEx.Create(bundle.Cer,
                                                      new KeyVaultKeyHandle(bundle), certificate.IssuerPolicies);
                    await _certificates.AddCertificateAsync(
                        certificateName, result, bundle.CertificateIdentifier.Identifier, ct);

                    return(result);
                }
                catch {
                    await Try.Async(() => _keyVaultClient.DeleteCertificateAsync(
                                        _vaultBaseUrl, certificateName, ct));

                    throw;
                }
            }
            catch (KeyVaultErrorException ex) {
                throw new ExternalDependencyException("Failed to import certificate", ex);
            }
        }
Example #2
0
        /// <summary>
        /// Convert to certificate model
        /// </summary>
        /// <param name="document"></param>
        /// <returns></returns>
        private Certificate DocumentToCertificate(CertificateDocument document)
        {
            if (document == null)
            {
                return(null);
            }
            var keyHandle = _keys.DeserializeHandle(document.KeyHandle);

            return(CertificateEx.Create(document.RawData,
                                        keyHandle,
                                        document.IsserPolicies,
                                        document.DisabledSince == null ? null : new RevocationInfo {
                Date = document.DisabledSince,
                // ...
            }));
        }
Example #3
0
 /// <summary>
 /// Convert to framework model
 /// </summary>
 /// <returns></returns>
 public static Certificate ToStackModel(this X509CertificateModel model)
 {
     return(CertificateEx.Create(model.ToRawData()));
 }
        /// <inheritdoc/>
        public async Task <Certificate> CreateCertificateAndPrivateKeyAsync(string rootCertificate,
                                                                            string certificateName, X500DistinguishedName subjectName, DateTime?notBefore,
                                                                            CreateKeyParams keyParams, Func <byte[], IEnumerable <X509Extension> > extensions,
                                                                            CancellationToken ct)
        {
            try {
                // (0) Retrieve issuer certificate
                var caCertBundle = await _keyVaultClient.GetCertificateAsync(
                    _vaultBaseUrl, rootCertificate, ct);

                if (caCertBundle == null)
                {
                    throw new ResourceNotFoundException("Issuer cert not found.");
                }
                var caCert = await _certificates.FindCertificateAsync(
                    caCertBundle.CertificateIdentifier.Identifier);

                if (caCert?.IssuerPolicies == null)
                {
                    throw new ArgumentException("Certificate cannot issue.");
                }

                // (1) Create key in key vault and get CSR.

                // policy unknown issuer, new key, exportable key
                var policyUnknownNewExportable = CreateCertificatePolicy(
                    subjectName.Name, keyParams, false, _keyStoreIsHsm, false, true);

                var attributes = CreateCertificateAttributes(notBefore,
                                                             caCert.IssuerPolicies.IssuedLifetime.Value, caCert.NotAfterUtc);
                var createResult = await CreateCertificateAsync(certificateName,
                                                                policyUnknownNewExportable, attributes, null, ct);

                if (createResult.Csr == null)
                {
                    throw new CryptographicUnexpectedOperationException(
                              "Failed to read CSR from CreateCertificate.");
                }
                // decode the CSR and verify consistency
                var info = createResult.Csr.ToCertificationRequest();

                try {
                    // (2) - Issue X509 Certificate with csr and root certificate.

                    // create signed cert
                    var signedcert = await _factory.CreateCertificateAsync(this,
                                                                           caCert, subjectName, info.PublicKey,
                                                                           attributes.NotBefore.Value, attributes.Expires.Value,
                                                                           caCert.IssuerPolicies.SignatureType.Value, false, extensions, ct);

                    // (3) - Complete certificate creation with merger of X509 Certificate.

                    var mergeResult = await _keyVaultClient.MergeCertificateAsync(
                        _vaultBaseUrl, certificateName,
                        new X509Certificate2Collection(signedcert), null, null, ct);

                    // (4) - Get merged certificate and key identifier

                    var mergedCert = await _keyVaultClient.GetCertificateAsync(
                        mergeResult.CertificateIdentifier.Identifier, ct);

                    var cert = CertificateEx.Create(mergedCert.Cer,
                                                    new KeyVaultKeyHandle(mergedCert));
                    System.Diagnostics.Debug.Assert(!cert.IsIssuer());
                    await _certificates.AddCertificateAsync(certificateName,
                                                            cert, mergedCert.CertificateIdentifier.Identifier, ct);

                    return(cert);
                }
                catch {
                    await _keyVaultClient.DeleteCertificateAsync(
                        _vaultBaseUrl, certificateName, ct);

                    await Try.Async(() => _keyVaultClient.PurgeDeletedCertificateAsync(
                                        _vaultBaseUrl, certificateName, ct));

                    throw;
                }
            }
            catch (KeyVaultErrorException ex) {
                throw new ExternalDependencyException(
                          "Failed to create new key pair certificate", ex);
            }
        }
        /// <inheritdoc/>
        public async Task <Certificate> NewRootCertificateAsync(string certificateName,
                                                                X500DistinguishedName subjectName, DateTime?notBefore, TimeSpan lifetime,
                                                                CreateKeyParams keyParams, IssuerPolicies policies,
                                                                Func <byte[], IEnumerable <X509Extension> > extensions,
                                                                CancellationToken ct)
        {
            if (string.IsNullOrEmpty(certificateName))
            {
                throw new ArgumentNullException(nameof(certificateName));
            }

            // Validate policies
            policies = policies.Validate(null, keyParams);
            string caTempCertIdentifier = null;

            try {
                // (1) Create key in key vault and get CSR.

                // policy self signed, new key, not exportable key
                var policySelfSignedNewKey = CreateCertificatePolicy(
                    subjectName.Name, keyParams, true, _keyStoreIsHsm, false, false);
                var tempAttributes = CreateCertificateAttributes(
                    DateTime.UtcNow.AddMinutes(-10), TimeSpan.FromMinutes(10),
                    DateTime.MaxValue);

                await CreateCertificateAsync(certificateName, policySelfSignedNewKey,
                                             tempAttributes, null, ct);

                // We have the cert - get it and key identifier to do the signing
                var createdCertificateBundle = await _keyVaultClient.GetCertificateAsync(
                    _vaultBaseUrl, certificateName, ct);

                caTempCertIdentifier =
                    createdCertificateBundle.CertificateIdentifier.Identifier;

                // policy unknown issuer, reuse key - not exportable
                var policyUnknownReuse = CreateCertificatePolicy(
                    subjectName.Name, keyParams, false, _keyStoreIsHsm, true, false);
                var attributes = CreateCertificateAttributes(notBefore, lifetime,
                                                             DateTime.MaxValue);

                // create the CSR
                var createResult = await CreateCertificateAsync(certificateName,
                                                                policyUnknownReuse, attributes, null, ct);

                if (createResult.Csr == null)
                {
                    throw new CryptographicUnexpectedOperationException(
                              "Failed to read CSR from CreateCertificate.");
                }

                // decode the CSR and verify consistency
                var info = createResult.Csr.ToCertificationRequest();

                // (2) - Issue root X509 Certificate with the csr.

                var signedcert = await _factory.CreateCertificateAsync(this,
                                                                       new KeyVaultKeyHandle(createdCertificateBundle), subjectName,
                                                                       info.PublicKey,
                                                                       attributes.NotBefore.Value, attributes.Expires.Value,
                                                                       policies.SignatureType.Value, true, extensions, ct);

                // (3) - Complete certificate creation with merger of X509 Certificate.

                var mergeResult = await _keyVaultClient.MergeCertificateAsync(
                    _vaultBaseUrl, certificateName,
                    new X509Certificate2Collection(signedcert), null, null, ct);

                // (4) - Get merged certificate and key identifier

                var mergedCert = await _keyVaultClient.GetCertificateAsync(
                    mergeResult.CertificateIdentifier.Identifier, ct);

                var cert = CertificateEx.Create(mergedCert.Cer,
                                                new KeyVaultKeyHandle(mergedCert), policies);
                await _certificates.AddCertificateAsync(certificateName, cert,
                                                        mergedCert.CertificateIdentifier.Identifier, ct);

                return(cert);
            }
            catch (KeyVaultErrorException kex) {
                throw new ExternalDependencyException(
                          "Failed to create new Root CA certificate", kex);
            }
            finally {
                if (caTempCertIdentifier != null)
                {
                    // disable the temp cert for self signing operation
                    var attr = new CertificateAttributes {
                        Enabled = false
                    };
                    await Try.Async(() => _keyVaultClient.UpdateCertificateAsync(
                                        caTempCertIdentifier, null, attr));
                }
            }
        }