public static void ReproduceBigExponentCsr()
        {
            X509Extension sanExtension = new X509Extension(
                "2.5.29.17",
                "302387047F00000187100000000000000000000000000000000182096C6F63616C686F7374".HexToByteArray(),
                false);

            byte[] autoCsr;
            byte[] csr;
            string csrPem;
            string autoCsrPem;

            using (RSA rsa = RSA.Create())
            {
                rsa.ImportParameters(TestData.RsaBigExponentParams);

                CertificateRequest request = new CertificateRequest(
                    "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
                    rsa,
                    HashAlgorithmName.SHA256,
                    RSASignaturePadding.Pkcs1);

                request.CertificateExtensions.Add(sanExtension);

                autoCsr    = request.CreateSigningRequest();
                autoCsrPem = request.CreateSigningRequestPem();

                X509SignatureGenerator generator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1);
                csr    = request.CreateSigningRequest(generator);
                csrPem = request.CreateSigningRequestPem(generator);
            }

            AssertExtensions.SequenceEqual(TestData.BigExponentPkcs10Bytes, autoCsr);
            AssertExtensions.SequenceEqual(TestData.BigExponentPkcs10Bytes, csr);
            Assert.Equal(TestData.BigExponentPkcs10Pem, autoCsrPem);
            Assert.Equal(TestData.BigExponentPkcs10Pem, csrPem);
        }
        public static void CreateSigningRequestWithAttributes(bool reversed)
        {
            // Generated by `openssl req -new -keyin bigexponent.pem` where bigexponent.pem
            // represents the PKCS8 of TestData.RsaBigExponentParams
            // All default values were taken, except
            // Challenge password: 1234 (vs unspecified)
            // An optional company name: Fabrikam (vs unspecified)
            const string ExpectedPem =
                "-----BEGIN CERTIFICATE REQUEST-----\n" +
                "MIICujCCAaICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx\n" +
                "ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASQwDQYJKoZIhvcN\n" +
                "AQEBBQADggERADCCAQwCggEBAK+BwcvYID9iSlOe1mCBdTcjk6KDfUiQ5IoZ3tNp\n" +
                "cxFWIJaNa+DT2qOKp3e+Au4La5O3JOjcwStjK0+oC7ySW85iT0ynzGBjBrOUA+KM\n" +
                "ky0k3VRv/k72o38QdwsiFeqMu1v0J+jE2Jt56zODdRAMX4PlXem0Rm3fvu5CU5rv\n" +
                "M+8Ye3dgw7GhshA8LYFEVkoMEDmgnIXPa1l061FvyNZiPJSuOloLs7THkpV9QyOR\n" +
                "Vmzz4qUq+wwUK54GgbiXJnGvK4LdOQo5uTnPcZVoaH5JkKYwUMp3aNzWs3iELxj9\n" +
                "sfbZ/wlrr3vrmNz5MNZvz9UD9Y1Bv/RiEuJOOvxF6kK9iEcCBQIAAARBoC4wEwYJ\n" +
                "KoZIhvcNAQkHMQYMBDEyMzQwFwYJKoZIhvcNAQkCMQoMCEZhYnJpa2FtMA0GCSqG\n" +
                "SIb3DQEBCwUAA4IBAQCr1X8D+ZkJqBmuZVEYqLPvNvie+KBycxgiJ08ZaV/dyndZ\n" +
                "cudn6G9K0hiIwwGrfI5gbIb7QdPi64g3l9VdIrdH3yvQ6AcOZ644paiUUpe3u93l\n" +
                "DTY+BGN7C0reJwL7ehalIrtS7hLKAQerg/qS7JO9aLRTbIXR52BQIUs9htYeATC5\n" +
                "VHHssrOZpIHqIN4oaZbE0BwZm0ap6RVD80Oexko8pjiz9XNmtUWadeXXtezuOWTb\n" +
                "duuJlh31kITIrbWVoMawMRq6JwNTPAFyiDMB/EFIvjxpUoS5yJe14bT8Hw2XvAFK\n" +
                "Z9jOhHEPmAsasfRRSwr6CXyIKqo1HVT1ARPgHKHX\n" +
                "-----END CERTIFICATE REQUEST-----";

            string builtPem;

            using (RSA key = RSA.Create(TestData.RsaBigExponentParams))
            {
                X500DistinguishedNameBuilder nameBuilder = new();
                nameBuilder.AddOrganizationName("Internet Widgits Pty Ltd");
                nameBuilder.AddStateOrProvinceName("Some-State");
                nameBuilder.AddCountryOrRegion("AU");

                CertificateRequest req = new CertificateRequest(
                    nameBuilder.Build(),
                    key,
                    HashAlgorithmName.SHA256,
                    RSASignaturePadding.Pkcs1);

                // Unstructured Name: UTF8String("Fabrikam")
                AsnEncodedData unstructuredNameAttr = new AsnEncodedData(
                    new Oid("1.2.840.113549.1.9.2", null),
                    "0C0846616272696B616D".HexToByteArray());

                // ChallengePassword
                AsnEncodedData cpAttr = new AsnEncodedData(
                    new Oid("1.2.840.113549.1.9.7", null),
                    "0C0431323334".HexToByteArray());

                // Request attributes are in a SET OF, which means they get sorted.
                // So both orders here produce the same output.
                if (reversed)
                {
                    req.OtherRequestAttributes.Add(unstructuredNameAttr);
                    req.OtherRequestAttributes.Add(cpAttr);
                }
                else
                {
                    req.OtherRequestAttributes.Add(cpAttr);
                    req.OtherRequestAttributes.Add(unstructuredNameAttr);
                }

                builtPem = req.CreateSigningRequestPem();
            }

            Assert.Equal(ExpectedPem, builtPem);
        }
        public static void CreateSigningRequestWithDuplicateAttributes(bool reversed)
        {
            const string ExpectedPem =
                "-----BEGIN CERTIFICATE REQUEST-----\n" +
                "MIIC/TCCAeUCAQAwgYoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u\n" +
                "MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp\n" +
                "b24xIDAeBgNVBAsTFy5ORVQgRnJhbWV3b3JrIChDb3JlRlgpMRIwEAYDVQQDEwls\n" +
                "b2NhbGhvc3QwggEkMA0GCSqGSIb3DQEBAQUAA4IBEQAwggEMAoIBAQCvgcHL2CA/\n" +
                "YkpTntZggXU3I5Oig31IkOSKGd7TaXMRViCWjWvg09qjiqd3vgLuC2uTtyTo3MEr\n" +
                "YytPqAu8klvOYk9Mp8xgYwazlAPijJMtJN1Ub/5O9qN/EHcLIhXqjLtb9CfoxNib\n" +
                "eeszg3UQDF+D5V3ptEZt377uQlOa7zPvGHt3YMOxobIQPC2BRFZKDBA5oJyFz2tZ\n" +
                "dOtRb8jWYjyUrjpaC7O0x5KVfUMjkVZs8+KlKvsMFCueBoG4lyZxryuC3TkKObk5\n" +
                "z3GVaGh+SZCmMFDKd2jc1rN4hC8Y/bH22f8Ja69765jc+TDWb8/VA/WNQb/0YhLi\n" +
                "Tjr8RepCvYhHAgUCAAAEQaArMBMGCSqGSIb3DQEJBzEGDAQxMjM0MBQGCSqGSIb3\n" +
                "DQEJBzEHDAUxMjM0NTANBgkqhkiG9w0BAQsFAAOCAQEAB3lwd8z6XGmX6mbOo3Xm\n" +
                "+ZyW4glQtJ51FAXA1zy83y5Uqyf85ZtTFl6UPw970x8KlSlY/9eMhyo/LORAwQql\n" +
                "J8oga5ho2clJF62IJX9/Ih6JlmcMfyi9qEQaqsY/Og4IBSvxQo39SGzGFLv9mhxa\n" +
                "R1YWoVggsbs638ph/T8Upz/GKb/0tBnGBThRZJip7HLugzzvSJGnirpp0fZhnwWM\n" +
                "l1IlddN5/AdZ86j/r5RNlDKDHlwqI3UJ5Olb1iVFt00d/vwVRM09V1ZNIpiCmPv6\n" +
                "MJG3L+NUKOpSUDXn9qtCxB0pd1MaZVit5EvJI98sKZhILRz3S5KXTxf+kBjNxC98\n" +
                "AQ==\n" +
                "-----END CERTIFICATE REQUEST-----";

            string output;

            using (RSA key = RSA.Create(TestData.RsaBigExponentParams))
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
                    key,
                    HashAlgorithmName.SHA256,
                    RSASignaturePadding.Pkcs1);

                // 1234
                AsnEncodedData cpAttr1 = new AsnEncodedData(
                    new Oid("1.2.840.113549.1.9.7", null),
                    "0C0431323334".HexToByteArray());

                // 12345
                AsnEncodedData cpAttr2 = new AsnEncodedData(
                    new Oid("1.2.840.113549.1.9.7", null),
                    "0C053132333435".HexToByteArray());

                if (reversed)
                {
                    req.OtherRequestAttributes.Add(cpAttr2);
                    req.OtherRequestAttributes.Add(cpAttr1);
                }
                else
                {
                    req.OtherRequestAttributes.Add(cpAttr1);
                    req.OtherRequestAttributes.Add(cpAttr2);
                }

                // ChallengePassword is defined as SINGLE VALUE TRUE,
                // so if we understood it as a rich concept we would block it.
                // But, we don't, so this problem gets passed on to the entity reading the request.
                output = req.CreateSigningRequestPem();
            }

            Assert.Equal(ExpectedPem, output);
        }