BouncyCastle의 C# API를 사용하여 CA 인증서와 자체 서명 인증서를 생성하는 좋은 예를 발견했습니다.BouncyCastle AT_SIGNATURE의 KeySpec 변경
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Downloaded using nuget, source: http://www.bouncycastle.org/csharp/
//Library is open-source.
namespace CertificateToolLibrary
{
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509.Extension;
using Org.BouncyCastle.X509;
public class X509Certificate2Builder
{
public string SubjectName
{ set { _subjectName = value; } }
public string SubjectAlternativeName
{ set { _subjectAlternativeName = value; } }
public string IssuerName
{ set { _issuerName = value; } }
public AsymmetricAlgorithm IssuerPrivateKey
{ set { _issuerPrivateKey = value; } }
public X509Certificate2 Issuer
{
set
{
_issuer = value;
_issuerName = value.IssuerName.Name;
if (value.HasPrivateKey)
_issuerPrivateKey = value.PrivateKey;
}
}
public int? KeyStrength
{ set { _keyStrength = value ?? 2048; } }
public DateTime? NotBefore
{ set { _notBefore = value; } }
public DateTime? NotAfter
{ set { _notAfter = value; } }
public bool Intermediate
{ set { _intermediate = value; } }
private string _subjectName;
private string _subjectAlternativeName;
private X509Certificate2 _issuer;
private string _issuerName;
private AsymmetricAlgorithm _issuerPrivateKey;
private int _keyStrength = 2048;
private DateTime? _notBefore;
private DateTime? _notAfter;
private bool _intermediate = true;
public X509Certificate2 Build()
{
// Generating Random Numbers
var randomGenerator = new CryptoApiRandomGenerator();
var random = new SecureRandom(randomGenerator);
// The Certificate Generator
var certificateGenerator = new X509V3CertificateGenerator();
// Serial Number
var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random);
certificateGenerator.SetSerialNumber(serialNumber);
// Signature Algorithm
certificateGenerator.SetSignatureAlgorithm("SHA512WithRSA");
// Issuer and Subject Name
certificateGenerator.SetIssuerDN(new X509Name(_issuerName ?? _subjectName));
certificateGenerator.SetSubjectDN(new X509Name(_subjectName));
//Subject Alternative Name
if (!(String.IsNullOrEmpty(_subjectAlternativeName)))
{
//Here we signify ip address instead of DNS SAN. This could be condition upon further development.
GeneralNames subjectAltName = new GeneralNames(new GeneralName(GeneralName.IPAddress, _subjectAlternativeName));
certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, subjectAltName);
}
// Authority Key Identifier
if (_issuer != null)
{
var authorityKeyIdentifier = new AuthorityKeyIdentifierStructure(DotNetUtilities.FromX509Certificate(_issuer));
certificateGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false, authorityKeyIdentifier);
//var subjectKeyIdentifier = new SubjectKeyIdentifier(DotNetUtilities.FromX509Certificate(_issuer));
//certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, false, subjectKeyIdentifier);
//certificateGenerator.addExtension(X509Extensions.SubjectKeyIdentifier.Id, false, new SubjectKeyIdentifierStructure(keyPair.getPublic()));
}
// Basic Constraints - certificate is allowed to be used as intermediate.
certificateGenerator.AddExtension(X509Extensions.BasicConstraints, false, new BasicConstraints(_intermediate));
// Valid For
certificateGenerator.SetNotBefore(_notBefore ?? DateTime.UtcNow.Date.AddDays(-1));
certificateGenerator.SetNotAfter(_notAfter ?? DateTime.UtcNow.Date.AddYears(3));
//Key Usage(s) don't set for CA cert, just the SSL cert.
if (_subjectName != "CN=Bla Certificate Authority")
{
certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment));
var usages = new[] { KeyPurposeID.IdKPServerAuth, KeyPurposeID.IdKPClientAuth};
certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(usages));
}
// Subject Public Key
var keyGenerationParameters = new KeyGenerationParameters(random, _keyStrength);
var keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
var subjectKeyPair = keyPairGenerator.GenerateKeyPair();
var issuerKeyPair = _issuerPrivateKey == null
? subjectKeyPair
: DotNetUtilities.GetKeyPair(_issuerPrivateKey);
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
//Add the subject key identifier for the SSL Certficate
if (_subjectName != "CN=Bla Certificate Authority")
{
certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(subjectKeyPair.Public));
}
// selfsign certificate
var certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
// merge into X509Certificate2
return new X509Certificate2(certificate.GetEncoded())
{
PrivateKey = ConvertToRsaPrivateKey(subjectKeyPair)
};
}
private static AsymmetricAlgorithm ConvertToRsaPrivateKey(AsymmetricCipherKeyPair keyPair)
{
var keyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
var seq = (Asn1Sequence)Asn1Object.FromByteArray(keyInfo.PrivateKey.GetDerEncoded());
if (seq.Count != 9)
throw new PemException("malformed sequence in RSA private key");
var rsa = new RsaPrivateKeyStructure(seq);
var rsaparams = new RsaPrivateCrtKeyParameters(rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);
return DotNetUtilities.ToRSA(rsaparams);
}
}
} 나는 모든 온라인 예제를 찾을 수 없습니다
:
그러나, 나는의 KeySpec = 2 (CERT_KEY_PROV_INFO_PROP_ID에 대한 At_Signature)가 아니라이 코드는 현재 제공 0의의 KeySpec 필요 키 스펙을 디지털 서명으로 수정하는 방법 개인 키 쪽에서 일어난다는 것을 알았지 만 적어도 Bouncycastle 코드를 사용하는 경우, 특히 C# 예제를 사용하는 경우에는 예제가 없습니다.
저는 네이티브 C# 코드에서 cspparams와 같은 rsaparams를 사용할 수는 있지만 그걸 찾을 수는 없습니다.
도움을 주시면 대단히 감사하겠습니다.
예를 들어 보시면 두 가지를 모두 사용하고 있습니다. – Mumbles76
certificateGenerator.AddExtension (X509Extensions.KeyUsage, true, new KeyUsage (KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment)); var 사용법 = 새로운 [] {KeyPurposeID.IdKPServerAuth, KeyPurposeID.IdKPClientAuth}; certificateGenerator.AddExtension (X509Extensions.ExtendedKeyUsage.Id, false, 새 ExtendedKeyUsage (용도)); – Mumbles76
이 링크는 질문에 대한 대답 일지 모르지만 여기에 답변의 핵심 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않게 될 수 있습니다. - [검토 중] (리뷰/저품각 게시물/14025596) – maazza