Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #5
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);
            }
Example #6
0
        /// <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();
        }