/// <summary>
        /// Posts the data to the specified URI.
        /// </summary>
        /// <typeparam name="T">The type of expected result</typeparam>
        /// <param name="client">The client.</param>
        /// <param name="jwsSigner">The jwsSigner used to sign the payload.</param>
        /// <param name="location">The URI.</param>
        /// <param name="entity">The payload.</param>
        /// <param name="ensureSuccessStatusCode">if set to <c>true</c>, throw exception if the request failed.</param>
        /// <param name="retryCount">Number of retries on badNonce errors (default = 1)</param>
        /// <returns>
        /// The response from ACME server.
        /// </returns>
        /// <exception cref="Exception">
        /// If the HTTP request failed and <paramref name="ensureSuccessStatusCode"/> is <c>true</c>.
        /// </exception>
        internal static async Task <AcmeHttpResponse <T> > Post <T>(this IAcmeHttpClient client,
                                                                    JwsSigner jwsSigner,
                                                                    Uri location,
                                                                    object entity,
                                                                    bool ensureSuccessStatusCode,
                                                                    int retryCount = 1)
        {
            var payload  = jwsSigner.Sign(entity, url: location, nonce: await client.ConsumeNonce());
            var response = await client.Post <T>(location, payload);

            while (response.Error?.Status == System.Net.HttpStatusCode.BadRequest &&
                   response.Error.Type?.CompareTo("urn:ietf:params:acme:error:badNonce") == 0 &&
                   retryCount-- > 0)
            {
                payload  = jwsSigner.Sign(entity, url: location, nonce: await client.ConsumeNonce());
                response = await client.Post <T>(location, payload);
            }

            if (ensureSuccessStatusCode && response.Error != null)
            {
                throw new AcmeRequestException(
                          string.Format(Strings.ErrorFetchResource, location),
                          response.Error);
            }

            return(response);
        }
Exemple #2
0
        /// <summary>
        /// Changes the registration key.
        /// </summary>
        /// <param name="account">The account.</param>
        /// <param name="newKey">The new registration key.</param>
        /// <returns>The awaitable.</returns>
        public async Task ChangeKey(AcmeAccount account, KeyInfo newKey)
        {
            var keyPair = new AccountKey(newKey);

            var body = new
            {
                account = account.Location,
                newKey  = keyPair.JsonWebKey,
            };

            var jws     = new JwsSigner(keyPair);
            var payload = jws.Sign(body);
            var payloadWithResourceType = new
            {
                payload.Header,
                payload.Payload,
                payload.Protected,
                payload.Signature,
                Resource = ResourceTypes.KeyChange
            };

            var uri = await this.handler.GetResourceUri(ResourceTypes.KeyChange);

            var result = await this.handler.Post(uri, payloadWithResourceType, key);

            ThrowIfError(result);

            this.key = keyPair;
        }
Exemple #3
0
        /// <summary>
        /// Revokes the certificate.
        /// </summary>
        /// <param name="certificate">The certificate in DER format.</param>
        /// <param name="reason">The reason for revocation.</param>
        /// <param name="certificatePrivateKey">The certificate's private key.</param>
        /// <returns>
        /// The awaitable.
        /// </returns>
        public async Task RevokeCertificate(byte[] certificate, RevocationReason reason, IKey certificatePrivateKey)
        {
            var endpoint = await this.GetResourceUri(d => d.RevokeCert);

            var body = new CertificateRevocation
            {
                Certificate = JwsConvert.ToBase64String(certificate),
                Reason      = reason
            };


            JwsPayload payload;

            if (certificatePrivateKey != null)
            {
                var jws = new JwsSigner(certificatePrivateKey);
                payload = jws.Sign(body, url: endpoint, nonce: await HttpClient.ConsumeNonce());
            }
            else
            {
                payload = await Sign(body, endpoint);
            }

            await HttpClient.Post <string>(endpoint, payload, true);
        }
Exemple #4
0
        /// <summary>
        /// Post to the new account endpoint.
        /// </summary>
        /// <param name="context">The ACME context.</param>
        /// <param name="body">The payload.</param>
        /// <param name="ensureSuccessStatusCode">if set to <c>true</c>, throw exception if the request failed.</param>
        /// <returns>The ACME response.</returns>
        internal static async Task <AcmeHttpResponse <Account> > NewAccount(
            IAcmeContext context, Account body, bool ensureSuccessStatusCode)
        {
            var endpoint = await context.GetResourceUri(d => d.NewAccount);

            var jws     = new JwsSigner(context.AccountKey);
            var payload = jws.Sign(body, url: endpoint, nonce: await context.HttpClient.ConsumeNonce());

            return(await context.HttpClient.Post <Account>(endpoint, payload, ensureSuccessStatusCode));
        }
Exemple #5
0
        /// <summary>
        /// Signs the data with account key.
        /// </summary>
        /// <param name="entity">The data to sign.</param>
        /// <param name="uri">The URI for the request.</param>
        /// <returns>The JWS payload.</returns>
        public async Task <JwsPayload> Sign(object entity, Uri uri)
        {
            var nonce = await HttpClient.ConsumeNonce();

            var location = await Account().Location();

            var jws = new JwsSigner(AccountKey);

            return(jws.Sign(entity, location, uri, nonce));
        }
Exemple #6
0
        /// <summary>
        /// Changes the account key.
        /// </summary>
        /// <param name="key">The new account key.</param>
        /// <returns>The account resource.</returns>
        public async Task <Account> ChangeKey(IKey key)
        {
            var endpoint = await this.GetResourceUri(d => d.KeyChange);

            var location = await Account().Location();

            var newKey    = key ?? KeyFactory.NewKey(defaultKeyType);
            var keyChange = new
            {
                account = location,
                oldKey  = AccountKey.JsonWebKey,
            };

            var jws  = new JwsSigner(newKey);
            var body = jws.Sign(keyChange, url: endpoint);

            var resp = await HttpClient.Post <Account>(this, endpoint, body, true);

            AccountKey = newKey;
            return(resp.Resource);
        }
Exemple #7
0
        /// <summary>
        /// Encodes the specified entity for ACME requests.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="keyPair">The key pair.</param>
        /// <param name="nonce">The nonce.</param>
        /// <returns>The encoded JSON.</returns>
        private static object Encode(object entity, IAccountKey keyPair, string nonce)
        {
            var encoder = new JwsSigner(keyPair.SignatureKey);

            return(encoder.Sign(entity, nonce));
        }