0

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를 사용할 수는 있지만 그걸 찾을 수는 없습니다.

도움을 주시면 대단히 감사하겠습니다.

답변

0

체크 아웃

난 당신이 KeyUsage.keyEncipherment

+0

예를 들어 보시면 두 가지를 모두 사용하고 있습니다. – Mumbles76

+0

certificateGenerator.AddExtension (X509Extensions.KeyUsage, true, new KeyUsage (KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment)); var 사용법 = 새로운 [] {KeyPurposeID.IdKPServerAuth, KeyPurposeID.IdKPClientAuth}; certificateGenerator.AddExtension (X509Extensions.ExtendedKeyUsage.Id, false, 새 ExtendedKeyUsage (용도)); – Mumbles76

+0

이 링크는 질문에 대한 대답 일지 모르지만 여기에 답변의 핵심 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않게 될 수 있습니다. - [검토 중] (리뷰/저품각 게시물/14025596) – maazza

0

내가, 데스크탑 개발에 있던 것을 밝혀을 사용하려는 생각 KeyUsage 상수 클래스와이 keySpec에는 그러나, 0으로 설정 내 도구를 2012 서버에서 실행했는데 keyspec이 1로 설정되었습니다. 모두 설정되었습니다.

0
public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey) 
    { 
     var cspParams = new CspParameters 
     { 
      ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider", 
      ProviderType = 24, 
      KeyContainerName = KEY_CONTAINER_NAME, 
      KeyNumber = (int)KeyNumber.Signature, 
      Flags = CspProviderFlags.UseMachineKeyStore 
     }; 

     RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams); 

     RSAParameters parameters = new RSAParameters 
     { 
      Modulus = privateKey.Modulus.ToByteArrayUnsigned(), 
      P = privateKey.P.ToByteArrayUnsigned(), 
      Q = privateKey.Q.ToByteArrayUnsigned(), 
      DP = privateKey.DP.ToByteArrayUnsigned(), 
      DQ = privateKey.DQ.ToByteArrayUnsigned(), 
      InverseQ = privateKey.QInv.ToByteArrayUnsigned(), 
      D = privateKey.Exponent.ToByteArrayUnsigned(), 
      Exponent = privateKey.PublicExponent.ToByteArrayUnsigned() 
     }; 

     rsaProvider.ImportParameters(parameters); 

     return rsaProvider; 
    } 

그래서 여기에 다른 답변을 추가하기 위해이 스 니펫을 사용하여 keyspec = 2 AT_SIGNATURE를 강제 실행할 수있었습니다. 하지만 현재 서명 문제가 있습니다. 다른 사람들이 그것을 올바른 방향으로 이끌어 갈 수 있도록 그냥 버리고 싶었습니다.