public async Task <X509Certificate2> GetActiveCertificateAsync(long fromTimeStamp, long toTimeStamp) { if (toTimeStamp < fromTimeStamp) { throw new ArgumentOutOfRangeException( $"Invalid time range. FromTimeStamp {fromTimeStamp}, ToTimeStamp {toTimeStamp}"); } FileSystemPrivateKeyFormat keyFormat = null; FileSystemCertFormat certFormat = null; FileSystemCertCollectionFormat certsCollection = await GetFileSystemCertCollectionFormat(); FileSystemKeysCollectionFormat keysCollection = await GetFileSystemKeyCollectionFormat(); foreach (KeyValuePair <string, FileSystemCertFormat> keyValuePair in certsCollection.Certs) { string orderUrl = keyValuePair.Key; if (keysCollection.Keys.TryGetValue(orderUrl, out FileSystemPrivateKeyFormat currentPrivateKey)) { FileSystemCertFormat currentCert = keyValuePair.Value; if (currentCert.NotAfter > fromTimeStamp && currentCert.NotBefore <= toTimeStamp) { if (certFormat == null || certFormat.NotAfter < currentCert.NotAfter) { certFormat = currentCert; keyFormat = currentPrivateKey; } } } } if (certFormat == null) { return(null); } byte[] certBytes = Convert.FromBase64String(certFormat.Val); X509Certificate certificate = _certCodec.Decode(certBytes); byte[] privateKeyBytes = Convert.FromBase64String(keyFormat.Val); CertPrivateKey privateKey = _privateKeyCodec.Decode(privateKeyBytes); return(CertHelper.ToX509Certificate2(privateKey, certificate)); }
protected async Task <bool> ResolveCertificate(AcmeProtocolClient acme) { if (_state.Certificate != null) { _logger.LogInformation("Certificate is already resolved"); return(true); } CertPrivateKey key = null; _logger.LogInformation("Refreshing Order status"); _state.Order = await acme.GetOrderDetailsAsync(_state.Order.OrderUrl, _state.Order); Save(_state.OrderFile, _state.Order); if (AcmeState.PendingStatus == _state.Order.Payload.Status) { _logger.LogInformation("Generating CSR"); byte[] csr; switch (_options.CertificateKeyAlgor) { case "rsa": key = CertHelper.GenerateRsaPrivateKey( _options.CertificateKeySize ?? AcmeOptions.DefaultRsaKeySize); csr = CertHelper.GenerateRsaCsr(_options.DnsNames, key); break; case "ec": key = CertHelper.GenerateEcPrivateKey( _options.CertificateKeySize ?? AcmeOptions.DefaultEcKeySize); csr = CertHelper.GenerateEcCsr(_options.DnsNames, key); break; default: throw new Exception("Unknown Certificate Key Algorithm: " + _options.CertificateKeyAlgor); } using (var keyPem = new MemoryStream()) { CertHelper.ExportPrivateKey(key, EncodingFormat.PEM, keyPem); keyPem.Position = 0L; Save(_state.CertificateKeysFile, keyPem); } Save(_state.CertificateRequestFile, csr); _logger.LogInformation("Finalizing Order"); _state.Order = await acme.FinalizeOrderAsync(_state.Order.Payload.Finalize, csr); Save(_state.OrderFile, _state.Order); } if (AcmeState.ValidStatus != _state.Order.Payload.Status) { _logger.LogWarning("Order is NOT VALID"); return(false); } if (string.IsNullOrEmpty(_state.Order.Payload.Certificate)) { _logger.LogWarning("Order Certificate is NOT READY YET"); var now = DateTime.Now; do { _logger.LogInformation("Waiting..."); // We wait in 5s increments await Task.Delay(5000); _state.Order = await acme.GetOrderDetailsAsync(_state.Order.OrderUrl, _state.Order); Save(_state.OrderFile, _state.Order); if (!string.IsNullOrEmpty(_state.Order.Payload.Certificate)) { break; } if (DateTime.Now < now.AddSeconds(_options.WaitForCertificate)) { _logger.LogWarning("Timed Out!"); return(false); } } while (true); } _logger.LogInformation("Retreiving Certificate"); var certBytes = await acme.GetOrderCertificateAsync(_state.Order); Save(_state.CertificateChainFile, certBytes); if (key == null) { _logger.LogInformation("Loading private key"); key = CertHelper.ImportPrivateKey(EncodingFormat.PEM, Load <Stream>(_state.CertificateKeysFile).value); } using (var crtStream = new MemoryStream(certBytes)) using (var pfxStream = new MemoryStream()) { _logger.LogInformation("Reading in Certificate chain (PEM)"); var cert = CertHelper.ImportCertificate(EncodingFormat.PEM, crtStream); _logger.LogInformation("Writing out Certificate archive (PKCS12)"); CertHelper.ExportArchive(key, new[] { cert }, ArchiveFormat.PKCS12, pfxStream); pfxStream.Position = 0L; Save(_state.CertificateFile, pfxStream); } _logger.LogInformation("Loading PKCS12 archive as active certificate"); _state.Certificate = new X509Certificate2(Load <byte[]>(_state.CertificateFile).value); return(true); }
private async Task ResolveCertificate(AcmeClient acme) { _logger.LogInformation("Refreshing Order status"); _order = await acme.GetOrderDetailsAsync(_order); // FIXME, wait for ready if (OrderStatus.Ready == _order.Status) { CertPrivateKey key = null; _logger.LogInformation("Generating CSR"); byte[] csr; switch (_options.CertificateKeyAlgor) { case "rsa": key = CertHelper.GenerateRsaPrivateKey( _options.CertificateKeySize ?? AcmeOptions.DefaultRsaKeySize); csr = CertHelper.GenerateRsaCsr(_options.DnsNames, key); break; case "ec": key = CertHelper.GenerateEcPrivateKey( _options.CertificateKeySize ?? AcmeOptions.DefaultEcKeySize); csr = CertHelper.GenerateEcCsr(_options.DnsNames, key); break; default: throw new Exception("Unknown Certificate Key Algorithm: " + _options.CertificateKeyAlgor); } await _stateStore.SavePrivateKeyAsync(_order.Url, key.KeyPair, _order.Expires); _logger.LogInformation("Finalizing Order"); _order = await acme.FinalizeOrderAsync(_order, csr); } // FIXME extract out if (string.IsNullOrEmpty(_order.CertificateUrl)) { _logger.LogWarning("Order Certificate is NOT READY YET"); var now = DateTime.Now; do { _logger.LogInformation("Waiting..."); await Task.Delay(5000); _order = await acme.GetOrderDetailsAsync(_order); if (!string.IsNullOrEmpty(_order.CertificateUrl)) { break; } _logger.LogInformation($"order status {_order.Status}"); if (DateTime.Now > now.AddSeconds(_options.WaitForCertificate)) { throw new TimeoutException("Failed to get certificate url"); } } while (true); await _stateStore.SaveOrderAsync(_order); } _logger.LogInformation("Retrieving Certificate"); X509Certificate newCert = await acme.GetOrderCertificateAsync(_order); await _stateStore.SaveCertificateAsync(_order.Url, newCert); }