public override void ExportCsr(Csr csr, EncodingFormat fmt, Stream target)
        {
            string outform;

            switch (fmt)
            {
            case EncodingFormat.PEM:
                outform = "PEM";
                break;

            case EncodingFormat.DER:
                outform = "DER";
                break;

            default:
                throw new NotSupportedException("unsupported encoding format");
            }

            var ceReq = new CERTENROLLLib.CX509CertificateRequestCertificate();

            ceReq.InitializeDecode(csr.Pem);

            if (fmt == EncodingFormat.DER)
            {
                var bytes = EncodeRaw(ceReq.RawData[CERTENROLLLib.EncodingType.XCN_CRYPT_STRING_BINARY]);
                target.Write(bytes, 0, bytes.Length);
            }
            else if (fmt == EncodingFormat.PEM)
            {
                var ceCsr = new CERTENROLLLib.CX509Enrollment();
                ceCsr.InitializeFromRequest(ceReq);
                var pem = ceCsr.CreateRequest(
                    CERTENROLLLib.EncodingType.XCN_CRYPT_STRING_BASE64REQUESTHEADER);
                var bytes = Encoding.UTF8.GetBytes(pem);
                target.Write(bytes, 0, bytes.Length);
            }
            else
            {
                throw new NotSupportedException("unsupported encoding format");
            }
        }
        public override Csr GenerateCsr(CsrParams csrParams, PrivateKey pk, Crt.MessageDigest md)
        {
            var rsaPk = pk as CeRsaPrivateKey;

            if (rsaPk != null)
            {
                var cePk = new CERTENROLLLib.CX509PrivateKey();

                // MS_DEF_PROV
                //cePk.ProviderName = "Microsoft Base Cryptographic Provider";
                cePk.ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0";

                // Don't store in the machine's local cert store and allow exporting of private key
                cePk.MachineContext = false;
                cePk.ExportPolicy   = CERTENROLLLib.X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_FLAG;

                cePk.Import(BCRYPT_PRIVATE_KEY_BLOB, rsaPk.Exported);

                var ceReq = new CERTENROLLLib.CX509CertificateRequestCertificate();
                ceReq.InitializeFromPrivateKey(
                    CERTENROLLLib.X509CertificateEnrollmentContext.ContextUser,
                    cePk, "");

                // CN=Test Cert, OU=Sandbox
                var subjParts = new[]
                {
                    new { name = "C", value = csrParams?.Details?.Country },
                    new { name = "ST", value = csrParams?.Details?.StateOrProvince },
                    new { name = "L", value = csrParams?.Details?.Locality },
                    new { name = "O", value = csrParams?.Details?.Organization },
                    new { name = "OU", value = csrParams?.Details?.OrganizationUnit },
                    new { name = "CN", value = csrParams?.Details?.CommonName },
                    new { name = "E", value = csrParams?.Details?.Email },
                };

                // Escape any non-standard character
                var re   = new Regex("[^A-Za-z0-9\\._-]");
                var subj = "";
                foreach (var sp in subjParts)
                {
                    if (!string.IsNullOrEmpty(sp.value))
                    {
                        var spVal = re.Replace(sp.value, "\\$0");
                        subj += $",{sp.name}={spVal}";
                    }
                }
                if (string.IsNullOrEmpty(subj))
                {
                    throw new InvalidOperationException("invalid CSR details");
                }
                subj = subj.Substring(1); // Skip over the first comma

                // http://msdn.microsoft.com/en-us/library/aa377051(VS.85).aspx
                var subjDN = new CERTENROLLLib.CX500DistinguishedName();
                subjDN.Encode(subj);
                ceReq.Subject = subjDN;

                if (csrParams.NotBefore != null)
                {
                    ceReq.NotBefore = csrParams.NotBefore.Value;
                }
                if (csrParams.NotAfter != null)
                {
                    ceReq.NotAfter = csrParams.NotAfter.Value;
                }

                var mdVal = Enum.GetName(typeof(Crt.MessageDigest), md);
                var mdOid = new System.Security.Cryptography.Oid(mdVal);
                var mdAlg = new CERTENROLLLib.CObjectId();
                mdAlg.InitializeFromValue(mdOid.Value);
                ceReq.SignatureInformation.HashAlgorithm = mdAlg;
                ceReq.Encode();

                var csr = new Csr(ceReq.RawData);
                return(csr);
            }
            else
            {
                throw new NotSupportedException("unsuppored private key type");
            }
        }