65.9K
CodeProject 正在变化。 阅读更多。
Home

证书到数据库再返回

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (17投票s)

2011年2月27日

CPOL

7分钟阅读

viewsIcon

140188

downloadIcon

9314

创建基于 PEM 格式证书和密钥的 X509。

引言

在当今的应用程序中,Web服务的使用不断增长。在Web服务领域,有不同的身份验证管理方式。其中一种常见的方法是相互证书交换。

假设您的应用程序使用一个Web服务,该服务需要客户证书才能正确地与端点进行身份验证。现在,您可以向您的客户解释如何创建证书,通过生成一个RSA密钥,然后创建一个pfx容器,将pfx容器文件放置在建议的文件夹中,然后将pfx文件的正确路径插入到您的应用程序中。嗯,这工作量很大,而且相当复杂。如果您需要为同一个客户在许多PC上部署它,并且您的服务直接从客户端访问呢?如果您排除一些技巧,那么还有很多额外的工作。

如果您只将证书和私钥的pem字符串以及密码存储在数据库中呢?很好,但在.NET中创建一个包含私钥的有效X509Certificate对象并不是一项简单的任务。别担心,本指南可以帮助您。

如果本介绍中使用的某些术语对您不清楚或不熟悉,但您仍然想遵循本指南,您将在下面的链接中找到一些有用的答案

入门

为了开始并尝试本指南中提出的解决方案,您需要Microsoft Visual Studio 2010的任何版本。此代码甚至可以在Visual Studio 2008或2005等早期版本上运行,但您需要根据我建议的代码自行设置项目。

为了创建您自己的证书,您可以使用您喜欢的工具,但我会建议您使用OpenSSL。您可以从以下地址下载

在安装OpenSSL之前,请确保您已安装适当版本的Visual C++ 2008 Redistributables。安装这些库后,您可以继续安装OpenSSL。

创建证书

在创建证书之前,我们需要生成私钥。使用OpenSSL实现这一点非常简单。打开您的命令提示符窗口,并进入您安装OpenSSL的文件夹(通常是C:\Program Files\OpenSSL)下的bin目录。

现在执行以下命令

opensslgenrsa 1024 >private.key

执行后,您应该会看到类似这样的内容

create_private_key.png

检查该文件夹,应该有一个名为private.key的新文件。这是证书将基于的RSA密钥。现在让我们创建证书。执行以下命令。

opensslreq -new -x509 -nodes -sha1 -days 1100 -key private.key> public.cer

一旦您按下回车键,系统会提示您回答几个关于证书属性将填充的详细信息的问题。完成后,您将看到以下内容

create_public_cert.png

恭喜!您的证书已完成!

证书以Base64编码的DER证书表示,夹在“-----BEGIN CERTIFICATE-----”和“-----END CERTIFICATE-----”之间。RSA签名密钥也是如此。有关更多详细信息,请查阅

现在,我们可以使用PKCS格式的文件容器来存储公共证书和私钥。这不是我们项目的目标,但为了完整性,我将向您展示如何通过OpenSSL完成此操作。

通过以下命令,您将创建所需的

openssl pkcs12 -export -in public.cer -inkeyprivate.key –out cert_key.p12

执行此命令后,系统会提示您输入导出密码,此密码将用于加密您的私钥,因此请确保其复杂且唯一。

app_loaded_small.png

现在您可以将其加载到X509Certificate2对象中

string certificatePath = @"cert_key.p12";
string certificatePassword = "password";
X509Certificate2 clientCertificate = 
	new X509Certificate2(certificatePath, certificatePassword);

在接下来的步骤中,我们将直接从代码中复制此行为。

加载证书

如果只需要证书,X509Certificate2类就可以完成任务。使用以下代码,您可以简单地加载证书

string certificatePath = @"public.cer";
X509Certificate2 clientCertificate = new X509Certificate2(certificatePath);

或者,如果您想直接从string加载它

string publicCertString = "-----BEGIN CERTIFICATE----- MCIISFSDFEESd etc. example";
X509Certificate2 clientCertificate = 
	new X509Certificate2(Encoding.UTF8.GetBytes(publicCertString));

现在,框架已经提供了很多功能。但这还不够。如果我们要从证书文件加载证书,我们可以做到。否则,如果我们要从pfx或pkcs12容器加载证书和私钥,我们也可以做到。但是,如果我们要动态加载证书和私钥,选择加密密码并使用我们的对象呢?X509Certificate2没有提供像X509Certificate2(string certFileName, string privateKeyFile, string password)这样的构造函数重载,或者接受字节数组以正确初始化此对象的类似重载。在这种情况下,我们需要做一些“脏活”。所以我们开始吧。

解码RSA私钥

我不会深入探讨RSA密钥的解码方式,源代码中有详细的注释,如果您感兴趣,请阅读它,它胜过千言万语。为了解码私钥,我们将使用DecodeRsaPrivateKey方法,该方法将返回代表我们私钥的RSACryptoServiceProvider实例。

创建X509Certificate2

如前几章所述,我将使用默认的X509Certificate2构造函数来创建证书。之后,我将把解码后的RSA private密钥作为RSACryptoServiceProvider分配给X509Certificate2实例属性PrivateKey。如果一切顺利,我们将拥有正确的X509Certificate2证书容器实例,其中包含证书和密钥,并使用选定的密码进行编码。这是代码示例

byte[] certBuffer = Helpers.GetBytesFromPEM(publicCert, PemStringType.Certificate);
byte[] keyBuffer  = Helpers.GetBytesFromPEM(privateKey, PemStringType.RsaPrivateKey);

X509Certificate2 certificate = new X509Certificate2(certBuffer, password);

RSACryptoServiceProvider prov = Crypto.DecodeRsaPrivateKey(keyBuffer);
certificate.PrivateKey = prov;

我忘了提辅助方法GetBytesFromPEM,它“清除”string中的头部和尾部信息。

演示应用程序

在演示应用程序中,您可以看到如何加载所述组件,创建X509证书,持久化并重新加载所有内容。界面只是一个示例,因为它原始、简单且不完整。但是,嘿,这是一个演示,对于演示来说已经足够了!重要的东西在幕后,那是您应该感兴趣的。

这是截图

进一步改进

如何改进此代码?好吧,测试一下,我怀疑创建密钥容器,我也会测试它。任何新发现都将及时通知,文章也将更新。

我还在考虑的其他事情是为X509Certificate2创建扩展方法,以使代码看起来更简单、更简洁。

也许将这些方法包含在您的应用程序的框架加密库中?任何想法都欢迎,如果您有任何想法,请随时与我联系或发表评论。

许可证

想法和实现完全由作者完成。DecodeRsaPrivateKey方法及其内部使用的所有代码均由Dan Maser先生慷慨提供;Dan,感谢您提供代码和所有支持。RSACryptoServiceProvider的初始化方式是我为了克服.NET 4.0遇到的问题而编写的代码,所有基于特征的大小和字节对齐都是由Dan Maser编写的,但是,与Dan交谈后,我们得出了以下结论。ASN.1解析代码的核心来自stackoverflow.com上的一篇文章。在分析了代码并进行了进一步研究后,我发现了它最初的来源,我相信是http://www.jensign.com/opensslkey/opensslkey.cs。该文件的顶部确实包含标准版权声明“Copyright (C) 2008 JavaScience Consulting”。我最初编写代码时,并没有故意使用任何受版权保护的信息,但现在有点模糊了。在该网站上,我找不到任何直接表明对使用或修改代码有任何限制的指示。在http://www.jensign.com/JavaScience/cryptoutils/index.html的底部,它确实写道“注意:这些实用程序和示例代码按原样提供,不提供任何支持或性能保证。它们旨在以最少的错误检查演示特定的技术实现细节。使用风险自负。”这似乎直接表明可以自行承担风险使用已发布的实用程序。

然而,我认为这没问题,但我猜你永远不知道律师们会怎么说。如果您发现此代码违法,请立即与我联系,所有代码和文章都将被删除。

如果不是这种情况,文章以及所有相关的源代码和文件均根据The Code Project Open License (CPOL) 获得许可。

编程愉快!

© . All rights reserved.