Я нашел отличный пример использования C# API BouncyCastle для создания сертификата CA и самозаверяющего сертификата.BouncyCastle Change KeySpec для AT_SIGNATURE
Однако мне нужно KeySpec = 2 (At_Signature для CERT_KEY_PROV_INFO_PROP_ID), а не KeySpec 0. Что в настоящее время предоставляет этот код:
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);
}
}
}
я не могу найти любые онлайн примеры о том, как изменить ключ для цифровой подписи. Я понимаю, что это должно произойти на стороне закрытого ключа, но там просто нет примеров, по крайней мере, при использовании кода bouncycastle, особенно в примерах C#.
Я полагаю, что использовать rsaparams как cspparams в родном коде C#, но я просто ничего не могу найти на нем.
Любая помощь была бы чрезвычайно оценена!
Да, если вы посмотрите в моем примере, я использую оба. – Mumbles76
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 (обычаи)); – Mumbles76
Хотя эта ссылка может ответить на вопрос, лучше включить здесь основные части ответа и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. - [Из обзора] (/ review/low-quality-posts/14025596) – maazza