public void CalculateSignatureShouldSucceed()
        {
            // The certificate should exist in the certificate store
            // on LocalMachine in CA store with appropriate subject CN
            // as it is defined in with the given "issuerSubject".
            // This certificate should have an associated private key that may not be exportable.
            const string issuerSubject = "L2";

            var privateKey = new PksEcPrivateKey(
                issuerSubject,
                "CA",
                "LocalMachine");

            const string algorithm = "SHA256withECDSA";

            ISignatureFactory signatureFactory = new PksAsn1SignatureFactory(algorithm, privateKey);

            // example of hash, real hash will be a longer byte array
            byte[] hash = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };


            IStreamCalculator calculator = signatureFactory.CreateCalculator();

            using (var stream = calculator.Stream)
            {
                stream.Write(hash, 0, hash.Length);
            }

            object result = calculator.GetResult();

            byte[] signature = ((IBlockResult)result).Collect();  // ASN.1 DER formatted signature

            Assert.IsNotNull(signature);
        }
        public void CreateCertificateShouldSucceed()
        {
            // some public key in base64 DER encoded, that will be used as public key of the new certificate,
            // it should be ECDSA with SHA256 for this example, since the signing Certificate is also ECDSA with SHA256 (OID 1.2.840.10045.4.3.2)
            const string publicKey = @"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhpFTpKgGDqfxSwp9WlPJMa2o3XR5x1xKAgC4CR2AFbSzGFAjCIkUKtBCUrA5Te6ydhxVduA3JFE2hzqy/6V6qA==";

            // The certificate should exist in the certificate store
            // on LocalMachine in CA store with appropriate subject CN
            // as it is defined in with the given "issuerSubject".
            // This certificate should have an associated private key that may not be exportable.
            const string issuerSubject = "L2";

            var privateKey = new PksEcPrivateKey(
                issuerSubject,
                "CA",
                "LocalMachine");

            const string algorithm = "SHA256withECDSA";

            ISignatureFactory signatureFactory = new PksAsn1SignatureFactory(algorithm, privateKey);


            // signatureCalculatorFactory can be used for generating a new certificate with BouncyCastle
            var certificateGenerator = new X509V3CertificateGenerator();

            // ... set all other required fields of the X509V3CertificateGenerator
            certificateGenerator.SetSerialNumber(BigInteger.One);
            certificateGenerator.SetIssuerDN(ToX509Name(issuerSubject));
            certificateGenerator.SetSubjectDN(ToX509Name("My-new-cert", "My-org"));

            certificateGenerator.SetPublicKey(
                PublicKeyFactory.CreateKey(
                    SubjectPublicKeyInfo.GetInstance(Convert.FromBase64String(publicKey))));
            certificateGenerator.SetNotBefore(DateTime.Now.Subtract(TimeSpan.FromMinutes(10)));

            certificateGenerator.SetNotAfter(DateTime.Now.Add(TimeSpan.FromDays(14)));

            // finally run the generator for a new certificate:
            X509Certificate cert = certificateGenerator.Generate(signatureFactory);

            Assert.IsNotNull(cert);
        }
        public X509Certificate CreateCertificate(CertificateDefinition definition)
        {
            var randomGenerator = new CryptoApiRandomGenerator();

            BigInteger serialNumber = CreateSerialNumber(randomGenerator);


            if (definition.SigningCertificate == null)
            {
                throw new CertificateIssuerException("Cannot create certificate without signing certificate (null).");
            }

            (AsymmetricCipherKeyPair caKeyPair, X509Name issuer) = GetSigningKeyPair(definition.SigningCertificate);

            var publicKeyForNewCert = PublicKeyFactory.CreateKey(definition.PublicKey);

            var certGen = new X509V3CertificateGenerator();

            certGen.SetSerialNumber(serialNumber);
            certGen.SetIssuerDN(issuer);
            certGen.SetSubjectDN(definition.Subject);
            certGen.SetPublicKey(publicKeyForNewCert);

            var now = DateTime.Now;

            certGen.SetNotBefore(now.Subtract(new TimeSpan(0, 0, 10, 0))); // start 10 min before now

            // add max 2 weeks from now but not more then L2 expiration date
            var certExpirationDate         = now.Add(definition.ExpireIn);
            var signingCertificateNotAfter = definition.SigningCertificate.NotAfter;

            if (signingCertificateNotAfter < now)
            {
                throw new CertificateIssuerException(
                          "Cannot create derived certificate because signing certificate already expired. Signing certificate subject name: " +
                          definition.SigningCertificate?.SubjectName.Name);
            }

            if (certExpirationDate > signingCertificateNotAfter)
            {
                certExpirationDate = signingCertificateNotAfter;
            }

            certGen.SetNotAfter(certExpirationDate);


            // certGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));

            AddExtensionSubjectKeyIdentifier(certGen, publicKeyForNewCert);

            AddExtensionAuthorityKeyIdentifier(certGen, caKeyPair);

            AddExtensionSubjectAltNames(certGen, definition.SubjectAltNames);

            // var s = @"file:////my-CA.com/CertEnroll/my-CA.com_my-Dev%20L2%20CA.crt";
            // AddExtensionAuthorityInfo(certGen, s);

            // string certificateTemplateExtension = "IPSECIntermediateOffline";
            // AddExtensionCertificateTemplateName(certGen, certificateTemplateExtension);

            // var crl = @"file:////my-CA.com/CertEnroll/my-Dev%20L2%20CA.crl";
            // AddExtensionCrlDistributionPoints(certGen, crl);

            // other supported algorithms:

            /* SHA1withECDSA
             * SHA224withECDSA
             * SHA256withECDSA
             * SHA384withECDSA
             * SHA512withECDSA
             * NONEwithECDSA
             */
            const string algorithm = "SHA256WITHECDSA";

            // This is the most interesting part where we use our custom signature factory that utilizes
            // the custom private key PksEcPrivateKey
            ISignatureFactory signatureFactory =
                new PksAsn1SignatureFactory(algorithm, caKeyPair.Private, new SecureRandom(randomGenerator));

            X509Certificate cert = certGen.Generate(signatureFactory);

            return(cert);
        }