我们目前有一个使用 Microsoft Active Directory 证书服务生成 CA 证书的解决方案。
我们有一个您可以登录的应用程序,您可以发送 CA 证书请求。
这会在后台加载一个 iframe(指向 MS CA 证书服务上的表单)使用 jQuery 复制数据负载并提交表单。
表单提交使用 ActiveX 和 CertEnroll 创建一个 CSR,并将其发布到另一个 ASP 页。(整个MS AD证书服务都是ASP页面)
问题是这只适用于IE(显然)
我的建议是移动 CSR 生成服务器端,这样它就不会依赖 IE 并且可以从任何浏览器中使用。
我有一个可行的解决方案,它将数据发送到 api,并在 api 中生成 CSR 并将其转发到 MS CA 证书服务器,这会生成有效的证书。
问题
问题是,一旦我安装了证书,就会丢失“您拥有与此证书对应的私钥”的信息。在现有系统上,此消息显示如下:
我的假设是这是因为尚未为私钥设置 KeyProtection。不幸的是,它在现有 VBScript 实现中使用的标志需要用户输入:XCN_NCRYPT_UI_PROTECT_KEY_FLAG。每次请求证书时,都会提示用户保护密钥
对于我的 .Net Framework 实现,我尝试了两种不同的 CSR 生成器,一种使用 Bouncy Castle,另一种使用 CERTENROLLLib 的互操作。
我将在下面显示的代码将是 CERTENROLLLib 实现,但如果有人对这两种解决方案有任何想法,我会很高兴听到他们
CERTENROLLLib CSR 一代
var values = new Dictionary<string, string>
{
{ "E", emailAddress },
{ "CN", commonName },
{ "OU", organizationalUnit },
{ "L", locality }
};
var privateKey = new CX509PrivateKeyClass
{
Length = 1024,
MachineContext = false,
CspInformations = GetCryptographicProvider(),
// This can't be set as it requires UI feedback
//KeyProtection = X509PrivateKeyProtection.XCN_NCRYPT_UI_PROTECT_KEY_FLAG,
ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_NONE,
};
// Create the actual key pair
privateKey.Create();
// Initialize the PKCS#10 certificate request object based on the private key.
// Using the context, indicate that this is a user certificate request and don't
// provide a template name
var certificateRequest = new CX509CertificateRequestPkcs10Class();
certificateRequest.InitializeFromPrivateKey(
X509CertificateEnrollmentContext.ContextUser,
privateKey,
string.Empty
);
var extension = new CX509ExtensionsClass
{
GetExtensionKeyUsage(),
GetExtensionEnhancedKeyUsage()
};
certificateRequest.X509Extensions.AddRange(extension);
// Encode the name in using the Distinguished Name object
var valueCollection = values.Select(v => $"{v.Key}={v.Value}").Reverse();
var subject = new CX500DistinguishedNameClass();
subject.Encode(
string.Join(";", valueCollection), X500NameFlags.XCN_CERT_NAME_STR_ENABLE_PUNYCODE_FLAG
);
// Assigning the subject name by using the Distinguished Name object initialized above
certificateRequest.Subject = subject;
// Create enrollment request
var enrollmentRequest = new CX509EnrollmentClass();
enrollmentRequest.InitializeFromRequest(certificateRequest);
var csr = enrollmentRequest.CreateRequest(EncodingType.XCN_CRYPT_STRING_BASE64REQUESTHEADER);
所以我的问题是如何为私钥添加密钥保护,如屏幕截图所示?
由于这是服务器端,我不能指望任何用户反馈,所以还有另一种方法。
任何指导都将受到欢迎,因为可能很清楚,我对 CSR 的产生还很陌生。
最终这将被重写,我们可能会生成我们自己的证书,但我只是试图改善目前的情况。
非常感谢