创建由其他 ECDSA 证书签名的 ECDSA 证书
Creating of ECDSA certficate signed by other ECDSA certificate
我需要创建由 "Root" 证书签名的 "Client" ECDSA 证书(自签名,ECDSA)。
"Root" 证书是按照 中的描述创建的。
要创建 "Client" 证书(由 "Root" 签名),可以使用稍微修改过的算法。
不同之处在于私钥(用于从为 "Client" 证书生成的密钥对中签署 public 密钥)必须从 "outside" 提供 - 它是 [=22= 的私钥] 证书。
但这就是问题所在。我找不到一种方法来获取私钥并将其转换为可以传递给签名工厂的 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" 证书)
谢谢
如果您可以依赖 .NET Framework 4.7.2(或 .NET Core 2.0),则无需 BouncyCastle,通过新的 CertificateRequest class:
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) 更改密钥创建以使用命名密钥。否则,将仅保存 public 部分(在 Windows 上)。
我需要创建由 "Root" 证书签名的 "Client" ECDSA 证书(自签名,ECDSA)。
"Root" 证书是按照
要创建 "Client" 证书(由 "Root" 签名),可以使用稍微修改过的算法。
不同之处在于私钥(用于从为 "Client" 证书生成的密钥对中签署 public 密钥)必须从 "outside" 提供 - 它是 [=22= 的私钥] 证书。
但这就是问题所在。我找不到一种方法来获取私钥并将其转换为可以传递给签名工厂的 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" 证书) 谢谢
如果您可以依赖 .NET Framework 4.7.2(或 .NET Core 2.0),则无需 BouncyCastle,通过新的 CertificateRequest class:
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) 更改密钥创建以使用命名密钥。否则,将仅保存 public 部分(在 Windows 上)。