acme-client 2.0.7 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +46 -15
- data/lib/acme/client.rb +22 -0
- data/lib/acme/client/jwk/ecdsa.rb +3 -1
- data/lib/acme/client/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9cb714bd4f0321181c50087f976122251233340d09f4ed612cf91070e0986d70
|
4
|
+
data.tar.gz: db7df58ad9a1e4794bef25dfbc309efad73b9b1cbb6100f77d9552cbb734fb5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d7eb7d76ea95ab724810af93ad4e79af03fe62752509a793b5310b01b670b7c57f737bbb3a68de72ab4e84f01f9d613e45937a50119ddfe3b0f5d0aa628f45e
|
7
|
+
data.tar.gz: 38b349fdcdb68f5ec493951ec4a480966256e591f6d9cffc4266116bff6d2aed6e8f0e5493acf985f6a81c0cad7c20a69e4d7bd1cedb95357b297cdcfb1b494c
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -23,17 +23,26 @@ gem 'acme-client'
|
|
23
23
|
```
|
24
24
|
|
25
25
|
## Usage
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
26
|
+
- [Acme::Client](#acmeclient)
|
27
|
+
- [Installation](#installation)
|
28
|
+
- [Usage](#usage)
|
29
|
+
- [Setting up a client](#setting-up-a-client)
|
30
|
+
- [Account management](#account-management)
|
31
|
+
- [Obtaining a certificate](#obtaining-a-certificate)
|
32
|
+
- [Ordering a certificate](#ordering-a-certificate)
|
33
|
+
- [Preparing for HTTP challenge](#preparing-for-http-challenge)
|
34
|
+
- [Preparing for DNS challenge](#preparing-for-dns-challenge)
|
35
|
+
- [Requesting a challenge verification](#requesting-a-challenge-verification)
|
36
|
+
- [Downloading a certificate](#downloading-a-certificate)
|
37
|
+
- [Ordering an alternative certificate](#ordering-an-alternative-certificate)
|
38
|
+
- [Extra](#extra)
|
39
|
+
- [Certificate revokation](#certificate-revokation)
|
40
|
+
- [Certificate renewal](#certificate-renewal)
|
41
|
+
- [Not implemented](#not-implemented)
|
42
|
+
- [Requirements](#requirements)
|
43
|
+
- [Development](#development)
|
44
|
+
- [Pull request?](#pull-request)
|
45
|
+
- [License](#license)
|
37
46
|
|
38
47
|
## Setting up a client
|
39
48
|
|
@@ -91,7 +100,7 @@ account.kid # => <kid string>
|
|
91
100
|
|
92
101
|
If you already have an existing account (for example one created in ACME v1) please note that unless the `kid` is provided at initialization, the client will lazy load the `kid` by doing a `POST` to `newAccount` whenever the `kid` is required. Therefore, you can easily get your `kid` for an existing account and (if needed) store it for reuse:
|
93
102
|
|
94
|
-
```
|
103
|
+
```ruby
|
95
104
|
client = Acme::Client.new(private_key: private_key, directory: 'https://acme-staging-v02.api.letsencrypt.org/directory')
|
96
105
|
|
97
106
|
# kid is not set, therefore a call to newAccount is made to lazy-initialize the kid
|
@@ -189,6 +198,23 @@ end
|
|
189
198
|
order.certificate # => PEM-formatted certificate
|
190
199
|
```
|
191
200
|
|
201
|
+
### Ordering an alternative certificate
|
202
|
+
|
203
|
+
Let's Encrypt is [transitioning](https://letsencrypt.org/2019/04/15/transitioning-to-isrg-root.html) to use a new intermediate certificate. Starting January 11, 2021 new certificates will be signed by their own intermediate. To ease the transition on clients Let's Encrypt will continue signing an alternative version of the certificate using the old, cross-signed intermediate until September 29, 2021. In order to utilize an alternative certificate the `Order#certificate` method accepts a `force_chain` keyword argument, which takes the issuer name of the intermediate certificate.
|
204
|
+
For example, to download the cross-signed certificate after January 11, 2021, call `Order#certificate` as follows:
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
begin
|
208
|
+
order.certificate(force_chain: 'DST Root CA X3')
|
209
|
+
rescue Acme::Client::Error::ForcedChainNotFound
|
210
|
+
order.certificate
|
211
|
+
end
|
212
|
+
```
|
213
|
+
|
214
|
+
Note: if the specified forced chain doesn't match an existing alternative certificate the method will raise an `Acme::Client::Error::ForcedChainNotFound` error.
|
215
|
+
|
216
|
+
Learn more about the original Github issue for this client [here](https://github.com/unixcharles/acme-client/issues/186), information from Let's Encrypt [here](https://letsencrypt.org/2019/04/15/transitioning-to-isrg-root.html), and cross-signing [here](https://letsencrypt.org/certificates/#cross-signing).
|
217
|
+
|
192
218
|
## Extra
|
193
219
|
|
194
220
|
### Certificate revokation
|
@@ -204,9 +230,15 @@ client.revoke(certificate: certificate)
|
|
204
230
|
There is no renewal process, just create a new order.
|
205
231
|
|
206
232
|
|
207
|
-
|
233
|
+
### Account Key Roll-over
|
208
234
|
|
209
|
-
|
235
|
+
To change the key used for an account you can call `#account_key_change` with the new private key or jwk.
|
236
|
+
|
237
|
+
```ruby
|
238
|
+
require 'openssl'
|
239
|
+
new_private_key = OpenSSL::PKey::RSA.new(4096)
|
240
|
+
client.account_key_change(private_key: new_private_key)
|
241
|
+
```
|
210
242
|
|
211
243
|
## Requirements
|
212
244
|
|
@@ -227,4 +259,3 @@ Yes.
|
|
227
259
|
## License
|
228
260
|
|
229
261
|
[MIT License](http://opensource.org/licenses/MIT)
|
230
|
-
|
data/lib/acme/client.rb
CHANGED
@@ -85,6 +85,28 @@ class Acme::Client
|
|
85
85
|
Acme::Client::Resources::Account.new(self, url: kid, **arguments)
|
86
86
|
end
|
87
87
|
|
88
|
+
def account_key_change(new_private_key: nil, new_jwk: nil)
|
89
|
+
if new_private_key.nil? && new_jwk.nil?
|
90
|
+
raise ArgumentError, 'must specify new_jwk or new_private_key'
|
91
|
+
end
|
92
|
+
old_jwk = jwk
|
93
|
+
new_jwk ||= Acme::Client::JWK.from_private_key(new_private_key)
|
94
|
+
|
95
|
+
inner_payload_header = {
|
96
|
+
url: endpoint_for(:key_change)
|
97
|
+
}
|
98
|
+
inner_payload = {
|
99
|
+
account: kid,
|
100
|
+
oldKey: old_jwk.to_h
|
101
|
+
}
|
102
|
+
payload = JSON.parse(new_jwk.jws(header: inner_payload_header, payload: inner_payload))
|
103
|
+
|
104
|
+
response = post(endpoint_for(:key_change), payload: payload, mode: :kid)
|
105
|
+
arguments = attributes_from_account_response(response)
|
106
|
+
@jwk = new_jwk
|
107
|
+
Acme::Client::Resources::Account.new(self, url: kid, **arguments)
|
108
|
+
end
|
109
|
+
|
88
110
|
def account
|
89
111
|
@kid ||= begin
|
90
112
|
response = post(endpoint_for(:new_account), payload: { onlyReturnExisting: true }, mode: :jwk)
|
@@ -73,8 +73,10 @@ class Acme::Client::JWK::ECDSA < Acme::Client::JWK::Base
|
|
73
73
|
# BigNumbers
|
74
74
|
bns = ints.map(&:value)
|
75
75
|
|
76
|
+
byte_size = (@private_key.group.degree + 7) / 8
|
77
|
+
|
76
78
|
# Binary R/S values
|
77
|
-
r, s = bns.map { |bn|
|
79
|
+
r, s = bns.map { |bn| bn.to_s(2).rjust(byte_size, "\x00") }
|
78
80
|
|
79
81
|
# JWS wants raw R/S concatenated.
|
80
82
|
[r, s].join
|
data/lib/acme/client/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acme-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Barbier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|