public async Task StandardCertificateRequest() { var restApi = new AcmeRestApi(ProtoacmeContants.LETSENCRYPT_STAGING_ENDPOINT); var client = new ProtoacmeClient(restApi); //1. Create a new account. var newAccountInfo = new AcmeCreateAccount(); newAccountInfo.Contact.Add("mailto:[email protected]"); newAccountInfo.TermsOfServiceAgreed = true; var account = await client.Account.CreateAsync(newAccountInfo); //2. Request a certificate. AcmeCertificateRequest certRequest = new AcmeCertificateRequest(); foreach (var dns in dnsNames) { certRequest.Identifiers.Add(new DnsCertificateIdentifier() { Value = dns }); } var certPromise = await client.Certificate.RequestCertificateAsync(account, certRequest); //3. Get challenge var challenges = await client.Challenge.GetChallengesAsync(account, certPromise, ChallengeType.Http); //4. Save Challenge and Account for next step. SaveAccountAndChallengeData(account, challenges, certPromise); }
public async Task WildCardCertificateRequest() { var restApi = new AcmeRestApi(ProtoacmeContants.LETSENCRYPT_STAGING_ENDPOINT); var client = new ProtoacmeClient(restApi); //1. Create a new account. var newAccountInfo = new AcmeCreateAccount(); newAccountInfo.Contact.Add("mailto:[email protected]"); newAccountInfo.Contact.Add("mailto:[email protected]"); newAccountInfo.TermsOfServiceAgreed = true; var account = await client.Account.CreateAsync(newAccountInfo); //2. Request the wildcard cert. AcmeCertificateRequest certRequest = new AcmeCertificateRequest(); certRequest.Identifiers.Add(new DnsCertificateIdentifier() { Value = wildCardDns }); var promise = await client.Certificate.RequestCertificateAsync(account, certRequest); //3. Get Challenges var challenge = await client.Challenge.GetChallengesAsync(account, promise, ChallengeType.Dns); //4. Save Challenge Information challenge[0].SaveToFile(@"c:\temp\dns_challenge.txt"); //5. Save account and additional info for future request. account.SaveToFile(@"c:\temp\account.dat"); promise.SaveToFile(@"c:\temp\promise.dat"); challenge.SaveToFile(@"c:\temp\challenge.dat"); }
public async Task VerifyChallenge_ShouldVerifyTheChallenge() { //SETUP AcmeRestApi api = new AcmeRestApi(ProtoacmeContants.LETSENCRYPT_STAGING_ENDPOINT); AcmeApiResponse <AcmeDirectory> directory; AcmeApiResponse nonceResponse = null; AcmeApiResponse <AcmeAccount> accountResponse = null; AcmeApiResponse <AcmeCertificateFulfillmentPromise> certificateFulfillmentPromise = null; List <AcmeApiResponse <AcmeAuthorization> > authorizations = null; AcmeApiResponse <AcmeChallengeStatus> challengeStatusResponse; AcmeCertificateRequest certifcateRequest = new AcmeCertificateRequest() { Identifiers = new List <DnsCertificateIdentifier>() { new DnsCertificateIdentifier() { Value = "taco.com" }, new DnsCertificateIdentifier() { Value = "www.taco.com" } } }; //EXECUTE directory = await api.GetDirectoryAsync(); nonceResponse = await api.GetNonceAsync(directory.Data); accountResponse = await api.CreateAccountAsync(directory.Data, nonceResponse.Nonce, new AcmeCreateAccount() { Contact = new List <string>() { "mailto:[email protected]" }, TermsOfServiceAgreed = true }); certificateFulfillmentPromise = await api.RequestCertificateAsync(directory.Data, accountResponse.Nonce, accountResponse.Data, certifcateRequest); authorizations = await api.GetChallengesAsync(certificateFulfillmentPromise.Data); AcmeChallenge httpChallenge = authorizations.First().Data.Challenges.First(t => t.Type.Equals("http-01")); string authKey = CreateAuthorizationKey(accountResponse.Data, httpChallenge.Token); challengeStatusResponse = await api.VerifyChallengeAsync(accountResponse.Data, httpChallenge, certificateFulfillmentPromise.Nonce, authKey); //ASSERT challengeStatusResponse.ShouldNotBeNull(); challengeStatusResponse.Status.ShouldBe(AcmeApiResponseStatus.Success); challengeStatusResponse.Data.ShouldNotBeNull(); challengeStatusResponse.Data.Status.ShouldBe("pending"); }
public async Task RequestCertificate_ShouldGetPromiseBack() { //SETUP AcmeRestApi api = new AcmeRestApi(ProtoacmeContants.LETSENCRYPT_STAGING_ENDPOINT); AcmeApiResponse <AcmeDirectory> directory; AcmeApiResponse nonceResponse = null; AcmeApiResponse <AcmeAccount> accountResponse = null; AcmeApiResponse <AcmeCertificateFulfillmentPromise> certificateFulfillmentPromise = null; AcmeCertificateRequest certifcateRequest = new AcmeCertificateRequest() { Identifiers = new List <DnsCertificateIdentifier>() { new DnsCertificateIdentifier() { Value = "taco.com" }, new DnsCertificateIdentifier() { Value = "www.taco.com" } } }; //EXECUTE directory = await api.GetDirectoryAsync(); nonceResponse = await api.GetNonceAsync(directory.Data); accountResponse = await api.CreateAccountAsync(directory.Data, nonceResponse.Nonce, new AcmeCreateAccount() { Contact = new List <string>() { "mailto:[email protected]" }, TermsOfServiceAgreed = true }); certificateFulfillmentPromise = await api.RequestCertificateAsync(directory.Data, accountResponse.Nonce, accountResponse.Data, certifcateRequest); //ASSERT certificateFulfillmentPromise.ShouldNotBeNull(); certificateFulfillmentPromise.Status.ShouldBe(AcmeApiResponseStatus.Success); certificateFulfillmentPromise.Data.ShouldNotBeNull(); certificateFulfillmentPromise.Data.Status.ShouldBe("pending"); certificateFulfillmentPromise.Data.Identifiers.ShouldNotBeNull(); certificateFulfillmentPromise.Data.Identifiers.Count.ShouldBe(2); certificateFulfillmentPromise.Data.Authorizations.ShouldNotBeNull(); certificateFulfillmentPromise.Data.Authorizations.Count.ShouldBe(2); certificateFulfillmentPromise.Data.Finalize.ShouldNotBeNull(); certificateFulfillmentPromise.Data.Finalize.Length.ShouldBeGreaterThan(0); }
public async Task <CertificateResponse> NewCertificateRequestAsync(byte[] csr, CancellationToken token = default(CancellationToken)) { await EnsureDirectoryAsync().ConfigureAwait(false); var request = new AcmeCertificateRequest { Csr = Jws.Base64UrlEncoded(csr) }; var response = await PostAsync <CertificateResponse>( _directory.NewCertificate, request, token ).ConfigureAwait(false); return(response); }
/// <summary> /// Sends a new order requesting a new certificate. /// </summary> /// <param name="directory">Directory object.</param> /// <param name="nonce">Nonce</param> /// <param name="account">Must be existing account.</param> /// <param name="certificates">Info describing the dns entries you are requesting certificates for.</param> /// <returns>A certificate fulfillment promise that is used to complete the certification chain in future requests. Wrapped by a response object.</returns> public async Task <AcmeApiResponse <AcmeCertificateFulfillmentPromise> > RequestCertificateAsync(AcmeDirectory directory, string nonce, AcmeAccount account, AcmeCertificateRequest certificates) { if (directory == null) { throw new ArgumentNullException("directory"); } if (string.IsNullOrEmpty(directory.NewAccount)) { throw new ArgumentException("directory is missing Account url."); } if (string.IsNullOrEmpty(nonce)) { throw new ArgumentNullException("nonce"); } if (account == null) { throw new ArgumentNullException("account"); } if (certificates == null) { throw new ArgumentNullException("certificates"); } if (certificates.Identifiers == null || !certificates.Identifiers.Any()) { throw new ArgumentException("Certificate is missing identifiers"); } JwsContainer <AcmeCertificateRequest> jwsObject = new JwsContainer <AcmeCertificateRequest>(account.SecurityInfo, nonce, directory.NewOrder, account.KID, certificates); string jwsToken = jwsObject.SerializeSignedToken(); var apiResp = await SendPostData( url : directory.NewOrder, data : jwsToken); string apiRespString = await apiResp.Content?.ReadAsStringAsync(); if (apiResp.StatusCode != HttpStatusCode.Created) { return(ErrorResponse <AcmeCertificateFulfillmentPromise>(apiRespString)); } if (!apiResp.Headers.TryGetValues(ProtoacmeContants.HEADER_NONCE, out IEnumerable <string> nonces)) { return(ErrorResponse <AcmeCertificateFulfillmentPromise>("Missing Replay-Nonce Header on RequestCertificate Response.")); } return(new AcmeApiResponse <AcmeCertificateFulfillmentPromise>() { Status = AcmeApiResponseStatus.Success, Nonce = nonces.FirstOrDefault(), Data = JsonConvert.DeserializeObject <AcmeCertificateFulfillmentPromise>(apiRespString) }); }
/// <summary> /// Request a new certificate /// </summary> /// <param name="account">Existing account</param> /// <param name="certificate">Info describing the dns entries you are requesting certificates for.</param> /// <returns>A certificate fulfillment promise that is used to complete the certification chain in future requests.</returns> public async Task <AcmeCertificateFulfillmentPromise> RequestCertificateAsync(AcmeAccount account, AcmeCertificateRequest certificate) { var directory = await _directoryCache.GetAsync(); var nonce = await _nonceCache.GetAsync(); var response = await _acmeApi.RequestCertificateAsync(directory, nonce, account, certificate); if (response.Status == AcmeApiResponseStatus.Error) { throw new AcmeProtocolException(response.Message); } _nonceCache.Update(response.Nonce); return(response.Data); }
public async Task DownloadCertificate_ShouldComplete() { //SETUP AcmeRestApi api = new AcmeRestApi(ProtoacmeContants.LETSENCRYPT_STAGING_ENDPOINT); AcmeApiResponse <AcmeDirectory> directory; AcmeApiResponse nonceResponse = null; AcmeApiResponse <AcmeAccount> accountResponse = null; AcmeApiResponse <AcmeCertificateFulfillmentPromise> certificateFulfillmentPromise = null; List <AcmeApiResponse <AcmeAuthorization> > authorizations = null; AcmeApiResponse <AcmeChallengeStatus> challengeStatusResponse = null; AcmeApiResponse <AcmeChallengeVerificationStatus> challengeVerificationResponse = null; AcmeApiResponse <AcmeCertificateFulfillmentPromise> certificatePromiseResult = null; AcmeApiResponse <ArraySegment <byte> > certificateResult = null; AcmeCertificateRequest certifcateRequest = new AcmeCertificateRequest() { Identifiers = new List <DnsCertificateIdentifier>() { new DnsCertificateIdentifier() { Value = "test.com" } } }; //EXECUTE directory = await api.GetDirectoryAsync(); nonceResponse = await api.GetNonceAsync(directory.Data); accountResponse = await api.CreateAccountAsync(directory.Data, nonceResponse.Nonce, new AcmeCreateAccount() { Contact = new List <string>() { "mailto:[email protected]" }, TermsOfServiceAgreed = true }); certificateFulfillmentPromise = await api.RequestCertificateAsync(directory.Data, accountResponse.Nonce, accountResponse.Data, certifcateRequest); authorizations = await api.GetChallengesAsync(certificateFulfillmentPromise.Data); AcmeChallenge httpChallenge = authorizations.First().Data.Challenges.First(t => t.Type.Equals("http-01")); string authKey = CreateAuthorizationKey(accountResponse.Data, httpChallenge.Token); challengeStatusResponse = await api.VerifyChallengeAsync(accountResponse.Data, httpChallenge, certificateFulfillmentPromise.Nonce, authKey); while ( challengeVerificationResponse == null || challengeVerificationResponse.Data.Status == "pending") { challengeVerificationResponse = await api.GetChallengeVerificationStatusAsync(httpChallenge); await Task.Delay(3000); } string csr = GenerateCSR(accountResponse.Data, "test.com"); certificatePromiseResult = await api.FinalizeCertificatePromiseAsync(accountResponse.Data, challengeStatusResponse.Nonce, certificateFulfillmentPromise.Data, csr); certificateResult = await api.GetCertificateAsync(certificatePromiseResult.Data, CertificateType.Cert); //We will write the cert out to a temp directory if it exists. Otherwise, forget it. if (Directory.Exists(@"c:\temp")) { using (FileStream fs = new FileStream(@"c:\temp\mycert.cer", FileMode.Create)) { byte[] bytes = certificateResult.Data.Array; fs.Write(bytes, 0, bytes.Length); } } //ASSERT (Cant really assert anything here. This call will mostlikey fail. There is no way to validate the domain here) }
public async Task FinalizeChallenge_ShouldComplete() { //SETUP AcmeRestApi api = new AcmeRestApi(ProtoacmeContants.LETSENCRYPT_STAGING_ENDPOINT); AcmeApiResponse <AcmeDirectory> directory; AcmeApiResponse nonceResponse = null; AcmeApiResponse <AcmeAccount> accountResponse = null; AcmeApiResponse <AcmeCertificateFulfillmentPromise> certificateFulfillmentPromise = null; List <AcmeApiResponse <AcmeAuthorization> > authorizations = null; AcmeApiResponse <AcmeChallengeStatus> challengeStatusResponse = null; AcmeApiResponse <AcmeChallengeVerificationStatus> challengeVerificationResponse = null; AcmeApiResponse <AcmeCertificateFulfillmentPromise> certificatePromiseResult = null; AcmeCertificateRequest certifcateRequest = new AcmeCertificateRequest() { Identifiers = new List <DnsCertificateIdentifier>() { new DnsCertificateIdentifier() { Value = "test.com" } } }; //EXECUTE directory = await api.GetDirectoryAsync(); nonceResponse = await api.GetNonceAsync(directory.Data); accountResponse = await api.CreateAccountAsync(directory.Data, nonceResponse.Nonce, new AcmeCreateAccount() { Contact = new List <string>() { "mailto:[email protected]" }, TermsOfServiceAgreed = true }); certificateFulfillmentPromise = await api.RequestCertificateAsync(directory.Data, accountResponse.Nonce, accountResponse.Data, certifcateRequest); authorizations = await api.GetChallengesAsync(certificateFulfillmentPromise.Data); AcmeChallenge httpChallenge = authorizations.First().Data.Challenges.First(t => t.Type.Equals("http-01")); string authKey = CreateAuthorizationKey(accountResponse.Data, httpChallenge.Token); challengeStatusResponse = await api.VerifyChallengeAsync(accountResponse.Data, httpChallenge, certificateFulfillmentPromise.Nonce, authKey); while ( challengeVerificationResponse == null || challengeVerificationResponse.Data.Status == "pending") { challengeVerificationResponse = await api.GetChallengeVerificationStatusAsync(httpChallenge); await Task.Delay(3000); } string csr = GenerateCSR(accountResponse.Data, "test.com"); certificatePromiseResult = await api.FinalizeCertificatePromiseAsync(accountResponse.Data, challengeStatusResponse.Nonce, certificateFulfillmentPromise.Data, csr); //ASSERT (Cant really assert anything here. This call will mostlikey fail. There is no way to validate the domain here) certificatePromiseResult.ShouldNotBeNull(); }