3 Commits de1e18d28e ... a0c0837fe3

Auteur SHA1 Bericht Datum
  shayne_lo a0c0837fe3 update for rca 4 maanden geleden
  shayne_lo e6cfb0721d add key constraint 4 maanden geleden
  shayne_lo c6fa4d1142 fix chain certificate order 4 maanden geleden

+ 16 - 0
CAUtilLib/AddExtensionData.cs

@@ -0,0 +1,16 @@
+using Org.BouncyCastle.Asn1;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CAUtilLib
+{
+    public class AddExtensionData
+    {
+        public string OID { get; set; }
+        public bool Critical { get; set; }
+        public Asn1Encodable ExtensionValue { get; set; }
+    }
+}

+ 91 - 23
CAUtilLib/BouncyCastleWrapper.cs

@@ -17,6 +17,7 @@ using System.Text;
 using System.Threading.Tasks;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.OpenSsl;
+using static System.Runtime.InteropServices.JavaScript.JSType;
 
 namespace CAUtilLib
 {
@@ -50,7 +51,7 @@ namespace CAUtilLib
             AsymmetricCipherKeyPair issuerKey,
             AsymmetricKeyParameter subjectPublic,
             BigInteger? issuerSerialNumber = null,
-            bool isCertificateAuthority = false)
+            List<AddExtensionData> extensionDatas = null)
         {
             var selfserilaNumber = BigInteger.ProbablePrime(120, secureRandom);
             if (issuerSerialNumber is null)
@@ -60,9 +61,11 @@ namespace CAUtilLib
 
             ISignatureFactory signatureFactory;
             signatureFactory = new Asn1SignatureFactory(
-                PkcsObjectIdentifiers.Sha512WithRsaEncryption.ToString(),
+                PkcsObjectIdentifiers.Sha256WithRsaEncryption.ToString(),
                 issuerKey.Private);
-            signatureFactory = new Asn1SignatureFactory(PkcsObjectIdentifiers.Sha512WithRsaEncryption.ToString(), issuerKey.Private);
+            //signatureFactory = new Asn1SignatureFactory(
+            //    PkcsObjectIdentifiers.Sha512WithRsaEncryption.ToString(),
+            //    issuerKey.Private);
 
             var certGenerator = new X509V3CertificateGenerator();
             certGenerator.SetIssuerDN(issuer);
@@ -84,24 +87,32 @@ namespace CAUtilLib
                     )
                 );
 
-            if (isCertificateAuthority)
+            if (extensionDatas != null)
             {
-                certGenerator.AddExtension(X509Extensions.BasicConstraints.Id, true,
-                    new BasicConstraints(0));
-                //certGenerator.AddExtension(X509Extensions.KeyUsage.Id, true,
-                //    new KeyUsage(KeyUsage.KeyCertSign));
+                foreach (var data in extensionDatas)
+                {
+                    certGenerator.AddExtension(data.OID, data.Critical, data.ExtensionValue);
+                }
             }
 
+            //if (isCertificateAuthority)
+            //{
+            //    certGenerator.AddExtension(X509Extensions.BasicConstraints.Id, true,
+            //        new BasicConstraints(0));
+            //    certGenerator.AddExtension(X509Extensions.KeyUsage.Id, true,
+            //        new KeyUsage(KeyUsage.KeyCertSign));
+            //}
+
             return certGenerator.Generate(signatureFactory);
         }
 
         public static bool ValidateCertificateChain(List<X509Certificate> certificates)
         {
-            for (int index = certificates.Count - 1; index > 0; index--)
+            for (int index = 0; index < certificates.Count - 1; index++)
             {
-                var signedCertificate = certificates[index];
-                var sourceCertificate = certificates[index - 1];
-                if (!ValidateCert(signedCertificate, sourceCertificate.GetPublicKey()))
+                var validateCertificate = certificates[index];
+                var sourceCertificate = certificates[index + 1]; 
+                if (!ValidateCert(validateCertificate, sourceCertificate.GetPublicKey()))
                 {
                     return false;
                 }
@@ -116,11 +127,11 @@ namespace CAUtilLib
                 return false;
             }
 
-            for (int index = certChain.Count - 1; index > -1; index--)
+            for (int index = 0; index < certChain.Count; index++)
             {
-                var signedCertificate = cert;
+                var validateCertificate = cert;
                 var sourceCertificate = certChain[index];
-                if (ValidateCert(signedCertificate, sourceCertificate.GetPublicKey()))
+                if (ValidateCert(validateCertificate, sourceCertificate.GetPublicKey()))
                 {
                     return true;
                 }
@@ -153,21 +164,78 @@ namespace CAUtilLib
             }
         }
 
-        public static X509Certificate GenerateSelfSignedCertificate(AsymmetricCipherKeyPair kp, string commonName = "Zerova")
+        public static X509Certificate GenerateSelfSignedRootCertificate(
+            X509Name subject,
+            AsymmetricCipherKeyPair kp
+            )
         {
-            //var certName = new X509Name("CN=" + commomName);
-            var certName = CreateX509Name(commonName: commonName);
-            return GenerateCertificate(certName, certName, kp, kp.Public, isCertificateAuthority: true);
+            List<AddExtensionData> datas = new List<AddExtensionData>() { 
+                new AddExtensionData(){
+                    OID = X509Extensions.BasicConstraints.Id,
+                    Critical = true,
+                    ExtensionValue = new BasicConstraints(true)
+                },
+                new AddExtensionData()
+                {
+                    OID= X509Extensions.KeyUsage.Id,
+                    Critical = true,
+                    ExtensionValue = new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyCertSign | KeyUsage.CrlSign)
+                }
+            };
+            return GenerateCertificate(subject, subject, kp, kp.Public, extensionDatas: datas);
+        }
+
+        public static X509Certificate GenerateIntermediateCertificate(
+            Pkcs10CertificationRequest csr,
+            X509Certificate rca,
+            AsymmetricCipherKeyPair issuerKey,
+            int pathLengthConstraint
+            )
+        {
+            var csrInfo = csr.GetCertificationRequestInfo();
+
+            List<AddExtensionData> datas = new List<AddExtensionData>() {
+                new AddExtensionData(){
+                    OID = X509Extensions.BasicConstraints.Id,
+                    Critical = true,
+                    ExtensionValue = new BasicConstraints(pathLengthConstraint)
+                },
+                new AddExtensionData()
+                {
+                    OID= X509Extensions.KeyUsage.Id,
+                    Critical = true,
+                    ExtensionValue = new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyCertSign | KeyUsage.CrlSign)
+                }
+            };
+            return GenerateCertificate(rca.SubjectDN, csrInfo.Subject, issuerKey, csr.GetPublicKey(), extensionDatas: datas);
+        }
+
+        public static X509Certificate GenerateEndCertificate(
+            Pkcs10CertificationRequest csr,
+            X509Certificate rca,
+            AsymmetricCipherKeyPair issuerKey
+            )
+        {
+            var csrInfo = csr.GetCertificationRequestInfo();
+
+            List<AddExtensionData> datas = new List<AddExtensionData>() {
+                new AddExtensionData()
+                {
+                    OID= X509Extensions.KeyUsage.Id,
+                    Critical = true,
+                    ExtensionValue = new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.NonRepudiation | KeyUsage.KeyEncipherment)
+                }
+            };
+            return GenerateCertificate(rca.SubjectDN, csrInfo.Subject, issuerKey, csr.GetPublicKey(), extensionDatas: datas);
         }
 
         public static X509Certificate SignCertificate(
             Pkcs10CertificationRequest csr,
             X509Certificate rca, 
-            AsymmetricCipherKeyPair issuerKey,
-            bool isCertificateAuthority = false)
+            AsymmetricCipherKeyPair issuerKey)
         {
             var csrInfo = csr.GetCertificationRequestInfo();
-            return GenerateCertificate(rca.SubjectDN, csrInfo.Subject, issuerKey, csr.GetPublicKey(), issuerSerialNumber: rca.SerialNumber, isCertificateAuthority: isCertificateAuthority);
+            return GenerateCertificate(rca.SubjectDN, csrInfo.Subject, issuerKey, csr.GetPublicKey(), issuerSerialNumber: rca.SerialNumber);
         }
 
         public static Pkcs10CertificationRequest CreateCertificateReq(AsymmetricCipherKeyPair kp, string commonName, string organizationName)
@@ -175,7 +243,7 @@ namespace CAUtilLib
             var subject = CreateX509Name(commonName: commonName, organizationName: organizationName);
 
             var csr = new Pkcs10CertificationRequest(
-                PkcsObjectIdentifiers.Sha512WithRsaEncryption.ToString(),
+                PkcsObjectIdentifiers.Sha256WithRsaEncryption.ToString(),
                 subject,
                 kp.Public,
                 null,

+ 2 - 1
CAUtilLib/CAUtil.cs

@@ -31,7 +31,8 @@ namespace CAUtilLib
                 return false;
             }
 
-            X509Certificate cert = BouncyCastleWrapper.GenerateSelfSignedCertificate(kp);
+            var subject = BouncyCastleWrapper.CreateX509Name(commonName: "Zerova");
+            X509Certificate cert = BouncyCastleWrapper.GenerateSelfSignedRootCertificate(subject, kp);
             var saveCertResult = await BouncyCastleWrapper.TrySaveAsPemAsync(RcaCertPath, new object[] { cert, kp.Private });
             if (!saveCertResult)
             {

+ 1 - 1
CertificateAutorityServer/Controllers/Rca/RcaController.cs

@@ -25,7 +25,7 @@ namespace CertificateAutorityServer.Controllers.Rca
         public async Task<IActionResult> ReqCsrSign(SignCsrReq signCsrReq)
         {
             var result = await certificateService.SignCsrByRca(signCsrReq);
-            return Ok(result);
+            return string.IsNullOrEmpty(result) ? BadRequest() : Ok(result);
         }
 
         [HttpPost("check")]

+ 11 - 2
CertificateAutorityServer/Controllers/RootController.cs

@@ -34,7 +34,8 @@ namespace CertificateAutorityServer.Controllers
             {
                 return BadRequest("key parse failed");
             }
-            var cert = BouncyCastleWrapper.GenerateCertificate(subject, subject, key, key.Public , isCertificateAuthority: true);
+            //var cert = BouncyCastleWrapper.GenerateCertificate(subject, subject, key, key.Public);
+            var cert = BouncyCastleWrapper.GenerateSelfSignedRootCertificate(subject, key);
             if (cert is null)
             {
                 return BadRequest("certificate create failed");
@@ -56,7 +57,15 @@ namespace CertificateAutorityServer.Controllers
             var csr = BouncyCastleWrapper.LoadPemCsrFromString(signCsrReq.Csr);
             var rca = BouncyCastleWrapper.LoadPemCertFromString(signCsrReq.Rca);
             var key = BouncyCastleWrapper.LoadPemKeyFromString(signCsrReq.RcaKey);
-            var crt = BouncyCastleWrapper.SignCertificate(csr, rca, key , isCertificateAuthority: signCsrReq.IsCa);
+            Org.BouncyCastle.X509.X509Certificate crt;
+            if (signCsrReq.IsCa)
+            {
+                crt = BouncyCastleWrapper.GenerateIntermediateCertificate(csr, rca, key, 0);
+            }
+            else
+            {
+                crt = BouncyCastleWrapper.GenerateEndCertificate(csr, rca, key);
+            }
             var crtString = await BouncyCastleWrapper.ToStringAsPem(crt);
             return Ok(crtString);
         }

+ 2 - 2
CertificateAutorityServer/Model/Rest/SignCsrReq.cs

@@ -3,8 +3,8 @@
     public class SignCsrReq
     {
         public required string Csr { get; set; }
-        public required string Rca { get; set; }
-        public required string RcaKey { get; set; }
+        public string Rca { get; set; }
+        public string RcaKey { get; set; }
         public bool IsCa { get; set; } = false;
         //public required string Name { get; set; }
         //public IFormFile? CsrFile { get; set; }

+ 6 - 3
CertificateAutorityServer/Service/CertificateService.cs

@@ -47,14 +47,16 @@ namespace CertificateAutorityServer.Service
             {
                 AsymmetricCipherKeyPair kp = BouncyCastleWrapper.GenerateRsaKeyPair(4096);
                 var saveKeyResult = BouncyCastleWrapper.TrySaveAsPemAsync(RcaKeyPath, new object[] { kp.Private }).Result;
-                X509Certificate cert = BouncyCastleWrapper.GenerateSelfSignedCertificate(kp);
+                var subject = BouncyCastleWrapper.CreateX509Name(commonName: "Zerova");
+                X509Certificate cert = BouncyCastleWrapper.GenerateSelfSignedRootCertificate(subject, kp);
                 var saveCertResult = BouncyCastleWrapper.TrySaveAsPemAsync(RcaCertPath, new object[] { cert, kp.Private }).Result;
                 return;
             }
             if (!File.Exists(RcaCertPath))
             {
                 var kp = BouncyCastleWrapper.LoadPemKeyFromFile(RcaKeyPath).Result;
-                var cert = BouncyCastleWrapper.GenerateSelfSignedCertificate(kp, config.DefaultRcaConfig.CommonName);
+                var subject = BouncyCastleWrapper.CreateX509Name(commonName: config.DefaultRcaConfig.CommonName);
+                var cert = BouncyCastleWrapper.GenerateSelfSignedRootCertificate(subject, kp);
                 var saveCertResult = BouncyCastleWrapper.TrySaveAsPemAsync(RcaCertPath, new object[] { cert, kp.Private }).Result;
             }
         }
@@ -83,7 +85,8 @@ namespace CertificateAutorityServer.Service
             var cert = await BouncyCastleWrapper.LoadPemCertFromFile(RcaKeyPath);
             var rcaKey = await BouncyCastleWrapper.LoadPemKeyFromFile(RcaKeyPath);
             var csr = BouncyCastleWrapper.LoadPemCsrFromString(signCsrReq.Csr);
-            var singedCert = BouncyCastleWrapper.SignCertificate(csr, cert, rcaKey);
+            //var singedCert = BouncyCastleWrapper.SignCertificate(csr, cert, rcaKey);
+            var singedCert = BouncyCastleWrapper.GenerateEndCertificate(csr, cert, rcaKey);
             return await BouncyCastleWrapper.ToStringAsPem(singedCert);
         }