创建由其他ECDSA证书签署的ECDSA证书

时间:2018-06-02 18:58:28

标签: c# certificate ecdsa

我需要创建由“Root”证书签名的“Client”ECDSA证书(自签名,ECDSA)。 “根”证书是按Translating Elliptic Curve parameters (BC to MS)

中所述创建的

要创建“客户端”证书(由“Root”签名),可以使用略微修改的算法。 不同之处在于私钥(用于从为“客户”证书生成的密钥对签署公钥)必须从“外部”提供 - 它是“根”证书的私钥。 但这是问题所在。我找不到如何获取和转换私钥到类型Org.BouncyCastle.Crypto.Parameters.ECPrivateKeyParameters可以传递给签名工厂的方法。

// 1. get private-key of "Root" certificate from existing certificate:
byte[] msRootCertData = File.ReadAllBytes(@"c:\root_ecdsa_cert.pfx");
X509Certificate2 msRootCert = new X509Certificate2(msRootCertData);
ECDsaCng msRootPrivateKey = msRootCert.GetECDsaPrivateKey() as ECDsaCng;
ECParameters msRootPrivateKeyParameters = msRootPrivateKey.ExportParameters(true);

// here comes the issue:
ECPrivateKeyParameters bcRootPrivateKeysParameters = TranslateMSKeysToBouncy(msRootPrivateKeyParameters);

// 2. generate "Client" key-pair:
AsymmetricCipherKeyPair bcClientKeyPair = bcKeyGen.GenerateKeyPair();
ECPrivateKeyParameters bcClientPrivKey = (ECPrivateKeyParameters)bcClientKeyPair.Private;
ECPrivateKeyParameters bcClientPublKey = (ECPublicKeyParameters)bcClientKeyPair.Public;

// 3. create X509 certificate:
X509V3CertificateGenerator bcCertGen = new X509V3CertificateGenerator();
bcCertGen.SetPublicKey(bcClientPublKey);
// .. set subject, validity period etc
ISignatureFactory sigFac = new Asn1SignatureFactory("Sha256WithECDSA", bcRootPrivateKeysParameters);
Org.BouncyCastle.X509.X509Certificate bcClientX509Cert = bcCertGen.Generate(sigFac);
byte[] x509CertEncoded = bcClientX509Cert.GetEncoded();

//其余部分与上述示例相同。

任何提示? 或者还有其他方式吗? (例如:将X509Certificate2的实例直接传递给BouncyCastle库(避免将私钥转换为Cng),或者在没有BouncyCastle的情况下生成“Client”证书) 感谢。

1 个答案:

答案 0 :(得分:3)

如果您可以依赖.NET Framework 4.7.2(或.NET Core 2.0),则可以通过新的CertificateRequest类在没有BouncyCastle的情况下执行此操作:

X509Certificate2 publicPrivate;

using (ECDsa clientPrivateKey = ECDsa.Create())
{
    var request = new CertificateRequest(
        "CN=Et. Cetera",
        clientPrivateKey,
        HashAlgorithmName.SHA256);

    // Assuming this isn't another CA cert:
    request.CertificateExtensions.Add(
        new X509BasicConstraintsExtension(false, false, 0, false));

    // other CertificateExtensions as you desire.

    // Assign, or derive, a serial number.
    // RFC 3280 recommends that it have no more than 20 bytes encoded.
    // 12 random bytes seems long enough.
    byte[] serial = new byte[12];

    using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(serial);
    }

    DateTimeOffset notBefore = DateTimeOffset.UtcNow;
    DateTimeOffset notAfter = notBefore.AddMonths(15);

    using (X509Certificate2 publicOnly = request.Create(
        msRootCert,
        notBefore,
        notAfter,
        serial))
    {
        publicPrivate = publicOnly.CopyWithPrivateKey(clientPrivateKey);
    }
}

// The original key object was disposed,
// but publicPrivate.GetECDsaPrivateKey() still works.

如果要将publicPrivate添加到X509Store,您需要1)将其导出到PFX并重新导入它,或者2)更改密钥创建以使用命名密钥。否则,只保存公共部分(在Windows上)。