c# - 使用 ASP.NET Core 3.0 内置 API 从 .crt 和 .key 文件创建 X509Certificate2
问题描述
我正在使用 ASP.NET Core 3.0 预览版 8 开发一个 Web 应用程序。我想要实现的是直接从 .crt 和 .key (PKCS#1) 文件创建一个 X509Certificate2 以使用新的 .NET Core 3.0 与 Kestrel 一起使用内置在此链接中介绍的 Api。
目前我正在使用此命令将证书转换为 .pfx 文件
openssl pkcs12 -export -in $CERTIFICATE_FILE -inkey $KEY_FILE -out $OUTPUT_CERTIFICATE_FILE -passout pass:$OUTPUT_CERTIFICATE_PASSWORD
然后我创建 X509Certificate2 并将其与 Kestrel 一起使用:
webBuilder.ConfigureKestrel((context, options) =>
{
options.ConfigureHttpsDefaults(httpsOptions =>
{
if (!context.HostingEnvironment.IsProduction())
return;
string outputCertificateFile = context.Configuration["OUTPUT_CERTIFICATE_FILE"];
string outputCertificatePassword = context.Configuration["OUTPUT_CERTIFICATE_PASSWORD"];
var tlsCertificate = new X509Certificate2(outputCertificateFile, outputCertificatePassword);
httpsOptions.ServerCertificate = tlsCertificate;
});
});
编辑:-
我已经根据上面链接中的示例实现了新的 Api:
using (var privateKey = RSA.Create())
{
byte[] keyBytes = File.ReadAllBytes(context.Configuration["KEY_FILE"]);
privateKey.ImportRSAPrivateKey(keyBytes, out int bytesRead);
X509Certificate2 certificateFile = new X509Certificate2(context.Configuration["CERTIFICATE_FILE"]);
X509Certificate2 tlsCertificate = certificateFile.CopyWithPrivateKey(privateKey);
httpsOptions.ServerCertificate = tlsCertificate;
}
但是新代码抛出了这个异常:
Unhandled exception. System.Security.Cryptography.CryptographicException: ASN1 corrupted data.
at System.Security.Cryptography.Asn1.AsnReader.CheckExpectedTag(Asn1Tag tag, Asn1Tag expectedTag, UniversalTagNumber tagNumber)
at System.Security.Cryptography.Asn1.AsnReader.ReadSequence(Asn1Tag expectedTag)
at System.Security.Cryptography.Asn1.RSAPrivateKeyAsn.Decode(AsnReader reader, Asn1Tag expectedTag, RSAPrivateKeyAsn& decoded)
at System.Security.Cryptography.Asn1.RSAPrivateKeyAsn.Decode(Asn1Tag expectedTag, ReadOnlyMemory`1 encoded, AsnEncodingRules ruleSet)
at System.Security.Cryptography.Asn1.RSAPrivateKeyAsn.Decode(ReadOnlyMemory`1 encoded, AsnEncodingRules ruleSet)
at System.Security.Cryptography.RSAKeyFormatHelper.FromPkcs1PrivateKey(ReadOnlyMemory`1 keyData, AlgorithmIdentifierAsn& algId, RSAParameters& ret)
at System.Security.Cryptography.RSA.ImportRSAPrivateKey(ReadOnlySpan`1 source, Int32& bytesRead)
at Example.Program.<>c__DisplayClass1_0.<CreateWebHostBuilder>b__3(HttpsConnectionAdapterOptions httpsOptions) in /src/Example/Program.cs:line 47
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions.ApplyHttpsDefaults(HttpsConnectionAdapterOptions httpsOptions)
at Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(ListenOptions listenOptions, Action`1 configureOptions)
at Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(ListenOptions listenOptions)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.BindAsync(AddressBindContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IServerAddressesFeature addresses, KestrelServerOptions serverOptions, ILogger logger, Func`2 createBinding)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
at Example.Program.Main(String[] args) in /src/Example/Program.cs:line 16
解决方案
以下应将 PEM 编码的证书和密钥文件加载到 Kestral 中:
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureHttpsDefaults(listenOptions =>
{
using var privateKey = RSA.Create();
privateKey.ImportRSAPrivateKey(
PemBytes(pemKeyFile), out var bytesRead);
X509Certificate2 certificate =
new X509Certificate2(PemBytes(pemCertFile));
listenOptions.ServerCertificate =
certificate.CopyWithPrivateKey(privateKey);
});
});
webBuilder.UseStartup<Startup>();
});
}
public static byte[] PemBytes(string fileName) =>
Convert.FromBase64String(
File.ReadAllLines(fileName)
.Where(l => !l.Contains('-'))
.Aggregate("", (current, next) => current + next));
推荐阅读
- android - 在Production Playstore App上没有答案的Flutter DialogFlow
- android - 前台服务 - 设置不确定的进度条
- mockito - 为什么@Spy 仅用于依赖项?
- azure - Azure 服务总线会话是否保证 FIFO 顺序?
- python - 在Python中每组每3行分组和求和
- shell - shell find - 获取当前文件的文件夹名称
- font-awesome - 带有tailwindcss的字体真棒响应大小
- javascript - 从 iframe 源将元素从父级移动到 iframe
- javascript - npm 注册表中 lodash tarball 中的额外文件
- android - 应用启动后切换硬件加速