linzer 0.7.9.beta1 → 0.7.9.beta2
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 +6 -0
- data/README.md +200 -115
- data/flake.lock +10 -34
- data/flake.nix +17 -5
- data/lib/linzer/message/adapter/http_gem/common.rb +43 -0
- data/lib/linzer/message/adapter/http_gem/request.rb +5 -7
- data/lib/linzer/message/adapter/http_gem/response.rb +4 -0
- data/lib/linzer/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f13471dec9f1ca620ac5fa94faeb2173632bec2aede20fbb1e156988c48fd10d
|
|
4
|
+
data.tar.gz: 4dffdf98551884ea0a1b11c892ef1cb2ee5cad1fb6234e1d54890feea210a898
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1ca361d6e8dbc9d1960f37f33785a56cb7cd5a22a61d9fbe44228541c5cf54791acc21d9d19b4fb9a078322855776686d42aff86bbc05d4014cc017669375e9a
|
|
7
|
+
data.tar.gz: 89979f2b5c0e2d2a527cb04e223879f543a26c0cc81ef702ce5c3858c8f241126a38d28aeb9070bacebfbfdf488eae75e5e75f9fd0a242b5e04dfa12c76f6d6d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.7.9.beta2] - 2026-04-19
|
|
4
|
+
|
|
5
|
+
- Add support for http gem 6.x while maintaining compatibility with 5.x.
|
|
6
|
+
Handles API differences introduced in 6.0.
|
|
7
|
+
- Improve README clarity and align it with current behavior and production usage.
|
|
8
|
+
|
|
3
9
|
## [0.7.9.beta1] - 2026-03-03
|
|
4
10
|
|
|
5
11
|
(Beta release to test gem release automation; no functional changes)
|
data/README.md
CHANGED
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
[rubydoc-badge]: https://img.shields.io/badge/docs-RubyDoc.info-blue
|
|
10
10
|
[rubydoc-link]: https://www.rubydoc.info/gems/linzer
|
|
11
11
|
|
|
12
|
-
Linzer is a Ruby library for [HTTP Message Signatures (RFC 9421)](https://www.rfc-editor.org/rfc/rfc9421.html)
|
|
12
|
+
Linzer is a Ruby library for [HTTP Message Signatures (RFC 9421)](https://www.rfc-editor.org/rfc/rfc9421.html),
|
|
13
|
+
allowing you to sign and verify HTTP requests and responses with
|
|
14
|
+
standard-compliant cryptographic signatures.
|
|
15
|
+
|
|
16
|
+
Useful for APIs, webhooks, and services that need to verify request
|
|
17
|
+
authenticity or prevent tampering.
|
|
13
18
|
|
|
14
19
|
## Install
|
|
15
20
|
|
|
@@ -23,48 +28,79 @@ Or just `gem install linzer`.
|
|
|
23
28
|
|
|
24
29
|
## Usage
|
|
25
30
|
|
|
26
|
-
###
|
|
31
|
+
### Quick start
|
|
27
32
|
|
|
28
|
-
Add the
|
|
29
|
-
as needed, e.g.:
|
|
33
|
+
Add the middleware to your Rack application:
|
|
30
34
|
|
|
31
35
|
```ruby
|
|
32
36
|
# config.ru
|
|
33
|
-
use Rack::Auth::Signature,
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
use Rack::Auth::Signature,
|
|
38
|
+
except: "/login",
|
|
39
|
+
default_key: {
|
|
40
|
+
material: Base64.strict_decode64(ENV["MYAPP_KEY"]),
|
|
41
|
+
alg: "hmac-sha256"
|
|
42
|
+
}
|
|
43
|
+
# or using a public/private key pair:
|
|
44
|
+
# default_key: { material: IO.read("app/config/pubkey.pem"), alg: "ed25519" }
|
|
36
45
|
```
|
|
37
46
|
|
|
38
|
-
|
|
47
|
+
In this example, the middleware requires a valid HTTP Message Signature
|
|
48
|
+
for all endpoints except /login.
|
|
49
|
+
|
|
50
|
+
To learn how to sign requests, see the
|
|
51
|
+
[Signing Requests](#signing-http-requests-and-responses) section.
|
|
52
|
+
|
|
53
|
+
#### Using a configuration file
|
|
54
|
+
|
|
55
|
+
For more complex setups, you can load configuration from a file, e.g.:
|
|
39
56
|
|
|
40
57
|
```ruby
|
|
41
58
|
# config.ru
|
|
42
|
-
use Rack::Auth::Signature,
|
|
59
|
+
use Rack::Auth::Signature,
|
|
60
|
+
except: "/login",
|
|
43
61
|
config_path: "app/configuration/http-signatures.yml"
|
|
44
62
|
```
|
|
45
63
|
|
|
46
|
-
|
|
64
|
+
#### Rails
|
|
65
|
+
|
|
66
|
+
In a Rails application, add the middleware in your configuration:
|
|
47
67
|
|
|
48
68
|
```ruby
|
|
49
69
|
# config/application.rb
|
|
50
|
-
config.middleware.use Rack::Auth::Signature,
|
|
70
|
+
config.middleware.use Rack::Auth::Signature,
|
|
71
|
+
except: "/login",
|
|
51
72
|
config_path: "http-signatures.yml"
|
|
52
73
|
```
|
|
53
74
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
#### What this does?
|
|
76
|
+
|
|
77
|
+
Once enabled, all protected routes will require a valid signature
|
|
78
|
+
generated by a client using the corresponding private key. Requests
|
|
79
|
+
without a valid signature will be rejected.
|
|
80
|
+
|
|
81
|
+
#### Next steps
|
|
82
|
+
|
|
83
|
+
- See a full configuration example:
|
|
84
|
+
[examples/sinatra/http-signatures.yml](https://github.com/nomadium/linzer/tree/master/examples/sinatra/http-signatures.yml)
|
|
85
|
+
|
|
86
|
+
- Browse the middleware implementation for all options:
|
|
87
|
+
[lib/rack/auth/signature.rb](https://github.com/nomadium/linzer/tree/master/lib/rack/auth/signature.rb)
|
|
88
|
+
|
|
89
|
+
- For more specific scenarios and use cases, continue below.
|
|
90
|
+
|
|
91
|
+
### Signing HTTP requests and responses
|
|
60
92
|
|
|
61
|
-
|
|
93
|
+
Linzer signs HTTP requests by adding the required `Signature` and
|
|
94
|
+
`Signature-Input` headers based on selected request components (e.g.
|
|
95
|
+
method, path, headers, etc).
|
|
62
96
|
|
|
63
|
-
|
|
97
|
+
Choose your client:
|
|
64
98
|
|
|
65
|
-
|
|
99
|
+
- Use the [http gem](https://github.com/httprb/http) → recommended (simplest)
|
|
100
|
+
- Use `Net::HTTP` → lower-level control
|
|
101
|
+
- Use `Linzer::HTTP` → quick experiments / debugging
|
|
66
102
|
|
|
67
|
-
####
|
|
103
|
+
#### Using [http gem](https://github.com/httprb/http)
|
|
68
104
|
|
|
69
105
|
```ruby
|
|
70
106
|
# first require http signatures feature class ready to be used with http gem:
|
|
@@ -85,7 +121,7 @@ response.body.to_s
|
|
|
85
121
|
=> "protected content..."
|
|
86
122
|
```
|
|
87
123
|
|
|
88
|
-
####
|
|
124
|
+
#### Using `Net::HTTP` (manual control)
|
|
89
125
|
|
|
90
126
|
```ruby
|
|
91
127
|
key = Linzer.generate_ed25519_key
|
|
@@ -111,7 +147,7 @@ request["signature-input"]
|
|
|
111
147
|
# => "sig1=(\"@method\" \"@request-target\" \"date\" ..."}
|
|
112
148
|
```
|
|
113
149
|
|
|
114
|
-
Then
|
|
150
|
+
Then send the request:
|
|
115
151
|
|
|
116
152
|
```ruby
|
|
117
153
|
require "net/http"
|
|
@@ -152,10 +188,7 @@ response = http.request(request)
|
|
|
152
188
|
# => #<Net::HTTPOK 200 OK readbody=true>
|
|
153
189
|
```
|
|
154
190
|
|
|
155
|
-
####
|
|
156
|
-
|
|
157
|
-
(This client is probably not suitable for production use but could be useful
|
|
158
|
-
enough to get started. It's build on top of Net::HTTP.)
|
|
191
|
+
#### Using the built-in client
|
|
159
192
|
|
|
160
193
|
```ruby
|
|
161
194
|
key = Linzer.generate_rsa_pss_sha512_key(4096)
|
|
@@ -172,13 +205,62 @@ response =
|
|
|
172
205
|
=> #<Net::HTTPOK 200 OK readbody=true>
|
|
173
206
|
```
|
|
174
207
|
|
|
175
|
-
|
|
208
|
+
(This client is intended for testing and exploration.
|
|
209
|
+
For production use, prefer a full-featured HTTP client).
|
|
176
210
|
|
|
177
|
-
|
|
178
|
-
[as shown above](#tldr-i-just-want-to-protect-my-application).
|
|
211
|
+
#### Signing HTTP responses (server-side)
|
|
179
212
|
|
|
180
|
-
|
|
181
|
-
|
|
213
|
+
You can sign responses using the same API as for requests, e.g.:
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
put "/baz" do
|
|
217
|
+
...
|
|
218
|
+
response
|
|
219
|
+
# => #<Sinatra::Response:0x0000000109ac40b8 ...
|
|
220
|
+
response.headers["x-custom-app-header"] = "..."
|
|
221
|
+
Linzer.sign!(response,
|
|
222
|
+
key: my_key,
|
|
223
|
+
components: %w[@status content-type content-digest x-custom-app-header],
|
|
224
|
+
label: "sig1",
|
|
225
|
+
params: {
|
|
226
|
+
created: Time.now.to_i
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
response["signature"]
|
|
230
|
+
# => "sig1=:2TPCzD4l48bg6LMcVXdV9u..."
|
|
231
|
+
response["signature-input"]
|
|
232
|
+
# => "sig1=(\"@status\" \"content-type\" \"content-digest\"..."
|
|
233
|
+
...
|
|
234
|
+
end
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Verifying HTTP signatures
|
|
238
|
+
|
|
239
|
+
Linzer verifies incoming requests (or responses) by checking:
|
|
240
|
+
|
|
241
|
+
- the signature is valid for the given key
|
|
242
|
+
- the signed components match the actual request
|
|
243
|
+
- any signature parameters (e.g. created, expires) are valid
|
|
244
|
+
|
|
245
|
+
If verification fails, an exception is raised explaining the reason.
|
|
246
|
+
|
|
247
|
+
#### Recommended: Rack middleware
|
|
248
|
+
|
|
249
|
+
The easiest way to verify incoming requests is via middleware:
|
|
250
|
+
|
|
251
|
+
```ruby
|
|
252
|
+
use Rack::Auth::Signature, except: "/login"
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
This automatically:
|
|
256
|
+
|
|
257
|
+
- verifies all incoming requests
|
|
258
|
+
- rejects invalid or unsigned requests
|
|
259
|
+
- integrates cleanly with Rack-based frameworks (Rails, Sinatra, etc.)
|
|
260
|
+
|
|
261
|
+
#### Manual verification (controller / route level)
|
|
262
|
+
|
|
263
|
+
If you need more control, you can verify incoming requests manually:
|
|
182
264
|
|
|
183
265
|
```ruby
|
|
184
266
|
post "/foo" do
|
|
@@ -190,18 +272,31 @@ post "/foo" do
|
|
|
190
272
|
# "PATH_INFO" => "/api",
|
|
191
273
|
# ...
|
|
192
274
|
|
|
193
|
-
result = Linzer.verify!(request, key: some_client_key)
|
|
275
|
+
result = Linzer.verify!(request, key: some_client_key) rescue false
|
|
194
276
|
# => true
|
|
195
277
|
...
|
|
278
|
+
# proceed with trusted request
|
|
196
279
|
end
|
|
197
280
|
```
|
|
198
281
|
|
|
199
|
-
If the signature is missing or invalid,
|
|
200
|
-
exception with a message clarifying why the request signature failed verification.
|
|
282
|
+
If the signature is missing or invalid, verify! will raise an exception.
|
|
201
283
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
284
|
+
```ruby
|
|
285
|
+
head "/bar" do
|
|
286
|
+
begin
|
|
287
|
+
Linzer.verify!(request, key: key)
|
|
288
|
+
rescue Linzer::VerifyError => e
|
|
289
|
+
halt 401, e.message
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### Dynamic key lookup
|
|
295
|
+
|
|
296
|
+
In many cases, the verification key depends on the `keyid` parameter provided in
|
|
297
|
+
the signature.
|
|
298
|
+
|
|
299
|
+
You can supply a block to resolve keys dynamically:
|
|
205
300
|
|
|
206
301
|
```ruby
|
|
207
302
|
get "/bar" do
|
|
@@ -211,14 +306,22 @@ get "/bar" do
|
|
|
211
306
|
end
|
|
212
307
|
# => true
|
|
213
308
|
...
|
|
309
|
+
# request is now verified
|
|
214
310
|
end
|
|
215
311
|
```
|
|
216
312
|
|
|
217
|
-
|
|
313
|
+
This is useful when:
|
|
314
|
+
|
|
315
|
+
- you have multiple clients
|
|
316
|
+
- keys are stored in a database or external service
|
|
317
|
+
- keys rotate over time
|
|
218
318
|
|
|
219
|
-
|
|
319
|
+
#### Verifying responses (client-side)
|
|
320
|
+
|
|
321
|
+
As expected, signed responses are verified using the same API shown previously:
|
|
220
322
|
|
|
221
323
|
```ruby
|
|
324
|
+
...
|
|
222
325
|
response
|
|
223
326
|
# => #<Net::HTTPOK 200 OK readbody=true>
|
|
224
327
|
response.body
|
|
@@ -228,43 +331,26 @@ result = Linzer.verify!(response, key: pubkey, no_older_than: 600)
|
|
|
228
331
|
# => true
|
|
229
332
|
```
|
|
230
333
|
|
|
231
|
-
###
|
|
334
|
+
### Using a custom HTTP library
|
|
232
335
|
|
|
233
|
-
|
|
234
|
-
|
|
336
|
+
If you’re using an HTTP library or framework other than Rack, http gem or
|
|
337
|
+
`Net::HTTP`, you can plug in your own adapter with very little effort.
|
|
235
338
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
components: %w[@status content-type content-digest x-custom-app-header],
|
|
245
|
-
label: "sig1",
|
|
246
|
-
params: {
|
|
247
|
-
created: Time.now.to_i
|
|
248
|
-
}
|
|
249
|
-
)
|
|
250
|
-
response["signature"]
|
|
251
|
-
# => "sig1=:2TPCzD4l48bg6LMcVXdV9u..."
|
|
252
|
-
response["signature-input"]
|
|
253
|
-
# => "sig1=(\"@status\" \"content-type\" \"content-digest\"..."
|
|
254
|
-
...
|
|
255
|
-
end
|
|
256
|
-
```
|
|
339
|
+
In most cases, implementing an adapter just means mapping your library’s
|
|
340
|
+
request/response objects to the small interface Linzer expects,
|
|
341
|
+
then registering it.
|
|
342
|
+
|
|
343
|
+
To do this:
|
|
344
|
+
|
|
345
|
+
- implement a simple adapter for your request/response objects
|
|
346
|
+
- register it with `Linzer::Message`
|
|
257
347
|
|
|
258
|
-
|
|
348
|
+
You can use the existing adapters as references:
|
|
259
349
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
[example adapter for http gem response](https://github.com/nomadium/linzer/blob/master/lib/linzer/message/adapter/http_gem/response.rb)
|
|
263
|
-
included with this gem or the ones
|
|
264
|
-
[provided out of the box](https://github.com/nomadium/linzer/blob/master/lib/linzer/message/adapter).
|
|
350
|
+
- [HTTP gem response adapter](https://github.com/nomadium/linzer/blob/master/lib/linzer/message/adapter/http_gem/response.rb)
|
|
351
|
+
- [Built-in adapters](https://github.com/nomadium/linzer/blob/master/lib/linzer/message/adapter)
|
|
265
352
|
|
|
266
|
-
|
|
267
|
-
see this example:
|
|
353
|
+
Example of how to register an adapter before using a custom HTTP library:
|
|
268
354
|
|
|
269
355
|
```ruby
|
|
270
356
|
Linzer::Message.register_adapter(HTTP::Response, Linzer::Message::Adapter::HTTPGem::Response)
|
|
@@ -278,22 +364,19 @@ response["signature-input"]
|
|
|
278
364
|
result = Linzer.verify!(response, key: my_key)
|
|
279
365
|
# => true
|
|
280
366
|
```
|
|
281
|
-
---
|
|
282
367
|
|
|
283
|
-
|
|
284
|
-
control on how the signing and verification routines are performed, Linzer allows
|
|
285
|
-
to manipulate instances of internal HTTP messages (requests & responses, see
|
|
286
|
-
`Linzer::Message` class and available adapters), signature objects
|
|
287
|
-
(`Linzer::Signature`) and how to register additional message adapters for any
|
|
288
|
-
HTTP ruby library not supported out of the box by this gem.
|
|
368
|
+
### Advanced verification
|
|
289
369
|
|
|
290
|
-
|
|
370
|
+
For low-level control over signing and verification, Linzer
|
|
371
|
+
exposes internal message and signature objects. This allows
|
|
372
|
+
you to work directly with `Linzer::Message` and `Linzer::Signature`,
|
|
373
|
+
or integrate custom HTTP adapters if needed.
|
|
291
374
|
|
|
292
|
-
####
|
|
375
|
+
#### Verifying a signature manually
|
|
293
376
|
|
|
294
377
|
```ruby
|
|
295
378
|
test_ed25519_key_pub = key.material.public_to_pem
|
|
296
|
-
# => "-----BEGIN PUBLIC KEY-----\
|
|
379
|
+
# => "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAK1ZrC4JqC356pRs..."
|
|
297
380
|
|
|
298
381
|
pubkey = Linzer.new_ed25519_public_key(test_ed25519_key_pub, "some-key-ed25519")
|
|
299
382
|
# => #<Linzer::Ed25519::Key:0x00000fe19b9384b0
|
|
@@ -306,53 +389,45 @@ Linzer.verify(pubkey, message, signature)
|
|
|
306
389
|
# => true
|
|
307
390
|
```
|
|
308
391
|
|
|
309
|
-
|
|
392
|
+
#### Preventing replay attacks
|
|
310
393
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
```
|
|
394
|
+
To reduce the risk of replay attacks (e.g. reusing a captured
|
|
395
|
+
valid request), you can validate the `created` timestamp in the signature.
|
|
314
396
|
|
|
315
|
-
|
|
316
|
-
`::verify` will raise if the `created` parameter of the signature is older than the given number of seconds.
|
|
317
|
-
|
|
318
|
-
#### What if an invalid signature if verified?
|
|
397
|
+
Linzer supports this via the `no_older_than` option:
|
|
319
398
|
|
|
320
399
|
```ruby
|
|
321
|
-
|
|
322
|
-
lib/linzer/verifier.rb:38:in `verify_or_fail': Failed to verify message: Invalid signature. (Linzer::Error)
|
|
400
|
+
Linzer.verify(pubkey, message, signature, no_older_than: 500)
|
|
323
401
|
```
|
|
324
402
|
|
|
325
|
-
|
|
403
|
+
`no_older_than` expects a number of seconds, but you can pass
|
|
404
|
+
anything that to responds to `#to_i`, including an `ActiveSupport::Duration`.
|
|
326
405
|
|
|
327
|
-
|
|
406
|
+
If the signature is older than the allowed window, verification
|
|
407
|
+
fails with an error.
|
|
328
408
|
|
|
329
|
-
|
|
330
|
-
headers = {
|
|
331
|
-
"date" => "Sat, 30 Mar 2024 21:40:13 GMT",
|
|
332
|
-
"x-response-custom" => "bar"
|
|
333
|
-
}
|
|
409
|
+
## Supported algorithms
|
|
334
410
|
|
|
335
|
-
|
|
336
|
-
# or just use the response object exposed by your HTTP framework
|
|
411
|
+
Linzer currently supports the following signature algorithms:
|
|
337
412
|
|
|
338
|
-
|
|
339
|
-
|
|
413
|
+
- RSASSA-PSS (SHA-512)
|
|
414
|
+
- RSASSA-PKCS1-v1_5 (SHA-256)
|
|
415
|
+
- HMAC-SHA256
|
|
416
|
+
- Ed25519
|
|
417
|
+
- ECDSA (P-256 and P-384 curves).
|
|
340
418
|
|
|
341
|
-
|
|
419
|
+
Of the JSON Web Signature (JWS) algorithms mentioned in RFC 9421,
|
|
420
|
+
only Ed25519 is currently supported. Support for additional
|
|
421
|
+
algorithms is planned and should be straightforward to add.
|
|
342
422
|
|
|
343
|
-
|
|
344
|
-
# => {"signature"=>
|
|
345
|
-
# "sig1=:tCldwXqbISktyABrmbhszo...",
|
|
346
|
-
# "signature-input"=>"sig1=(\"@status\" \"date\" ..."}
|
|
347
|
-
|
|
348
|
-
```
|
|
423
|
+
The goal is to support as much of the RFC as possible before the 1.0 release.
|
|
349
424
|
|
|
350
|
-
|
|
425
|
+
## Documentation
|
|
351
426
|
|
|
352
|
-
|
|
427
|
+
The codebase is well-documented, and the Ruby API documentation is
|
|
428
|
+
available on [Rubydoc](https://www.rubydoc.info/gems/linzer).
|
|
353
429
|
|
|
354
|
-
|
|
355
|
-
in subsequent releases.
|
|
430
|
+
For deeper details or edge cases, the source code and unit tests are also a good reference.
|
|
356
431
|
|
|
357
432
|
## Ruby version compatibility
|
|
358
433
|
|
|
@@ -360,7 +435,17 @@ linzer is built in [Continuous Integration](https://github.com/nomadium/linzer/a
|
|
|
360
435
|
|
|
361
436
|
## Security
|
|
362
437
|
|
|
363
|
-
This gem is provided “as is” without any warranties. It has not
|
|
438
|
+
This gem is provided “as is” without any warranties. It has not
|
|
439
|
+
been independently audited for security vulnerabilities. Users
|
|
440
|
+
are advised to review the code and assess its suitability for their
|
|
441
|
+
use case, particularly in production environments.
|
|
442
|
+
|
|
443
|
+
Despite this, Linzer is already used in production by other projects
|
|
444
|
+
with security-sensitive requirements, including
|
|
445
|
+
[Mastodon](https://github.com/mastodon/mastodon)
|
|
446
|
+
([since version 4.5.0](https://docs.joinmastodon.org/spec/security/#http-message-signatures)).
|
|
447
|
+
This does not constitute a security guarantee or endorsement,
|
|
448
|
+
but it may be useful context when evaluating adoption.
|
|
364
449
|
|
|
365
450
|
## Development
|
|
366
451
|
|
data/flake.lock
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
"nodes": {
|
|
3
3
|
"bundix": {
|
|
4
4
|
"inputs": {
|
|
5
|
-
"nixpkgs":
|
|
5
|
+
"nixpkgs": [
|
|
6
|
+
"nixpkgs"
|
|
7
|
+
]
|
|
6
8
|
},
|
|
7
9
|
"locked": {
|
|
8
10
|
"lastModified": 1762235257,
|
|
@@ -20,25 +22,11 @@
|
|
|
20
22
|
},
|
|
21
23
|
"nixpkgs": {
|
|
22
24
|
"locked": {
|
|
23
|
-
"lastModified":
|
|
24
|
-
"narHash": "sha256-
|
|
25
|
+
"lastModified": 1775710090,
|
|
26
|
+
"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=",
|
|
25
27
|
"owner": "NixOS",
|
|
26
28
|
"repo": "nixpkgs",
|
|
27
|
-
"rev": "
|
|
28
|
-
"type": "github"
|
|
29
|
-
},
|
|
30
|
-
"original": {
|
|
31
|
-
"id": "nixpkgs",
|
|
32
|
-
"type": "indirect"
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
"nixpkgs_2": {
|
|
36
|
-
"locked": {
|
|
37
|
-
"lastModified": 1770115704,
|
|
38
|
-
"narHash": "sha256-KHFT9UWOF2yRPlAnSXQJh6uVcgNcWlFqqiAZ7OVlHNc=",
|
|
39
|
-
"owner": "NixOS",
|
|
40
|
-
"repo": "nixpkgs",
|
|
41
|
-
"rev": "e6eae2ee2110f3d31110d5c222cd395303343b08",
|
|
29
|
+
"rev": "4c1018dae018162ec878d42fec712642d214fdfa",
|
|
42
30
|
"type": "github"
|
|
43
31
|
},
|
|
44
32
|
"original": {
|
|
@@ -48,31 +36,19 @@
|
|
|
48
36
|
"type": "github"
|
|
49
37
|
}
|
|
50
38
|
},
|
|
51
|
-
"nixpkgs_3": {
|
|
52
|
-
"locked": {
|
|
53
|
-
"lastModified": 1678875422,
|
|
54
|
-
"narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
|
|
55
|
-
"owner": "NixOS",
|
|
56
|
-
"repo": "nixpkgs",
|
|
57
|
-
"rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
|
|
58
|
-
"type": "github"
|
|
59
|
-
},
|
|
60
|
-
"original": {
|
|
61
|
-
"id": "nixpkgs",
|
|
62
|
-
"type": "indirect"
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
39
|
"root": {
|
|
66
40
|
"inputs": {
|
|
67
41
|
"bundix": "bundix",
|
|
68
|
-
"nixpkgs": "
|
|
42
|
+
"nixpkgs": "nixpkgs",
|
|
69
43
|
"ruby-nix": "ruby-nix",
|
|
70
44
|
"systems": "systems"
|
|
71
45
|
}
|
|
72
46
|
},
|
|
73
47
|
"ruby-nix": {
|
|
74
48
|
"inputs": {
|
|
75
|
-
"nixpkgs":
|
|
49
|
+
"nixpkgs": [
|
|
50
|
+
"nixpkgs"
|
|
51
|
+
]
|
|
76
52
|
},
|
|
77
53
|
"locked": {
|
|
78
54
|
"lastModified": 1755059052,
|
data/flake.nix
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
inputs = {
|
|
3
3
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
|
|
5
|
+
systems = {
|
|
6
|
+
url = "github:nix-systems/default-linux";
|
|
7
|
+
# XXX: should work, not tested yet on MacOS
|
|
8
|
+
# url = "github:nix-systems/default";
|
|
9
|
+
inputs.nixpkgs.follows = "nixpkgs";
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
ruby-nix = {
|
|
13
|
+
url = "github:inscapist/ruby-nix";
|
|
14
|
+
inputs.nixpkgs.follows = "nixpkgs";
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
bundix = {
|
|
18
|
+
url = "github:inscapist/bundix";
|
|
19
|
+
inputs.nixpkgs.follows = "nixpkgs";
|
|
20
|
+
};
|
|
9
21
|
};
|
|
10
22
|
|
|
11
23
|
outputs = {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Linzer
|
|
4
|
+
class Message
|
|
5
|
+
module Adapter
|
|
6
|
+
# http.rb gem message adapters.
|
|
7
|
+
#
|
|
8
|
+
# Provides adapters for {HTTP::Request} and {HTTP::Response} objects
|
|
9
|
+
# from the http.rb gem.
|
|
10
|
+
#
|
|
11
|
+
# @note These adapters are loaded on-demand when using the
|
|
12
|
+
# {Linzer::HTTP::SignatureFeature}.
|
|
13
|
+
module HTTPGem
|
|
14
|
+
# Shared functionality for http.rb request and response adapters.
|
|
15
|
+
module Common
|
|
16
|
+
# Retrieves a header value by name.
|
|
17
|
+
# @param name [String] The header name
|
|
18
|
+
# @return [String, nil] The header value
|
|
19
|
+
def header(name)
|
|
20
|
+
@operation.headers[name]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Attaches a signature to the response.
|
|
24
|
+
# @param signature [Signature] The signature to attach
|
|
25
|
+
# @return [Object] The underlying response object
|
|
26
|
+
def attach!(signature)
|
|
27
|
+
signature.to_h.each { |h, v| @operation.headers[h] = v }
|
|
28
|
+
@operation
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def field(name)
|
|
34
|
+
has_tr = name.parameters["tr"]
|
|
35
|
+
return nil if has_tr # XXX: is there a library actually supporting trailers?
|
|
36
|
+
value = @operation.headers[name.value.to_s]
|
|
37
|
+
value.dup&.strip
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "linzer/message/adapter/http_gem/common"
|
|
4
|
+
|
|
3
5
|
module Linzer
|
|
4
6
|
class Message
|
|
5
7
|
module Adapter
|
|
6
|
-
# http.rb gem message adapters.
|
|
7
|
-
#
|
|
8
|
-
# Provides adapters for {HTTP::Request} and {HTTP::Response} objects
|
|
9
|
-
# from the http.rb gem.
|
|
10
|
-
#
|
|
11
|
-
# @note These adapters are loaded on-demand when using the
|
|
12
|
-
# {Linzer::HTTP::SignatureFeature}.
|
|
13
8
|
module HTTPGem
|
|
14
9
|
# Adapter for {HTTP::Request} objects from http.rb gem.
|
|
15
10
|
#
|
|
16
11
|
# Extends the generic request adapter with http.rb-specific
|
|
17
12
|
# method name retrieval.
|
|
18
13
|
class Request < Generic::Request
|
|
14
|
+
include HTTPGem::Common
|
|
15
|
+
|
|
19
16
|
private
|
|
20
17
|
|
|
21
18
|
def derived(name)
|
|
19
|
+
return @operation.uri.host if name.value == "@authority"
|
|
22
20
|
return @operation.verb.to_s.upcase if name.value == "@method"
|
|
23
21
|
super
|
|
24
22
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "linzer/message/adapter/http_gem/common"
|
|
4
|
+
|
|
3
5
|
module Linzer
|
|
4
6
|
class Message
|
|
5
7
|
module Adapter
|
|
@@ -13,6 +15,8 @@ module Linzer
|
|
|
13
15
|
#
|
|
14
16
|
# @see https://github.com/httprb/http http.rb gem
|
|
15
17
|
class Response < Generic::Response
|
|
18
|
+
include HTTPGem::Common
|
|
19
|
+
|
|
16
20
|
private
|
|
17
21
|
|
|
18
22
|
def derived(name)
|
data/lib/linzer/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: linzer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.9.
|
|
4
|
+
version: 0.7.9.beta2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Miguel Landaeta
|
|
@@ -199,6 +199,7 @@ files:
|
|
|
199
199
|
- lib/linzer/message/adapter/abstract.rb
|
|
200
200
|
- lib/linzer/message/adapter/generic/request.rb
|
|
201
201
|
- lib/linzer/message/adapter/generic/response.rb
|
|
202
|
+
- lib/linzer/message/adapter/http_gem/common.rb
|
|
202
203
|
- lib/linzer/message/adapter/http_gem/request.rb
|
|
203
204
|
- lib/linzer/message/adapter/http_gem/response.rb
|
|
204
205
|
- lib/linzer/message/adapter/net_http/request.rb
|