public static bool Enroll(string username, WindowsCertificate agentCertificate, string caConfig, string template, string csr, out string errorMessage, out X509Certificate2 cert) { errorMessage = null; cert = null; string argsUser = username; X509Store store = new X509Store("My", StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); // Create a PKCS 10 inner request. CX509CertificateRequestPkcs10 pkcs10Req; try { pkcs10Req = new CX509CertificateRequestPkcs10(); pkcs10Req.InitializeDecode(csr, EncodingType.XCN_CRYPT_STRING_BASE64_ANY); } catch (Exception ex) { errorMessage = "Unable to create PKCS10 request, malformed CSR?" + Environment.NewLine + ex.Message; return(false); } // Create a CMC outer request and initialize CX509CertificateRequestCmc cmcReq; try { cmcReq = new CX509CertificateRequestCmc(); cmcReq.InitializeFromInnerRequestTemplateName(pkcs10Req, template); cmcReq.RequesterName = argsUser; } catch (Exception ex) { errorMessage = "Unable to create CMC request, bad certificate template?" + Environment.NewLine + ex.Message; return(false); } if (agentCertificate.StoreLocation == StoreLocation.CurrentUser) { try { CSignerCertificate signer = new CSignerCertificate(); signer.Initialize(false, X509PrivateKeyVerify.VerifyNone, EncodingType.XCN_CRYPT_STRING_HEXRAW, agentCertificate.Certificate.Thumbprint); cmcReq.SignerCertificate = signer; } catch (COMException ex) when(ex.HResult == (int)WindowsCryptoApiErrors.CRYPT_E_NOT_FOUND) { errorMessage = "Agent certificate was not found in the CurrentUser store"; return(false); } catch (COMException ex) when(ex.HResult == (int)WindowsCryptoApiErrors.NTE_NO_KEY) { errorMessage = "Could not access the key of the agent certificate. Perhaps you do not have permissions for it?" + Environment.NewLine + Environment.NewLine + "Consult the manual for more information"; return(false); } catch (Exception ex) { errorMessage = "Unable to initialize signer, bad agent certificate?" + Environment.NewLine + ex.Message; return(false); } } else if (agentCertificate.StoreLocation == StoreLocation.LocalMachine) { try { CSignerCertificate signer = new CSignerCertificate(); signer.Initialize(true, X509PrivateKeyVerify.VerifyNone, EncodingType.XCN_CRYPT_STRING_HEXRAW, agentCertificate.Certificate.Thumbprint); cmcReq.SignerCertificate = signer; } catch (COMException ex) when(ex.HResult == (int)WindowsCryptoApiErrors.CRYPT_E_NOT_FOUND) { errorMessage = "Agent certificate was not found in the LocalMachine store"; return(false); } catch (COMException ex) when(ex.HResult == (int)WindowsCryptoApiErrors.NTE_NO_KEY) { errorMessage = "Could not access the key of the agent certificate. Perhaps you do not have permissions for it?" + Environment.NewLine + Environment.NewLine + "Consult the manual for more information"; return(false); } catch (Exception ex) { errorMessage = "Unable to initialize signer, bad agent certificate?" + Environment.NewLine + ex.Message; return(false); } } else { errorMessage = "Agent certificate was not found in any store"; return(false); } // encode the request cmcReq.Encode(); string strRequest = cmcReq.RawData[EncodingType.XCN_CRYPT_STRING_BASE64]; CCertRequest objCertRequest = new CCertRequest(); // Get CA config from UI string strCAConfig = caConfig; // Submit the request int iDisposition; try { iDisposition = objCertRequest.Submit(CR_IN_BASE64 | CR_IN_FORMATANY, strRequest, null, strCAConfig); } catch (Exception ex) { errorMessage = "Unable to submit signing request, bad CA config?" + Environment.NewLine + ex.Message; return(false); } // Check the submission status if (CR_DISP_ISSUED != iDisposition) // Not enrolled { string strDisposition = objCertRequest.GetDispositionMessage(); errorMessage = strDisposition; if (CR_DISP_UNDER_SUBMISSION == iDisposition) { return(false); } errorMessage = errorMessage + Environment.NewLine + objCertRequest.GetLastStatus(); return(false); } // Get the certificate string strCert = objCertRequest.GetCertificate(CR_OUT_BASE64); byte[] rawCert = Convert.FromBase64String(strCert); cert = new X509Certificate2(rawCert); return(true); }
static void Main(string[] args) { if (args.Length != 5) { Console.WriteLine("Usage: Signer.exe [EnrollmentCertificateThumbprint] [BehalfOfUser] [PathToCSR] [OutputFileName] [CertificateTemplate]"); return; } string argsKey = args[0]; string argsUser = args[1]; string argsCsr = args[2]; string argsCrt = args[3]; string argsCrtTmpl = args[4]; string csr = string.Join("\n", File.ReadAllLines(argsCsr).Where(s => s.Length > 0 && !s.StartsWith("--"))); // Create a PKCS 10 inner request. CX509CertificateRequestPkcs10 pkcs10Req = new CX509CertificateRequestPkcs10(); pkcs10Req.InitializeDecode(csr); // Create a CMC outer request and initialize CX509CertificateRequestCmc cmcReq = new CX509CertificateRequestCmc(); cmcReq.InitializeFromInnerRequestTemplateName(pkcs10Req, argsCrtTmpl); cmcReq.RequesterName = argsUser; CSignerCertificate signer = new CSignerCertificate(); signer.Initialize(false, X509PrivateKeyVerify.VerifyNone, (EncodingType)0xc, argsKey); cmcReq.SignerCertificate = signer; // encode the request cmcReq.Encode(); string strRequest = cmcReq.RawData[EncodingType.XCN_CRYPT_STRING_BASE64]; CCertConfig objCertConfig = new CCertConfig(); CCertRequest objCertRequest = new CCertRequest(); // Get CA config from UI string strCAConfig = objCertConfig.GetConfig(CC_UIPICKCONFIG); // Submit the request int iDisposition = objCertRequest.Submit(CR_IN_BASE64 | CR_IN_FORMATANY, strRequest, null, strCAConfig); // Check the submission status if (CR_DISP_ISSUED != iDisposition) // Not enrolled { string strDisposition = objCertRequest.GetDispositionMessage(); if (CR_DISP_UNDER_SUBMISSION == iDisposition) { Console.WriteLine("The submission is pending: " + strDisposition); return; } Console.WriteLine("The submission failed: " + strDisposition); Console.WriteLine("Last status: " + objCertRequest.GetLastStatus()); return; } // Get the certificate string strCert = objCertRequest.GetCertificate(CR_OUT_BASE64); File.WriteAllText(argsCrt, "-----BEGIN CERTIFICATE-----\n" + strCert + "-----END CERTIFICATE-----\n"); }
private static void Enroll(string publicKeyAsPem, string username, string agentCertificate, string caConfig) { string argsKey = agentCertificate; string argsUser = username; X509Store store = new X509Store("My", StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); publicKeyAsPem = string.Join("", publicKeyAsPem.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Where(s => !s.StartsWith("--"))); // Create a PKCS 10 inner request. CX509PublicKey pubKey = new CX509PublicKey(); pubKey.InitializeFromEncodedPublicKeyInfo(publicKeyAsPem); CObjectId sha512 = new CObjectId(); sha512.InitializeFromValue("2.16.840.1.101.3.4.2.3"); CX509CertificateRequestPkcs10 pkcs10Req = new CX509CertificateRequestPkcs10(); pkcs10Req.InitializeFromPublicKey(X509CertificateEnrollmentContext.ContextUser, pubKey, ""); pkcs10Req.HashAlgorithm = sha512; string toSign = pkcs10Req.RawDataToBeSigned[EncodingType.XCN_CRYPT_STRING_HASHDATA]; //using (YubikeyPivTool piv = new YubikeyPivTool()) //{ // //piv. //} // Create a CMC outer request and initialize CX509CertificateRequestCmc cmcReq = new CX509CertificateRequestCmc(); cmcReq.InitializeFromInnerRequestTemplateName(pkcs10Req, "SmartcardLogon"); cmcReq.RequesterName = argsUser; CSignerCertificate signer = new CSignerCertificate(); signer.Initialize(false, X509PrivateKeyVerify.VerifyNone, (EncodingType)0xc, argsKey); cmcReq.SignerCertificate = signer; // encode the request cmcReq.Encode(); string strRequest = cmcReq.RawData[EncodingType.XCN_CRYPT_STRING_BASE64]; CCertRequest objCertRequest = new CCertRequest(); // Get CA config from UI string strCAConfig = caConfig; // Submit the request int iDisposition = objCertRequest.Submit(CR_IN_BASE64 | CR_IN_FORMATANY, strRequest, null, strCAConfig); // Check the submission status if (CR_DISP_ISSUED != iDisposition) // Not enrolled { string strDisposition = objCertRequest.GetDispositionMessage(); if (CR_DISP_UNDER_SUBMISSION == iDisposition) { Console.WriteLine("The submission is pending: " + strDisposition); return; } Console.WriteLine("The submission failed: " + strDisposition); Console.WriteLine("Last status: " + objCertRequest.GetLastStatus()); return; } // Get the certificate string strCert = objCertRequest.GetCertificate(CR_OUT_BASE64); string argsCrt = "tmp.crt"; File.WriteAllText(argsCrt, "-----BEGIN CERTIFICATE-----\n" + strCert + "-----END CERTIFICATE-----\n"); }