1
  1. 次のように、Bouncy Castle ライブラリを使用して、CA ルート証明書と自己署名マシン証明書を作成しています。実装全体を以下にリストします。パスワードで保護された .PFX ファイルを作成できます。

  2. CA ルート証明書を作成しましたが、マシンに既にインストールされているため (サブジェクトと発行者が同じ)、インストールしません。それに加えて、元の CAR ルート証明書 (MyCARoot.cer) がどのように作成されたのかはわかりませんが、次のコマンドでインストールされます。

    certmgr.exe /add MyCARoot.cer /c /s /r localMachine ルート

  3. ある時点で、certutil.exe を使用して作成した自己署名マシン証明書 (.PFX) をインストールできましたが、現在は常に上記のエラーが返されます。

  4. ここでの私の質問は、1 つ以上の領域を対象としています。

    • 以下の私の実装が正しいかどうか-「秘密鍵のエクスポートを許可する」などの何かを見逃していましたか...
    • アプローチ全体が正しいかどうか - makecert.exe を pvk2pfx.exe と一緒に使用する代わりに、自己署名マシン証明書を手動で作成してインストールする必要があったため、それに切り替えました。ユーザーは秘密鍵パスワードの入力を 4 回求められます。 ..
    • 生成した .pfx が正しいことを確認するにはどうすればよいですか? (certutil.exeでインストールしようとする以外に?

              AsymmetricKeyParameter caPrivateKey = null;
      
          try
          {
              // Create Root CA certificate
              X509Certificate2 x509 = CertMaker.GenerateCACertificate(mSubject, ref caPrivateKey);
      
              // Save certificate to file
              byte[] certBytes = x509.Export(X509ContentType.Cert, mRootCaPwd);
              string certFilePath = Path.Combine(mInstallPath, mSubject + ".cer");
              File.WriteAllBytes(certFilePath, certBytes);
          }
          catch(Exception ex)
          {
              Log.Verbose(ex);
              TextLog.Info("Failed to generate CA Root Certificate");
              return;
          }
      
          if (caPrivateKey == null)
          {
              Log.Verbose("Failed to generate CA Root Certificate: Failed to generate private key.");
              TextLog.Info("Failed to generate CA Root Certificate: Failed to generate private key.");
              return;
          }
          try
          {
              X509Certificate2 cert = CertMaker.GenerateSelfSignedCertificate(mSubject, mIssuer, caPrivateKey);
      
              // Save certificate to file
              byte[] certBytes = cert.Export(X509ContentType.Pkcs12, mComputerCertPwd);
              string filename = String.Format("MyServer_{0}.pfx", mSubject);
              string certFilePath = Path.Combine(mInstallPath, filename);
              File.WriteAllBytes(certFilePath, certBytes);
          }
          catch(Exception ex)
          {
              Log.Verbose("Failed to generate Machine Certificate." + ex.Message);
              TextLog.Info("Failed to generate Machine Certificate.");
          }
      

および関数の実装:

       public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey, int keyStrength = 4096)
    {
        using (Log.VerboseCall())
        {
            try
            {
                // Generating Random Numbers
                var randomGenerator = new CryptoApiRandomGenerator();
                var random = new SecureRandom(randomGenerator);
                Log.Verbose("Generated Random Numbers");

                ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerPrivKey, random);
                Log.Verbose("Generated SignatureFactory");

                // The Certificate Generator
                var certificateGenerator = new X509V3CertificateGenerator();
                certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, true, new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth));

                // Serial Number
                var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
                certificateGenerator.SetSerialNumber(serialNumber);

                Log.Verbose("Added Serial Number to CertificateGenerator");

                // Issuer and Subject Name
                X509Name subjectDN = new X509Name("CN=" + subjectName);
                X509Name issuerDN = new X509Name("CN=" + issuerName);
                certificateGenerator.SetIssuerDN(issuerDN);
                certificateGenerator.SetSubjectDN(subjectDN);

                Log.Verbose("Had set Subject Name and Issuer Name");

                // Valid For
                var notBefore = DateTime.UtcNow.Date;
                var notAfter = notBefore.AddYears(100);

                certificateGenerator.SetNotBefore(notBefore);
                certificateGenerator.SetNotAfter(notAfter);

                // Subject Public Key
                AsymmetricCipherKeyPair subjectKeyPair;
                var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
                var keyPairGenerator = new RsaKeyPairGenerator();
                keyPairGenerator.Init(keyGenerationParameters);
                subjectKeyPair = keyPairGenerator.GenerateKeyPair();

                certificateGenerator.SetPublicKey(subjectKeyPair.Public);

                Log.Verbose("Had generated and set Subject Public Key");

                // Generating the Certificate
                var issuerKeyPair = subjectKeyPair;

                // NOTE #1
                // In another reference I saw this - instead
                //var dotNetPrivateKey = ToDotNetKey(privateKey);
                //var dotNetCert = new X509Certificate2(DotNetUtilities.ToX509Certificate(newCert));
                //dotNetCert.PrivateKey = dotNetPrivateKey;

                // self-signed certificate
                var certificate = certificateGenerator.Generate(signatureFactory);
                var dotNetPrivateKey = ToDotNetKey((RsaPrivateCrtKeyParameters)subjectKeyPair.Private);

                Log.Verbose("Generated Certificate");

                // correcponding private key
                PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);

                Log.Verbose("Created Private Key");

                // merge into X509Certificate2
                var x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

                Log.Verbose("Generated Encoded Certificate");

                var seq = (Asn1Sequence)Asn1Object.FromByteArray(info.ParsePrivateKey().GetDerEncoded());
                if (seq.Count != 9)
                    throw new PemException("Malformed sequence in RSA private key");

                RsaPrivateKeyStructure rsa = RsaPrivateKeyStructure.GetInstance(seq);
                RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(rsa.Modulus, rsa.PublicExponent,
                                                                                      rsa.PrivateExponent, rsa.Prime1,
                                                                                      rsa.Prime2, rsa.Exponent1,
                                                                                      rsa.Exponent2, rsa.Coefficient);

                Log.Verbose("Generated RSA Key Parameters");

                x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
                Log.Verbose("Had set CA Private Key");

                return x509;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to create Self-Signed Machine certificate: {0}", ex.Message);
                return null;
            }
        }
    }

    /// <summary>
    /// Generate Self-Signed Root CA Certificate
    /// </summary>
    /// <param name="subjectName"></param>
    /// <param name="CaPrivateKey"></param>
    /// <returns>Returns the X509 certificate and reference to Root CA Private Key</returns>
    public static X509Certificate2 GenerateCACertificate(string subjectName, ref AsymmetricKeyParameter CaPrivateKey)
    {
        using (Log.VerboseCall())
        {
            try
            {
                int keyStrength = 4096;

                // Generating Random Numbers
                CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
                SecureRandom random = new SecureRandom(randomGenerator);

                Log.Verbose("Generated Random Numbers");

                // The Certificate Generator
                X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();

                // Serial Number
                BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
                certificateGenerator.SetSerialNumber(serialNumber);

                Log.Verbose("Added Serial Number to CertificateGenerator");

                // Issuer and Subject Name
                X509Name subjectDN = new X509Name("CN="+subjectName);
                X509Name issuerDN = subjectDN;
                certificateGenerator.SetIssuerDN(issuerDN);
                certificateGenerator.SetSubjectDN(subjectDN);

                Log.Verbose("Had set Subject Name and Issuer Name");

                // Valid For
                var notBefore = DateTime.UtcNow.Date;
                var notAfter = notBefore.AddYears(100);

                certificateGenerator.SetNotBefore(notBefore);
                certificateGenerator.SetNotAfter(notAfter);

                // Subject Public Key
                AsymmetricCipherKeyPair subjectKeyPair;
                var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
                var keyPairGenerator = new RsaKeyPairGenerator();
                keyPairGenerator.Init(keyGenerationParameters);
                subjectKeyPair = keyPairGenerator.GenerateKeyPair();

                certificateGenerator.SetPublicKey(subjectKeyPair.Public);

                Log.Verbose("Had generated and set Subject Public Key");

                // Generating the Certificate
                AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
                ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerKeyPair.Private, random);

                Log.Verbose("Created SignatureFactory");

                // selfsign certificate
                // certificateGenerator.Generate signs the certificate using the private key, 
                // but doesn't put the private key in the certificate, which wouldn't make sense.
                Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(signatureFactory);
                X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

                Log.Verbose("Generated CA Root Certificate");

                CaPrivateKey = issuerKeyPair.Private;

                Log.Verbose("Had set CA Private Key");

                return x509;
            }
            catch (Exception ex)
            {
                Log.VerboseFormat("Failed to create Root CA certificate: {0}", ex.Message);
                return null;
            }
        }
    }

    /// <summary>
    /// See NOTE #1
    /// </summary>
    /// <param name="privateKey"></param>
    /// <returns></returns>
    public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
    {
        // If you don't do this (cspParams), when you execute the netsh command you get the error 1312. i.e. of the netsh command:
        //
        // netsh http add sslcert ipport = 192.168.0.15:8081 certhash =‎5424476237fc2785ed2d0fd620a9131d7c999f6f appid = { 02639d71 - 0935 - 35e8 - 9d1b - 9dd1a2a34627 }

        var cspParams = new CspParameters
        {
            KeyContainerName = Guid.NewGuid().ToString(),
            KeyNumber = (int)KeyNumber.Exchange,
            Flags = CspProviderFlags.UseMachineKeyStore
        };

        var rsaProvider = new RSACryptoServiceProvider(cspParams);
        var 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;
    }
4

0 に答える 0