尝试创建非自签名证书时出现异常

2024-01-04

我想从每个设备的自签名证书切换到一对证书,其中一个是之前生成的,放置在受信任的根证书颁发机构存储中,对于所有设备都是相同的,并且作为第二个证书的根 CA,该证书是根据每个设备生成的设备,并放置在个人存储中。

我不想使用 makecert,因为创建签名证书会显示 UI,这是我想避免的。另外,由于一些与许可证相关的内容,OpenSSL 无法使用(尽管我有可用的解决方案)。因此,现在我正在使用基于 CertEnroll lib 的小型 C# 工具。

这就是我为第一个根 CA 证书创建 pfx 的方法。

makecert -n "CN=Root CA" -cy authority -r -a sha256 -len 2048 -sv root.pvk root.cer
pvk2pfx -pvk root.pvk -spc root.cer -pfx root.pfx -pi 123 -po 123

要从 C# 代码创建证书,我参考了问题如何以编程方式为 WCF 服务创建自签名证书? https://stackoverflow.com/questions/18339706/how-to-create-self-signed-certificate-programmatically-for-wcf-service and C# 使用 certenroll.dll 生成非自签名客户端 CX509Certificate 请求,无需 CA https://stackoverflow.com/questions/17756940/c-sharp-generate-a-non-self-signed-client-cx509certificate-request-without-a-ca.

到目前为止,我有以下代码。证书生成方法:

/// <summary>
/// Generates self-signed certificate with specified subject, which will expire after specified timespan.
/// </summary>
public X509Certificate2 CreateCertificate(string subjectName, TimeSpan expirationLength, X509Certificate2 issuer = null)
{
    // create DN for subject and issuer
    var dn = new CX500DistinguishedName();
    dn.Encode("CN=" + subjectName);

    var issuerName = new CX500DistinguishedName();
    if(issuer != null)
    {
        issuerName.Encode(issuer.Subject);
    }

    var privateKey = new CX509PrivateKey
    {
        ProviderName = "Microsoft Strong Cryptographic Provider",
        Length = 2048,
        KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE,
        KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_DECRYPT_FLAG |
                       X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_KEY_AGREEMENT_FLAG,
        MachineContext = true,
        ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG
    };

    privateKey.Create();

    // Use the stronger SHA512 hashing algorithm
    var hashobj = new CObjectId();
    hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
            ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY,
            AlgorithmFlags.AlgorithmFlagsNone, "SHA512");

    var cert = new CX509CertificateRequestCertificate();
    cert.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextMachine, privateKey, "");
    cert.Subject = dn;
    if (issuer != null)
        cert.Issuer = issuerName;
    else
        cert.Issuer = dn;
    cert.NotBefore = DateTime.Now.Date;
    cert.NotAfter = cert.NotBefore + expirationLength;
    cert.HashAlgorithm = hashobj; // Specify the hashing algorithm

    if(issuer != null)
    {
        var signerCertificate = new CSignerCertificate();
        signerCertificate.Initialize(true, X509PrivateKeyVerify.VerifyAllowUI, EncodingType.XCN_CRYPT_STRING_HEX, issuer.GetRawCertDataString());
        cert.SignerCertificate = signerCertificate; 
    }
    cert.Encode();

    // Do the final enrollment process
    var enroll = new CX509Enrollment();
    enroll.InitializeFromRequest(cert); // load the certificate
    enroll.CertificateFriendlyName = subjectName; // Optional: add a friendly name

    var csr = enroll.CreateRequest(); // Output the request in base64
    // and install it back as the response
    enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate,
            csr, EncodingType.XCN_CRYPT_STRING_BASE64, ""); // no password
    // output a base64 encoded PKCS#12 so we can import it back to the .Net security classes
    var base64encoded = enroll.CreatePFX("", // no password, this is for internal consumption
            PFXExportOptions.PFXExportChainWithRoot);

    // instantiate the target class with the PKCS#12 data (and the empty password)
    return new X509Certificate2(Convert.FromBase64String(base64encoded), "",
        X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
}

查找现有证书并基于它创建新证书的简单应用程序:

static void Main(string[] args)
{
    var certificateGenerator = new CertificateGenerator();

    X509Certificate2 rootCA;

    using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine))
    {
        store.Open(OpenFlags.ReadWrite);

        rootCA = store.Certificates.OfType<X509Certificate2>()
            .FirstOrDefault(c => c.Subject.StartsWith("CN=Root CA", StringComparison.Ordinal));

        store.Close();
    }

    if (rootCA == null)
        throw new Exception("Can't find root CA certificate");

    var testCert = certificateGenerator.CreateCertificate("Test", new TimeSpan(3650, 0, 0, 0), rootCA);
    using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
    {
        store.Open(OpenFlags.ReadWrite);
        store.Add(testCert);
        store.Close();
    }
}

问题是,如果我尝试不在受信任的根证书颁发机构中引用证书,而是在个人中引用证书(即使我在证书上有密码),它效果很好。但是,如果我尝试根据受信任的根证书颁发机构的 CA 证书创建证书,我会收到异常signerCertificate.Initialize, saying

Cannot find object or property. 0x80092004 (-2146885628 CRYPT_E_NOT_FOUND)

那么,我错过了什么?


ISignerCertificate::Initialize要求通过请求或我的商店绑定私钥:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa376832(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa376832(v=vs.85).aspx:

如果需要私钥,则只有个人和请求存储 搜索过。

如果不需要私钥,则根 CA 和中间 CA 商店也被搜查。

Windows 期望您仅将 CA 的公共部分放入 CA(中间)或 Root/ThirdPartyRoot 存储中,并且如果您是颁发者,您还可以将其安装(现在带有私钥)到 CurrentUser\My或 LocalMachine\My.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尝试创建非自签名证书时出现异常 的相关文章

随机推荐

  • 代码应在短暂延迟后执行一次

    我有这个Timer Timer delayTimer new Timer delayTimer Interval 500 delayTimer Elapsed object sender ElapsedEventArgs e gt Cons
  • Java 并发:倒数锁存器与循环屏障

    我正在阅读java util concurrent API http download oracle com javase 6 docs api java util concurrent package summary html 并发现 C
  • 我正在为字符串实现 CaseAccentInsensitiveEqualityComparer 。我不知道如何实现 GetHashCode

    我的代码是这样的 public class CaseAccentInsensitiveEqualityComparer IEqualityComparer
  • 寻找 PHP ord() 函数的良好 Unicode 兼容替代方案

    经过相当多的搜索和测试 我发现了 PHP 的 Unicode 兼容替代方案的最简单方法ord 功能是这样的 utf8Character list ord unpack N mb convert encoding utf8Character
  • 如何在C#中实现取消事件

    我知道在 C 中 有几个内置事件传递参数 取消 如果将其设置为true将停止引发事件的对象中的进一步执行 您将如何实现一个事件 其中引发对象能够跟踪 EventArgs 中的属性 这是我正在尝试做的 WinForms 示例 http msd
  • R稀疏逻辑矩阵符号

    做什么的 R 中的稀疏逻辑矩阵中的符号表示 我在下面展示了一些例子 gt library Matrix gt m lt Matrix c 0 0 2 0 3 5 gt m 3 x 5 sparse Matrix of class dgCMa
  • C++中命名空间的使用

    我们可以像下面的代码片段一样使用命名空间吗 该代码在 gcc 和 msvc 中编译 让我对命名空间的使用感到困惑 在 f1 h 中 namespace My void foo 在f1 cpp中 void My foo 我认为该函数应该定义为
  • 将 Numpy Lstsq 残差值转换为 R^2

    我正在执行如下最小二乘回归 单变量 我想用 R 2 来表达结果的显着性 Numpy 返回一个未缩放的残差值 这将是对其进行标准化的明智方法 field clean back clean rid zeros backscatter field
  • Unix 时间戳在 DateTime 中不断返回 1970 年 1 月 17 日

    我正在使用以下方法返回格式化日期07 00AM Apr 12 2016 但我不断得到01 41PM Sat Jan 17 1970 比如说我的时间戳是1460469600 这是我的方法 public static String format
  • Android 中的警报对话框不应关闭

    我正在制作一个应用程序 其中有一个警报对话框 现在我正在检查从对话框积极按钮 OnClick 方法中的 AlertDialog editText 获得的一些数据 但如果我从 edittext 字段获得的数据正确与否 该对话框总是会关闭 我们
  • 使用熵的加权决策树

    我正在使用构建二元分类树互信息增益 http en wikipedia org wiki Mutual information作为分裂函数 但由于训练数据偏向于少数类别 因此建议通过逆类别频率对每个训练示例进行加权 如何对训练数据进行加权
  • 如何从 Spring JMS 生成 WebSphere MQ 消息?

    我需要以 WebSphere MQ 消息格式生成队列消息 默认情况下 spring 以 JMS 格式生成消息 我用谷歌搜索并了解到WebSphere MQ消息格式包含MQMD和RFH2标头 不知道如何从 Spring 生成这两个 雄猫在哪里
  • C++20 概念中“等于”的概念

    我多次发现 在阅读一些概念定义时 该术语的使用equal 像Swappable Let t1 and t2 be 维护平等表示不同的表达式equal类型对象T Is equal标准中的某处定义 我想这意味着两个对象的语义 或者它们引用的值
  • 根据属性值设置视图可见性?

    使用 SwiftUI 定义视图层次结构时 是否可以设置hidden 定义主体中视图的值 例如 var body some View VStack alignment leading Text self name font headline
  • 在 Windows 8.1 上全新安装 Visual Studio 2013 后出现 ASP.NET MVC Razor 错误

    我最近买了一台新笔记本电脑并全新安装了 Visual Studio 2013 Professional 安装后 我做的第一件事就是确保 Nuget 设置为自动下载缺失的包 我现在正在尝试使用与购买新笔记本电脑之前使用的相同的大型解决方案 但
  • Angular UI Router 1.0.0 - 使用 $transitions.onBefore 防止路由加载

    我升级到 UI Router 1 0 0 它已从 on stateChangeX to transitions onX 在这里查看 transitions https ui router github io docs latest clas
  • Curl 到 Openshift 控制台以获取访问令牌

    我正在尝试检索 openshift 登录的用户访问令牌 我想要实现的方法是通过curl命令 其中用户提供他的用户名和密码 并作为响应将获得令牌 我无法使用 openshift python 客户端 它只能是 GET POST 调用 您需要执
  • 如何选择充满常量的多行?

    在 SQL 语句中选择常量而不引用表是完全合法的 SELECT 1 2 3 后者返回的结果集是包含值的单行 我想知道是否有一种方法可以使用常量表达式一次选择多行 例如 SELECT 1 2 3 4 5 6 7 8 9 我想要像上面这样的东西
  • UITextView行高

    不确定之前是否提到过 但我无法在任何地方找到答案 I have UITextView随着一堆文本 大约 130 行 的变化 我需要在我的文本中获取该文本的 5 行高度UITextView 尝试这个 textView font lineHei
  • 尝试创建非自签名证书时出现异常

    我想从每个设备的自签名证书切换到一对证书 其中一个是之前生成的 放置在受信任的根证书颁发机构存储中 对于所有设备都是相同的 并且作为第二个证书的根 CA 该证书是根据每个设备生成的设备 并放置在个人存储中 我不想使用 makecert 因为