public virtual Task VerifySigningRequestAsync(
            ApplicationRecordDataType application,
            byte[] certificateRequest)
        {
            try
            {
                var pkcs10CertificationRequest = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest(certificateRequest);

                if (!pkcs10CertificationRequest.Verify())
                {
                    throw new ServiceResultException(StatusCodes.BadInvalidArgument, "CSR signature invalid.");
                }

                var info             = pkcs10CertificationRequest.GetCertificationRequestInfo();
                var altNameExtension = GetAltNameExtensionFromCSRInfo(info);
                if (altNameExtension != null)
                {
                    if (altNameExtension.Uris.Count > 0)
                    {
                        if (!altNameExtension.Uris.Contains(application.ApplicationUri))
                        {
                            throw new ServiceResultException(StatusCodes.BadCertificateUriInvalid,
                                                             "CSR AltNameExtension does not match " + application.ApplicationUri);
                        }
                    }
                }
                return(Task.CompletedTask);
            }
            catch (Exception ex)
            {
                if (ex is ServiceResultException)
                {
                    throw ex as ServiceResultException;
                }
                throw new ServiceResultException(StatusCodes.BadInvalidArgument, ex.Message);
            }
        }
Exemple #2
0
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            CreateSigningRequestUploadApiModel request = (CreateSigningRequestUploadApiModel)validationContext.ObjectInstance;
            var errorList = new List <string>();

            if (request.CertificateRequestFile == null &&
                String.IsNullOrWhiteSpace(request.ApiModel.CertificateRequest))
            {
                errorList.Add(nameof(request.CertificateRequestFile));
                errorList.Add("ApiModel.CertificateRequest");
                return(new ValidationResult("At least one CSR field is required.", errorList));
            }

            if (request.CertificateRequestFile != null &&
                !String.IsNullOrWhiteSpace(request.ApiModel.CertificateRequest))
            {
                errorList.Add(nameof(request.CertificateRequestFile));
                errorList.Add("ApiModel.CertificateRequest");
                return(new ValidationResult("Only one CSR field is required.", errorList));
            }

            byte[] certificateRequest = null;

            if (request.ApiModel.CertificateRequest != null)
            {
                errorList.Add("ApiModel.CertificateRequest");
                try
                {
                    const string certRequestPemHeader = "-----BEGIN CERTIFICATE REQUEST-----";
                    const string certRequestPemFooter = "-----END CERTIFICATE REQUEST-----";
                    if (request.ApiModel.CertificateRequest.Contains(certRequestPemHeader, StringComparison.OrdinalIgnoreCase))
                    {
                        var strippedCertificateRequest = request.ApiModel.CertificateRequest.Replace(certRequestPemHeader, "", StringComparison.OrdinalIgnoreCase);
                        strippedCertificateRequest = strippedCertificateRequest.Replace(certRequestPemFooter, "", StringComparison.OrdinalIgnoreCase);
                        certificateRequest         = Convert.FromBase64String(strippedCertificateRequest);
                    }
                    else
                    {
                        certificateRequest = Convert.FromBase64String(request.ApiModel.CertificateRequest);
                    }
                }
                catch
                {
                    return(new ValidationResult("Cannot decode base64 encoded CSR.", errorList));
                }
            }

            if (request.CertificateRequestFile != null)
            {
                errorList.Add(nameof(request.CertificateRequestFile));
                try
                {
                    using (var memoryStream = new MemoryStream())
                    {
                        request.CertificateRequestFile.CopyToAsync(memoryStream).Wait();
                        certificateRequest = memoryStream.ToArray();
                    }
                }
                catch
                {
                    errorList.Add(nameof(request.CertificateRequestFile));
                    return(new ValidationResult("Invalid CSR file.", errorList));
                }
            }

            if (certificateRequest != null)
            {
                try
                {
                    var pkcs10CertificationRequest = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest(certificateRequest);
                    if (!pkcs10CertificationRequest.Verify())
                    {
                        return(new ValidationResult("CSR signature invalid.", errorList));
                    }

                    var info             = pkcs10CertificationRequest.GetCertificationRequestInfo();
                    var altNameExtension = GetAltNameExtensionFromCSRInfo(info);
                    if (altNameExtension != null &&
                        altNameExtension.Uris.Count > 0)
                    {
                        if (!altNameExtension.Uris.Contains(request.ApplicationUri))
                        {
                            return(new ValidationResult(altNameExtension.Uris[0] + " doesn't match the ApplicationUri.", errorList));
                        }
                    }
                    else
                    {
                        return(new ValidationResult("The CSR does not contain a valid Application Uri.", errorList));
                    }
                }
                catch
                {
                    return(new ValidationResult("CSR decoding failed. Invalid data?", errorList));
                }
            }

            return(ValidationResult.Success);
        }
        public virtual async Task <X509Certificate2> SigningRequestAsync(
            ApplicationRecordDataType application,
            string[] domainNames,
            byte[] certificateRequest)
        {
            try
            {
                var pkcs10CertificationRequest = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest(certificateRequest);

                if (!pkcs10CertificationRequest.Verify())
                {
                    throw new ServiceResultException(StatusCodes.BadInvalidArgument, "CSR signature invalid.");
                }

                var info             = pkcs10CertificationRequest.GetCertificationRequestInfo();
                var altNameExtension = GetAltNameExtensionFromCSRInfo(info);
                if (altNameExtension != null)
                {
                    if (altNameExtension.Uris.Count > 0)
                    {
                        if (!altNameExtension.Uris.Contains(application.ApplicationUri))
                        {
                            throw new ServiceResultException(StatusCodes.BadCertificateUriInvalid,
                                                             "CSR AltNameExtension does not match " + application.ApplicationUri);
                        }
                    }

                    if (altNameExtension.IPAddresses.Count > 0 || altNameExtension.DomainNames.Count > 0)
                    {
                        var domainNameList = new List <string>();
                        domainNameList.AddRange(altNameExtension.DomainNames);
                        domainNameList.AddRange(altNameExtension.IPAddresses);
                        domainNames = domainNameList.ToArray();
                    }
                }

                DateTime yesterday = DateTime.UtcNow.AddDays(-1);
                using (var signingKey = await LoadSigningKeyAsync(Certificate, string.Empty))
                {
                    return(CertificateFactory.CreateCertificate(
                               null,
                               null,
                               null,
                               application.ApplicationUri ?? "urn:ApplicationURI",
                               application.ApplicationNames.Count > 0 ? application.ApplicationNames[0].Text : "ApplicationName",
                               info.Subject.ToString(),
                               domainNames,
                               Configuration.DefaultCertificateKeySize,
                               yesterday,
                               Configuration.DefaultCertificateLifetime,
                               Configuration.DefaultCertificateHashSize,
                               false,
                               signingKey,
                               info.SubjectPublicKeyInfo.GetEncoded()));
                }
            }
            catch (Exception ex)
            {
                if (ex is ServiceResultException)
                {
                    throw ex as ServiceResultException;
                }
                throw new ServiceResultException(StatusCodes.BadInvalidArgument, ex.Message);
            }
        }
        public virtual async Task <X509Certificate2> SigningRequestAsync(
            ApplicationRecordDataType application,
            string[] domainNames,
            byte[] certificateRequest)
        {
            try
            {
                var pkcs10CertificationRequest = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest(certificateRequest);

                if (!pkcs10CertificationRequest.Verify())
                {
                    throw new ServiceResultException(StatusCodes.BadInvalidArgument, "CSR signature invalid.");
                }

                var info             = pkcs10CertificationRequest.GetCertificationRequestInfo();
                var altNameExtension = GetAltNameExtensionFromCSRInfo(info);
                if (altNameExtension != null)
                {
                    if (altNameExtension.Uris.Count > 0)
                    {
                        if (!altNameExtension.Uris.Contains(application.ApplicationUri))
                        {
                            throw new ServiceResultException(StatusCodes.BadCertificateUriInvalid,
                                                             "CSR AltNameExtension does not match " + application.ApplicationUri);
                        }
                    }

                    if (altNameExtension.IPAddresses.Count > 0 || altNameExtension.DomainNames.Count > 0)
                    {
                        var domainNameList = new List <string>();
                        domainNameList.AddRange(altNameExtension.DomainNames);
                        domainNameList.AddRange(altNameExtension.IPAddresses);
                        domainNames = domainNameList.ToArray();
                    }
                }

                DateTime yesterday = DateTime.Today.AddDays(-1);
                using (var signingKey = await LoadSigningKeyAsync(Certificate, string.Empty).ConfigureAwait(false))
                {
                    return(CertificateFactory.CreateCertificate(
                               application.ApplicationUri,
                               null,
                               info.Subject.ToString(),
                               domainNames)
                           .SetNotBefore(yesterday)
                           .SetLifeTime(Configuration.DefaultCertificateLifetime)
                           .SetHashAlgorithm(X509Utils.GetRSAHashAlgorithmName(Configuration.DefaultCertificateHashSize))
                           .SetIssuer(signingKey)
                           .SetRSAPublicKey(info.SubjectPublicKeyInfo.GetEncoded())
                           .CreateForRSA());
                }
            }
            catch (Exception ex)
            {
                if (ex is ServiceResultException)
                {
                    throw ex as ServiceResultException;
                }
                throw new ServiceResultException(StatusCodes.BadInvalidArgument, ex.Message);
            }
        }
Exemple #5
0
        /// <summary>
        /// Creates a new signed application certificate in group id.
        /// </summary>
        /// <remarks>
        /// The key for the certificate is created in KeyVault, then exported.
        /// In order to deleted the created key, the impersonated user needs
        /// create, get and delete rights for KeyVault certificates
        /// </remarks>
        public async Task <X509Certificate2> CreateSignedKeyPairCertAsync(
            string caCertId,
            X509Certificate2 issuerCert,
            string applicationUri,
            string applicationName,
            string subjectName,
            string[] domainNames,
            DateTime notBefore,
            DateTime notAfter,
            int keySize,
            int hashSize,
            KeyVaultSignatureGenerator generator,
            string authorityInformationAccess,
            CancellationToken ct = default)
        {
            CertificateOperation createResult = null;
            var certName = KeyStoreName(caCertId, Guid.NewGuid().ToString());

            try
            {
                // policy unknown issuer, new key, exportable
                var policyUnknownNewExportable = CreateCertificatePolicy(subjectName, keySize, false, false, true);
                var attributes = CreateCertificateAttributes(notBefore, notAfter);

                // create the CSR
                createResult = await _keyVaultClient.CreateCertificateAsync(
                    _vaultBaseUrl,
                    certName,
                    policyUnknownNewExportable,
                    attributes,
                    null,
                    ct)
                               .ConfigureAwait(false);

                if (createResult.Csr == null)
                {
                    throw new ServiceResultException(StatusCodes.BadInvalidArgument, "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 ServiceResultException(StatusCodes.BadInvalidArgument, "Invalid CSR.");
                }

                // create the self signed app cert
                var publicKey  = KeyVaultCertFactory.GetRSAPublicKey(info.SubjectPublicKeyInfo);
                var signedcert = await KeyVaultCertFactory.CreateSignedCertificate(
                    applicationUri,
                    applicationName,
                    subjectName,
                    domainNames,
                    (ushort)keySize,
                    notBefore,
                    notAfter,
                    (ushort)hashSize,
                    issuerCert,
                    publicKey,
                    generator,
                    extensionUrl : authorityInformationAccess);

                // merge signed cert with keystore
                var mergeResult = await _keyVaultClient.MergeCertificateAsync(
                    _vaultBaseUrl,
                    certName,
                    new X509Certificate2Collection(signedcert)
                    );

                X509Certificate2 keyPair = null;
                var secret = await _keyVaultClient.GetSecretAsync(mergeResult.SecretIdentifier.Identifier, ct);

                if (secret.ContentType == CertificateContentType.Pfx)
                {
                    var certBlob = Convert.FromBase64String(secret.Value);
                    keyPair = CertificateFactory.CreateCertificateFromPKCS12(certBlob, string.Empty);
                }
                else if (secret.ContentType == CertificateContentType.Pem)
                {
                    Encoding encoder    = Encoding.UTF8;
                    var      privateKey = encoder.GetBytes(secret.Value.ToCharArray());
                    keyPair = CertificateFactory.CreateCertificateWithPEMPrivateKey(signedcert, privateKey, string.Empty);
                }

                return(keyPair);
            }
            catch
            {
                throw new ServiceResultException(StatusCodes.BadInternalError, "Failed to create new key pair certificate");
            }
            finally
            {
                try
                {
                    var deletedCertBundle = await _keyVaultClient.DeleteCertificateAsync(_vaultBaseUrl, certName, ct);

                    await _keyVaultClient.PurgeDeletedCertificateAsync(_vaultBaseUrl, certName, ct);
                }
                catch
                {
                    // intentionally fall through, purge may fail
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Creates a new Root CA certificate in group id, tags it for trusted or issuer store.
        /// </summary>
        public async Task <X509Certificate2> CreateCACertificateAsync(
            string id,
            string subject,
            DateTime notBefore,
            DateTime notAfter,
            int keySize,
            int hashSize,
            bool trusted,
            string crlDistributionPoint = null,
            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 ServiceResultException(StatusCodes.BadUnexpectedError, "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, trusted);

                // create the CSR
                var createResult = await _keyVaultClient.CreateCertificateAsync(
                    _vaultBaseUrl,
                    id,
                    policyUnknownReuse,
                    attributes,
                    tags,
                    ct)
                                   .ConfigureAwait(false);

                if (createResult.Csr == null)
                {
                    throw new ServiceResultException(StatusCodes.BadInvalidArgument, "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 ServiceResultException(StatusCodes.BadInvalidArgument, "Invalid CSR.");
                }

                // create the self signed root CA cert
                var publicKey  = KeyVaultCertFactory.GetRSAPublicKey(info.SubjectPublicKeyInfo);
                var signedcert = await KeyVaultCertFactory.CreateSignedCertificate(
                    null,
                    null,
                    subject,
                    null,
                    (ushort)keySize,
                    notBefore,
                    notAfter,
                    (ushort)hashSize,
                    null,
                    publicKey,
                    new KeyVaultSignatureGenerator(this, caCertKeyIdentifier, null),
                    true,
                    crlDistributionPoint);

                // merge Root CA cert with
                var mergeResult = await _keyVaultClient.MergeCertificateAsync(
                    _vaultBaseUrl,
                    id,
                    new X509Certificate2Collection(signedcert)
                    );

                return(signedcert);
            }
            catch (KeyVaultErrorException kex)
            {
                var ex = kex;
                throw new ServiceResultException(StatusCodes.BadInternalError, "Failed to create new Root CA certificate");
            }
            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
                    }
                }
            }
        }
        /// <summary>
        /// Creates a KeyVault signed certficate from signing request.
        /// </summary>
        public override async Task <X509Certificate2> SigningRequestAsync(
            ApplicationRecordDataType application,
            string[] domainNames,
            byte[] certificateRequest
            )
        {
            try
            {
                var pkcs10CertificationRequest = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest(certificateRequest);
                if (!pkcs10CertificationRequest.Verify())
                {
                    throw new ServiceResultException(StatusCodes.BadInvalidArgument, "CSR signature invalid.");
                }

                var info             = pkcs10CertificationRequest.GetCertificationRequestInfo();
                var altNameExtension = GetAltNameExtensionFromCSRInfo(info);
                if (altNameExtension != null)
                {
                    if (altNameExtension.Uris.Count > 0)
                    {
                        if (!altNameExtension.Uris.Contains(application.ApplicationUri))
                        {
                            throw new ServiceResultException(StatusCodes.BadCertificateUriInvalid,
                                                             "CSR AltNameExtension does not match " + application.ApplicationUri);
                        }
                    }

                    if (altNameExtension.IPAddresses.Count > 0 || altNameExtension.DomainNames.Count > 0)
                    {
                        var domainNameList = new List <string>();
                        domainNameList.AddRange(altNameExtension.DomainNames);
                        domainNameList.AddRange(altNameExtension.IPAddresses);
                        domainNames = domainNameList.ToArray();
                    }
                }

                var authorityInformationAccess = BuildAuthorityInformationAccessUrl();

                DateTime notBefore = DateTime.UtcNow.AddDays(-1);
                await LoadPublicAssets().ConfigureAwait(false);

                var signingCert = Certificate;
                {
                    var publicKey = KeyVaultCertFactory.GetRSAPublicKey(info.SubjectPublicKeyInfo);
                    return(await KeyVaultCertFactory.CreateSignedCertificate(
                               application.ApplicationUri,
                               application.ApplicationNames.Count > 0?application.ApplicationNames[0].Text : "ApplicationName",
                               info.Subject.ToString(),
                               domainNames,
                               Configuration.DefaultCertificateKeySize,
                               notBefore,
                               notBefore.AddMonths(Configuration.DefaultCertificateLifetime),
                               Configuration.DefaultCertificateHashSize,
                               signingCert,
                               publicKey,
                               new KeyVaultSignatureGenerator(_keyVaultServiceClient, _caCertKeyIdentifier, signingCert),
                               extensionUrl : authorityInformationAccess
                               ));
                }
            }
            catch (Exception ex)
            {
                if (ex is ServiceResultException)
                {
                    throw ex as ServiceResultException;
                }
                throw new ServiceResultException(StatusCodes.BadInvalidArgument, ex.Message);
            }
        }