Exemple #1
0
        public PkiCertificate Sign(PkiEncodingFormat format, byte[] encodedCsr,
                                   PkiHashAlgorithm signingHashAlgorithm,
                                   DateTimeOffset?notBefore = null,
                                   DateTimeOffset?notAfter  = null)
        {
            var csr = new PkiCertificateSigningRequest(format, encodedCsr, signingHashAlgorithm);

            return(Sign(csr, notBefore, notAfter));
        }
Exemple #2
0
        // [DataRow(PkiAsymmetricAlgorithm.Ecdsa, 256, PkiEncodingFormat.Pem)]
        public void ExportImportCsr(PkiAsymmetricAlgorithm algor, int bits, PkiEncodingFormat format)
        {
            var hashAlgor = PkiHashAlgorithm.Sha256;

            var sn   = "CN=foo.example.com";
            var sans = new[] {
                "foo-alt1.example.com",
                "foo-alt2.example.com",
            };
            var keys = PkiKeyTests.GenerateKeyPair(algor, bits);
            var csr  = new PkiCertificateSigningRequest(sn, keys, hashAlgor);

            csr.CertificateExtensions.Add(
                PkiCertificateExtension.CreateDnsSubjectAlternativeNames(sans));

            var saveOut = Path.Combine(_testTemp,
                                       $"csrexport-{algor}-{bits}-{hashAlgor}-sans.{format}");

            var encoding = csr.ExportSigningRequest(format);

            File.WriteAllBytes(saveOut, encoding);

            encoding = File.ReadAllBytes(saveOut);
            PkiCertificateSigningRequest csr2 = new PkiCertificateSigningRequest(format, encoding, hashAlgor);

            using (var ms = new MemoryStream())
            {
                csr2.Save(ms);
                File.WriteAllBytes(saveOut + 2, ms.ToArray());
            }

            // File.WriteAllBytes(saveOut + "1a.pem", csr.ExportSigningRequest(PkiEncodingFormat.Pem));
            // File.WriteAllBytes(saveOut + "1b.pem", csr.ExportSigningRequest(PkiEncodingFormat.Pem));
            // File.WriteAllBytes(saveOut + "2a.pem", csr2.ExportSigningRequest(PkiEncodingFormat.Pem));
            // File.WriteAllBytes(saveOut + "2b.pem", csr2.ExportSigningRequest(PkiEncodingFormat.Pem));

            Assert.AreEqual(csr.SubjectName, csr2.SubjectName);
            Assert.AreEqual(csr.HashAlgorithm, csr2.HashAlgorithm);
            CollectionAssert.AreEqual(
                csr.PublicKey.Export(PkiEncodingFormat.Der),
                csr2.PublicKey.Export(PkiEncodingFormat.Der));
            CollectionAssert.AreEqual(
                csr.CertificateExtensions,
                csr2.CertificateExtensions, CertExtComparerInstance);

            Assert.AreEqual(csr.PublicKey.IsPrivate, csr2.PublicKey.IsPrivate);
            Assert.AreEqual(csr.PublicKey.Algorithm, csr2.PublicKey.Algorithm);
            CollectionAssert.AreEqual(
                csr.PublicKey.Export(PkiEncodingFormat.Der),
                csr2.PublicKey.Export(PkiEncodingFormat.Der));
        }
Exemple #3
0
        public byte[] Export(PkiEncodingFormat format)
        {
            switch (format)
            {
            case PkiEncodingFormat.Pem:
                using (var sw = new StringWriter())
                {
                    var pemWriter = new PemWriter(sw);
                    pemWriter.WriteObject(NativeCertificate);
                    return(Encoding.UTF8.GetBytes(sw.GetStringBuilder().ToString()));
                }

            case PkiEncodingFormat.Der:
                return(NativeCertificate.GetEncoded());

            default:
                throw new NotSupportedException();
            }
        }
        /// <summary>
        /// Exports the key into a supported key format.
        /// </summary>
        public byte[] Export(PkiEncodingFormat format, char[] password = null)
        {
            switch (format)
            {
            case PkiEncodingFormat.Pem:
                using (var sw = new StringWriter())
                {
                    object pemObject = NativeKey;
                    if (IsPrivate && password != null)
                    {
                        var pkcs8Gen = new Pkcs8Generator(NativeKey,
                                                          Pkcs8Generator.PbeSha1_3DES);
                        pkcs8Gen.Password = password;
                        pemObject         = pkcs8Gen.Generate();
                    }
                    var pemWriter = new PemWriter(sw);
                    pemWriter.WriteObject(pemObject);
                    return(Encoding.UTF8.GetBytes(sw.GetStringBuilder().ToString()));
                }

            case PkiEncodingFormat.Der:
                if (IsPrivate)
                {
                    var keyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(NativeKey);
                    return(keyInfo.GetDerEncoded());
                }
                else
                {
                    var keyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(NativeKey);
                    return(keyInfo.GetDerEncoded());
                }

            default:
                throw new NotSupportedException();
            }
        }
Exemple #5
0
        public PkiCertificateSigningRequest(PkiEncodingFormat format, byte[] encoded,
                                            PkiHashAlgorithm hashAlgorithm)
        {
            Pkcs10CertificationRequest pkcs10;

            switch (format)
            {
            case PkiEncodingFormat.Pem:
                var encodedString = Encoding.UTF8.GetString(encoded);
                using (var sr = new StringReader(encodedString))
                {
                    var pemReader = new PemReader(sr);
                    pkcs10 = pemReader.ReadObject() as Pkcs10CertificationRequest;
                    if (pkcs10 == null)
                    {
                        throw new Exception("invalid PEM object is not PKCS#10 archive");
                    }
                }
                break;

            case PkiEncodingFormat.Der:
                pkcs10 = new Pkcs10CertificationRequest(encoded);
                break;

            default:
                throw new NotSupportedException();
            }

            var info            = pkcs10.GetCertificationRequestInfo();
            var nativePublicKey = pkcs10.GetPublicKey();
            var rsaKey          = nativePublicKey as RsaKeyParameters;
            var ecdsaKey        = nativePublicKey as ECPublicKeyParameters;

            if (rsaKey != null)
            {
                PublicKey = new PkiKey(nativePublicKey, PkiAsymmetricAlgorithm.Rsa);
            }
            else if (ecdsaKey != null)
            {
                PublicKey = new PkiKey(nativePublicKey, PkiAsymmetricAlgorithm.Ecdsa);
            }
            else
            {
                throw new NotSupportedException("unsupported asymmetric algorithm key");
            }
            SubjectName   = info.Subject.ToString();
            HashAlgorithm = hashAlgorithm;


            // // // Based on:
            // // //    http://forum.rebex.net/4284/pkcs10-certificate-request-example-provided-castle-working

            // // var extGen = new X509ExtensionsGenerator();
            // // foreach (var ext in CertificateExtensions)
            // // {
            // //     extGen.AddExtension(ext.Identifier, ext.IsCritical, ext.Value);
            // // }
            // // var attr = new AttributeX509(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest,
            // //         new DerSet(extGen.Generate()));


            // Based on:
            //    http://unitstep.net/blog/2008/10/27/extracting-x509-extensions-from-a-csr-using-the-bouncy-castle-apis/
            //    https://stackoverflow.com/q/24448909/5428506
            foreach (var attr in info.Attributes.ToArray())
            {
                if (attr is DerSequence derSeq && derSeq.Count == 2)
                {
                    var attrX509 = AttributeX509.GetInstance(attr);
                    if (object.Equals(attrX509.AttrType, PkcsObjectIdentifiers.Pkcs9AtExtensionRequest))
                    {
                        // The `Extension Request` attribute is present.
                        // The X509Extensions are contained as a value of the ASN.1 Set.
                        // Assume that it is the first value of the set.
                        if (attrX509.AttrValues.Count >= 1)
                        {
                            var csrExts = X509Extensions.GetInstance(attrX509.AttrValues[0]);
                            foreach (var extOid in csrExts.GetExtensionOids())
                            {
                                if (object.Equals(extOid, X509Extensions.SubjectAlternativeName))
                                {
                                    var ext    = csrExts.GetExtension(extOid);
                                    var extVal = ext.Value;
                                    var der    = extVal.GetDerEncoded();
                                    // The ext value, which is an ASN.1 Octet String, **MIGHT** be tagged with
                                    // a leading indicator that it's an Octet String and its length, so we want
                                    // to remove it if that's the case to extract the GeneralNames collection
                                    if (der.Length > 2 && der[0] == 4 && der[1] == der.Length - 2)
                                    {
                                        der = der.Skip(2).ToArray();
                                    }
                                    var asn1obj = Asn1Object.FromByteArray(der);
                                    var gnames  = GeneralNames.GetInstance(asn1obj);
                                    CertificateExtensions.Add(new PkiCertificateExtension
                                    {
                                        Identifier = extOid,
                                        IsCritical = ext.IsCritical,
                                        Value      = gnames,
                                    });
                                }
                            }

                            // No need to search any more.
                            break;
                        }
                    }
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Creates an ASN.1 DER-encoded PKCS#10 CertificationRequest object representing
        /// the current state of this CertificateRequest object.
        /// </summary>
        /// <returns>An ASN.1 DER-encoded certificate signing request.</returns>
        public byte[] ExportSigningRequest(PkiEncodingFormat format)
        {
            if (!HasPrivateKey)
            {
                throw new InvalidOperationException("cannot export CSR without a private key");
            }

            // Based on:
            //    https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/pkcs/test/PKCS10Test.cs
            //    https://stackoverflow.com/questions/46182659/how-to-delay-sign-the-certificate-request-using-bouncy-castle-with-ecdsa-signatu
            //    http://www.bouncycastle.org/wiki/display/JA1/X.509+Public+Key+Certificate+and+Certification+Request+Generation:
            //        #X.509PublicKeyCertificateandCertificationRequestGeneration-EllipticCurve(ECDSA)
            //        #X.509PublicKeyCertificateandCertificationRequestGeneration-RSA
            //        #X.509PublicKeyCertificateandCertificationRequestGeneration-CreatingCertificationRequests
            //    https://stackoverflow.com/a/37563051/5428506

            var x509name = new X509Name(SubjectName);
            var pubKey   = _keyPair.PublicKey.NativeKey;
            var prvKey   = _keyPair.PrivateKey.NativeKey;

            // Asn1Set attrSet = null;
            // if (CertificateExtensions.Count > 0)
            // {
            //     var certExts = CertificateExtensions.ToDictionary(
            //             ext => ext.Identifier, ext => ext.Value);
            //     var csrAttrs = new[]
            //     {
            //         new Org.BouncyCastle.Asn1.Cms.Attribute(
            //             PkcsObjectIdentifiers.Pkcs9AtExtensionRequest,
            //             new DerSet(new X509Extensions(certExts))),
            //     };
            //     attrSet = new DerSet(csrAttrs);
            // }

            // Based on:
            //    http://forum.rebex.net/4284/pkcs10-certificate-request-example-provided-castle-working

            var extGen = new X509ExtensionsGenerator();

            foreach (var ext in CertificateExtensions)
            {
                extGen.AddExtension(ext.Identifier, ext.IsCritical, ext.Value);
            }
            var attr = new AttributeX509(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest,
                                         new DerSet(extGen.Generate()));

            var sigFactory = ComputeSignatureAlgorithm(prvKey);
            var pkcs10     = new Pkcs10CertificationRequest(sigFactory, x509name,
                                                            pubKey, new DerSet(attr), prvKey);

            switch (format)
            {
            case PkiEncodingFormat.Pem:
                using (var sw = new StringWriter())
                {
                    var pemWriter = new PemWriter(sw);
                    pemWriter.WriteObject(pkcs10);
                    return(Encoding.UTF8.GetBytes(sw.GetStringBuilder().ToString()));
                }

            case PkiEncodingFormat.Der:
                return(pkcs10.GetDerEncoded());

            default:
                throw new NotSupportedException();
            }
        }