linzer 0.7.9 → 0.8.0.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/.standard.yml +1 -0
- data/CHANGELOG.md +19 -0
- data/README.md +63 -0
- data/Rakefile +6 -0
- data/benchmarks/profile_sign_ed25519.rb +102 -0
- data/benchmarks/profile_verify_ed25519.rb +107 -0
- data/benchmarks/sign.rb +55 -0
- data/benchmarks/verify.rb +68 -0
- data/lib/faraday/http_signature/middleware.rb +25 -4
- data/lib/linzer/common.rb +53 -23
- data/lib/linzer/ed25519.rb +4 -2
- data/lib/linzer/helper.rb +34 -15
- data/lib/linzer/hmac.rb +14 -12
- data/lib/linzer/http/signature_feature.rb +15 -4
- data/lib/linzer/http/structured_field.rb +145 -0
- data/lib/linzer/http.rb +13 -7
- data/lib/linzer/jws.rb +4 -4
- data/lib/linzer/key.rb +20 -2
- data/lib/linzer/message/adapter/abstract.rb +36 -22
- data/lib/linzer/message/adapter/generic/request.rb +1 -0
- data/lib/linzer/message/adapter.rb +0 -3
- data/lib/linzer/message/field/parser.rb +5 -5
- data/lib/linzer/message/field.rb +55 -3
- data/lib/linzer/message/overlay.rb +143 -0
- data/lib/linzer/message/wrapper.rb +0 -2
- data/lib/linzer/message.rb +18 -0
- data/lib/linzer/rack.rb +24 -0
- data/lib/linzer/rsa_pss.rb +4 -4
- data/lib/linzer/signature/context.rb +80 -0
- data/lib/linzer/signature/profile/base.rb +43 -0
- data/lib/linzer/signature/profile/example.rb +39 -0
- data/lib/linzer/signature/profile/web_bot_auth.rb +201 -0
- data/lib/linzer/signature/profile.rb +70 -0
- data/lib/linzer/signature.rb +147 -32
- data/lib/linzer/signer.rb +36 -15
- data/lib/linzer/verifier.rb +9 -3
- data/lib/linzer/version.rb +1 -1
- data/lib/linzer.rb +5 -4
- metadata +13 -41
data/lib/linzer/signature.rb
CHANGED
|
@@ -26,12 +26,14 @@ module Linzer
|
|
|
26
26
|
# @see https://www.rfc-editor.org/rfc/rfc9421.html#section-4 RFC 9421 Section 4
|
|
27
27
|
class Signature
|
|
28
28
|
# @api private
|
|
29
|
-
# Use {.build} to create Signature instances.
|
|
30
|
-
def initialize(metadata, value, label, parameters = {})
|
|
31
|
-
@metadata
|
|
32
|
-
@value
|
|
33
|
-
@parameters
|
|
34
|
-
@label
|
|
29
|
+
# Use {.build} or {.from_components} to create Signature instances.
|
|
30
|
+
def initialize(metadata, value, label, parameters = {}, parsed_items: nil, headers: nil)
|
|
31
|
+
@metadata = metadata.clone.freeze
|
|
32
|
+
@value = value.clone.freeze
|
|
33
|
+
@parameters = parameters.clone.freeze
|
|
34
|
+
@label = label.clone.freeze
|
|
35
|
+
@parsed_items = parsed_items&.freeze
|
|
36
|
+
@headers = headers&.freeze
|
|
35
37
|
freeze
|
|
36
38
|
end
|
|
37
39
|
|
|
@@ -74,6 +76,20 @@ module Linzer
|
|
|
74
76
|
FieldId.deserialize_components(serialized_components)
|
|
75
77
|
end
|
|
76
78
|
|
|
79
|
+
# Builds FieldId objects for each covered component.
|
|
80
|
+
#
|
|
81
|
+
# Uses {parsed_items} when available to create {FastIdentifier} objects
|
|
82
|
+
# that bypass Starry re-parsing. Falls back to constructing full
|
|
83
|
+
# {FieldId} objects from the serialized strings.
|
|
84
|
+
#
|
|
85
|
+
# Returns a fresh array each time because some adapter methods may
|
|
86
|
+
# mutate item parameters during field lookup (e.g., deleting "req").
|
|
87
|
+
#
|
|
88
|
+
# @return [Array<FastIdentifier, FieldId>] FieldId objects for each component
|
|
89
|
+
def field_ids
|
|
90
|
+
build_field_ids
|
|
91
|
+
end
|
|
92
|
+
|
|
77
93
|
# Returns the signature creation timestamp.
|
|
78
94
|
#
|
|
79
95
|
# @return [Integer, nil] Unix timestamp when the signature was created,
|
|
@@ -132,20 +148,60 @@ module Linzer
|
|
|
132
148
|
# @example Attaching to a Net::HTTP request
|
|
133
149
|
# signature.to_h.each { |name, value| request[name] = value }
|
|
134
150
|
def to_h
|
|
151
|
+
return @headers if @headers
|
|
152
|
+
|
|
153
|
+
items = @parsed_items || serialized_components.map { |c| HTTP::StructuredField.parse_item(c) }
|
|
135
154
|
{
|
|
136
|
-
"signature" =>
|
|
137
|
-
"signature-input" =>
|
|
138
|
-
label =>
|
|
139
|
-
serialized_components.map { |c| Starry.parse_item(c) },
|
|
140
|
-
parameters
|
|
141
|
-
)
|
|
155
|
+
"signature" => HTTP::StructuredField.serialize({label => value}),
|
|
156
|
+
"signature-input" => HTTP::StructuredField.serialize({
|
|
157
|
+
label => HTTP::StructuredField::InnerList.new(items, parameters)
|
|
142
158
|
})
|
|
143
159
|
}
|
|
144
160
|
end
|
|
145
161
|
|
|
162
|
+
private
|
|
163
|
+
|
|
164
|
+
def build_field_ids
|
|
165
|
+
if @parsed_items && @parsed_items.size == @metadata.size
|
|
166
|
+
@metadata.each_with_index.map do |serialized, i|
|
|
167
|
+
item = @parsed_items[i]
|
|
168
|
+
# Clone items that have parameters since the adapter's retrieve
|
|
169
|
+
# method may mutate parameters (e.g., deleting "req").
|
|
170
|
+
unless item.parameters.empty?
|
|
171
|
+
item = HTTP::StructuredField::Item.new(item.value, item.parameters.dup)
|
|
172
|
+
end
|
|
173
|
+
Message::Field::FastIdentifier.new(serialized, item)
|
|
174
|
+
end
|
|
175
|
+
else
|
|
176
|
+
@metadata.map { |c| FieldId.new(field_name: c) }
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
146
180
|
class << self
|
|
147
181
|
private :new
|
|
148
182
|
|
|
183
|
+
# Creates a Signature directly from its constituent parts.
|
|
184
|
+
#
|
|
185
|
+
# This avoids the serialize-then-parse round-trip when the caller
|
|
186
|
+
# (e.g. {Signer.sign}) already has all the data.
|
|
187
|
+
#
|
|
188
|
+
# @api private
|
|
189
|
+
# @param components [Array<String>] Serialized component identifiers
|
|
190
|
+
# @param raw_signature [String] The raw signature bytes
|
|
191
|
+
# @param label [String] The signature label
|
|
192
|
+
# @param parameters [Hash] Signature parameters (symbol keys)
|
|
193
|
+
# @param parsed_items [Array<Starry::Item>] Pre-parsed component items
|
|
194
|
+
# @param headers [Hash] Pre-serialized header strings
|
|
195
|
+
# @return [Signature] The constructed signature
|
|
196
|
+
def from_components(components:, raw_signature:, label:, parameters:, parsed_items:, headers:)
|
|
197
|
+
# Signature stores parameters with string keys (as produced by Starry
|
|
198
|
+
# parsing). Convert symbol keys from Signer to match.
|
|
199
|
+
string_params = {}
|
|
200
|
+
parameters.each { |k, v| string_params[k.to_s] = v }
|
|
201
|
+
new(components, raw_signature, label, string_params,
|
|
202
|
+
parsed_items: parsed_items, headers: headers)
|
|
203
|
+
end
|
|
204
|
+
|
|
149
205
|
# Builds a Signature from HTTP headers.
|
|
150
206
|
#
|
|
151
207
|
# Parses the `signature` and `signature-input` headers according to
|
|
@@ -178,25 +234,26 @@ module Linzer
|
|
|
178
234
|
def build(headers, options = {})
|
|
179
235
|
basic_validate headers
|
|
180
236
|
headers.transform_keys!(&:downcase)
|
|
237
|
+
headers.transform_values! { |v| v.encode(Encoding::ASCII) }
|
|
181
238
|
validate headers
|
|
182
239
|
|
|
183
|
-
input =
|
|
240
|
+
input = HTTP::StructuredField.parse_dictionary(
|
|
241
|
+
headers["signature-input"],
|
|
242
|
+
field_name: "signature-input"
|
|
243
|
+
)
|
|
244
|
+
|
|
184
245
|
reject_multiple_signatures if input.size > 1 && options[:label].nil?
|
|
185
246
|
label = options[:label] || input.keys.first
|
|
186
247
|
|
|
187
|
-
|
|
188
|
-
fail_with_signature_not_found label unless signature.key?(label)
|
|
189
|
-
|
|
190
|
-
raw_signature =
|
|
191
|
-
signature[label].value
|
|
192
|
-
.force_encoding(Encoding::ASCII_8BIT)
|
|
248
|
+
raw_signature = extract_raw_signature(headers["signature"], label)
|
|
193
249
|
|
|
194
250
|
fail_due_invalid_components unless input[label].value.respond_to?(:each)
|
|
195
251
|
|
|
196
|
-
|
|
252
|
+
parsed_items = input[label].value
|
|
253
|
+
components = serialize_parsed_items(parsed_items)
|
|
197
254
|
parameters = input[label].parameters
|
|
198
255
|
|
|
199
|
-
new(components, raw_signature, label, parameters)
|
|
256
|
+
new(components, raw_signature, label, parameters, parsed_items: parsed_items)
|
|
200
257
|
end
|
|
201
258
|
|
|
202
259
|
private
|
|
@@ -223,19 +280,77 @@ module Linzer
|
|
|
223
280
|
raise Error.new "Unexpected value for covered components."
|
|
224
281
|
end
|
|
225
282
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
283
|
+
# Extracts the raw signature bytes for a given label from the
|
|
284
|
+
# signature header without a full Starry dictionary parse.
|
|
285
|
+
#
|
|
286
|
+
# The signature header format is: label=:base64data:
|
|
287
|
+
# For multiple signatures: label1=:b64:, label2=:b64:
|
|
288
|
+
#
|
|
289
|
+
# Falls back to full Starry parsing for non-trivial cases.
|
|
290
|
+
#
|
|
291
|
+
# @param header_value [String] the raw signature header
|
|
292
|
+
# @param label [String] the signature label to extract
|
|
293
|
+
# @return [String] the decoded signature bytes (ASCII-8BIT)
|
|
294
|
+
# @raise [Error] if the label is not found or decoding fails
|
|
295
|
+
def extract_raw_signature(header_value, label)
|
|
296
|
+
value = header_value.is_a?(String) ? header_value : header_value.to_s
|
|
297
|
+
prefix = "#{label}=:"
|
|
298
|
+
|
|
299
|
+
# Fast path: single signature (most common case)
|
|
300
|
+
if value.start_with?(prefix)
|
|
301
|
+
end_idx = value.index(":", prefix.length)
|
|
302
|
+
if end_idx
|
|
303
|
+
encoded = value[prefix.length...end_idx]
|
|
304
|
+
return Base64.strict_decode64(encoded)
|
|
305
|
+
.force_encoding(Encoding::ASCII_8BIT)
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# Multi-signature or unusual format: find the right entry
|
|
310
|
+
# Split on comma-separated dictionary members
|
|
311
|
+
value.split(",").each do |entry|
|
|
312
|
+
entry = entry.strip
|
|
313
|
+
if entry.start_with?(prefix)
|
|
314
|
+
end_idx = entry.index(":", prefix.length)
|
|
315
|
+
if end_idx
|
|
316
|
+
encoded = entry[prefix.length...end_idx]
|
|
317
|
+
return Base64.strict_decode64(encoded)
|
|
318
|
+
.force_encoding(Encoding::ASCII_8BIT)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Label not found via fast path — fall back to Starry
|
|
324
|
+
signature = HTTP::StructuredField.parse_dictionary(
|
|
325
|
+
value.encode(Encoding::US_ASCII),
|
|
326
|
+
field_name: "signature"
|
|
327
|
+
)
|
|
328
|
+
fail_with_signature_not_found label unless signature.key?(label)
|
|
329
|
+
signature[label].value.force_encoding(Encoding::ASCII_8BIT)
|
|
330
|
+
rescue ArgumentError
|
|
331
|
+
# Base64 decode failed — fall back to Starry
|
|
332
|
+
signature = HTTP::StructuredField.parse_dictionary(
|
|
333
|
+
value.encode(Encoding::US_ASCII),
|
|
334
|
+
field_name: "signature")
|
|
335
|
+
fail_with_signature_not_found label unless signature.key?(label)
|
|
336
|
+
signature[label].value.force_encoding(Encoding::ASCII_8BIT)
|
|
230
337
|
end
|
|
231
338
|
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
339
|
+
# Serializes parsed structured field items to their RFC 8941
|
|
340
|
+
# string representations.
|
|
341
|
+
#
|
|
342
|
+
# Serialization is delegated to `Starry.serialize_item` to ensure
|
|
343
|
+
# consistent RFC-compliant formatting of structured field items and
|
|
344
|
+
# parameters.
|
|
345
|
+
#
|
|
346
|
+
# @param items [Array<Starry::Item>]
|
|
347
|
+
# Parsed structured field items.
|
|
348
|
+
#
|
|
349
|
+
# @return [Array<String>]
|
|
350
|
+
# The serialized structured field item representations.
|
|
351
|
+
#
|
|
352
|
+
def serialize_parsed_items(items)
|
|
353
|
+
items.map { |item| HTTP::StructuredField.serialize_item(item) }
|
|
239
354
|
end
|
|
240
355
|
end
|
|
241
356
|
end
|
data/lib/linzer/signer.rb
CHANGED
|
@@ -68,16 +68,31 @@ module Linzer
|
|
|
68
68
|
# tag: "my-app"
|
|
69
69
|
# )
|
|
70
70
|
def sign(key, message, components, options = {})
|
|
71
|
-
serialized_components =
|
|
72
|
-
|
|
71
|
+
serialized_components, field_ids =
|
|
72
|
+
FieldId.serialize_components_with_field_ids(Array(components))
|
|
73
|
+
validate key, message, serialized_components, field_ids: field_ids
|
|
74
|
+
|
|
75
|
+
# Reuse the already-parsed items from field_ids
|
|
76
|
+
parsed_items = field_ids.map(&:item)
|
|
73
77
|
|
|
74
78
|
parameters = populate_parameters(key, options)
|
|
75
|
-
signature_base = signature_base(message, serialized_components, parameters
|
|
79
|
+
signature_base = signature_base(message, serialized_components, parameters,
|
|
80
|
+
field_ids: field_ids)
|
|
76
81
|
|
|
77
|
-
|
|
82
|
+
raw_signature = key.sign(signature_base)
|
|
78
83
|
label = options[:label] || DEFAULT_LABEL
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
# Build the signature directly, bypassing the serialize -> parse round-trip
|
|
86
|
+
headers = serialize(raw_signature, serialized_components, parameters, label)
|
|
87
|
+
|
|
88
|
+
Linzer::Signature.from_components(
|
|
89
|
+
components: serialized_components,
|
|
90
|
+
raw_signature: raw_signature,
|
|
91
|
+
label: label,
|
|
92
|
+
parameters: parameters,
|
|
93
|
+
parsed_items: parsed_items,
|
|
94
|
+
headers: headers
|
|
95
|
+
)
|
|
81
96
|
end
|
|
82
97
|
|
|
83
98
|
# Returns the default signature label.
|
|
@@ -91,19 +106,22 @@ module Linzer
|
|
|
91
106
|
|
|
92
107
|
# Validates signing inputs.
|
|
93
108
|
# @raise [SigningError] If any input is invalid
|
|
94
|
-
def validate(key, message, components)
|
|
109
|
+
def validate(key, message, components, field_ids: nil)
|
|
95
110
|
msg = "Message cannot be signed with null %s"
|
|
96
111
|
raise SigningError, msg % "value" if message.nil?
|
|
97
112
|
raise SigningError, msg % "key" if key.nil?
|
|
98
113
|
raise SigningError, msg % "component" if components.nil?
|
|
99
114
|
|
|
100
115
|
begin
|
|
101
|
-
validate_components message, components
|
|
116
|
+
validate_components message, components, field_ids: field_ids
|
|
102
117
|
rescue Error => ex
|
|
103
118
|
raise SigningError, ex.message, cause: ex
|
|
104
119
|
end
|
|
105
120
|
end
|
|
106
121
|
|
|
122
|
+
RESERVED_OPTIONS = %i[created keyid label].freeze
|
|
123
|
+
private_constant :RESERVED_OPTIONS
|
|
124
|
+
|
|
107
125
|
# Builds the signature parameters hash from options and key.
|
|
108
126
|
# @return [Hash] The populated parameters
|
|
109
127
|
def populate_parameters(key, options)
|
|
@@ -114,22 +132,25 @@ module Linzer
|
|
|
114
132
|
key_id = options[:keyid] || (key.key_id if key.respond_to?(:key_id))
|
|
115
133
|
parameters[:keyid] = key_id unless key_id.nil?
|
|
116
134
|
|
|
117
|
-
|
|
135
|
+
options.each { |k, v| parameters[k] = v unless RESERVED_OPTIONS.include?(k) }
|
|
118
136
|
|
|
119
137
|
parameters
|
|
120
138
|
end
|
|
121
139
|
|
|
122
140
|
# Serializes the signature into HTTP header format.
|
|
141
|
+
#
|
|
142
|
+
# Uses direct string building instead of Starry.serialize to avoid
|
|
143
|
+
# the overhead of generic structured field serialization.
|
|
144
|
+
#
|
|
123
145
|
# @return [Hash] Hash with "signature" and "signature-input" keys
|
|
124
146
|
def serialize(signature, components, parameters, label)
|
|
147
|
+
sig_b64 = Base64.strict_encode64(signature)
|
|
148
|
+
input_params = HTTP::StructuredField.serialize_parameters(parameters)
|
|
149
|
+
components_str = components.join(" ")
|
|
150
|
+
|
|
125
151
|
{
|
|
126
|
-
"signature"
|
|
127
|
-
"signature-input" =>
|
|
128
|
-
Starry.serialize(label =>
|
|
129
|
-
Starry::InnerList.new(
|
|
130
|
-
components.map { |c| Starry.parse_item(c) },
|
|
131
|
-
parameters
|
|
132
|
-
))
|
|
152
|
+
"signature" => "#{label}=:#{sig_b64}:",
|
|
153
|
+
"signature-input" => "#{label}=(#{components_str})#{input_params}"
|
|
133
154
|
}
|
|
134
155
|
end
|
|
135
156
|
end
|
data/lib/linzer/verifier.rb
CHANGED
|
@@ -59,7 +59,12 @@ module Linzer
|
|
|
59
59
|
parameters = signature.parameters
|
|
60
60
|
serialized_components = signature.serialized_components
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
# Build fresh field_ids for signature_base (validate already
|
|
63
|
+
# consumed its own set, which may have been mutated by adapters).
|
|
64
|
+
field_ids = signature.field_ids
|
|
65
|
+
|
|
66
|
+
signature_base = signature_base(message, serialized_components, parameters,
|
|
67
|
+
field_ids: field_ids)
|
|
63
68
|
|
|
64
69
|
verify_or_fail key, signature.value, signature_base
|
|
65
70
|
end
|
|
@@ -78,10 +83,11 @@ module Linzer
|
|
|
78
83
|
end
|
|
79
84
|
|
|
80
85
|
raise VerifyError, "Signature raw value to cannot be null" if signature.value.nil?
|
|
81
|
-
raise VerifyError, "Components cannot be null" if signature.
|
|
86
|
+
raise VerifyError, "Components cannot be null" if signature.serialized_components.nil?
|
|
82
87
|
|
|
83
88
|
begin
|
|
84
|
-
validate_components message, signature.serialized_components
|
|
89
|
+
validate_components message, signature.serialized_components,
|
|
90
|
+
field_ids: signature.field_ids
|
|
85
91
|
rescue Error => ex
|
|
86
92
|
raise VerifyError, ex.message, cause: ex
|
|
87
93
|
end
|
data/lib/linzer/version.rb
CHANGED
data/lib/linzer.rb
CHANGED
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
require "starry"
|
|
4
4
|
require "openssl"
|
|
5
|
-
require "rack"
|
|
6
5
|
require "uri"
|
|
7
6
|
require "net/http"
|
|
8
7
|
|
|
9
8
|
require_relative "linzer/version"
|
|
9
|
+
require_relative "linzer/http"
|
|
10
|
+
require_relative "linzer/http/structured_field"
|
|
10
11
|
require_relative "linzer/common"
|
|
12
|
+
require_relative "linzer/signature/context"
|
|
13
|
+
require_relative "linzer/signature/profile"
|
|
11
14
|
require_relative "linzer/helper"
|
|
12
15
|
require_relative "linzer/options"
|
|
13
16
|
require_relative "linzer/message"
|
|
14
17
|
require_relative "linzer/message/adapter"
|
|
15
18
|
require_relative "linzer/message/wrapper"
|
|
19
|
+
require_relative "linzer/message/overlay"
|
|
16
20
|
require_relative "linzer/message/field"
|
|
17
21
|
require_relative "linzer/message/field/parser"
|
|
18
22
|
require_relative "linzer/signature"
|
|
@@ -25,7 +29,6 @@ require_relative "linzer/ecdsa"
|
|
|
25
29
|
require_relative "linzer/key/helper"
|
|
26
30
|
require_relative "linzer/signer"
|
|
27
31
|
require_relative "linzer/verifier"
|
|
28
|
-
require_relative "linzer/http"
|
|
29
32
|
|
|
30
33
|
# Linzer is a Ruby library for HTTP Message Signatures as defined in RFC 9421.
|
|
31
34
|
#
|
|
@@ -157,5 +160,3 @@ module Linzer
|
|
|
157
160
|
# Used for serializing and deserializing component identifiers.
|
|
158
161
|
FieldId = Message::Field::Identifier
|
|
159
162
|
end
|
|
160
|
-
|
|
161
|
-
require_relative "rack/auth/signature"
|
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.
|
|
4
|
+
version: 0.8.0.beta2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Miguel Landaeta
|
|
@@ -23,26 +23,6 @@ dependencies:
|
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0.2'
|
|
26
|
-
- !ruby/object:Gem::Dependency
|
|
27
|
-
name: rack
|
|
28
|
-
requirement: !ruby/object:Gem::Requirement
|
|
29
|
-
requirements:
|
|
30
|
-
- - ">="
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '2.2'
|
|
33
|
-
- - "<"
|
|
34
|
-
- !ruby/object:Gem::Version
|
|
35
|
-
version: '4.0'
|
|
36
|
-
type: :runtime
|
|
37
|
-
prerelease: false
|
|
38
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
39
|
-
requirements:
|
|
40
|
-
- - ">="
|
|
41
|
-
- !ruby/object:Gem::Version
|
|
42
|
-
version: '2.2'
|
|
43
|
-
- - "<"
|
|
44
|
-
- !ruby/object:Gem::Version
|
|
45
|
-
version: '4.0'
|
|
46
26
|
- !ruby/object:Gem::Dependency
|
|
47
27
|
name: uri
|
|
48
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -63,26 +43,6 @@ dependencies:
|
|
|
63
43
|
- - ">="
|
|
64
44
|
- !ruby/object:Gem::Version
|
|
65
45
|
version: 1.0.2
|
|
66
|
-
- !ruby/object:Gem::Dependency
|
|
67
|
-
name: logger
|
|
68
|
-
requirement: !ruby/object:Gem::Requirement
|
|
69
|
-
requirements:
|
|
70
|
-
- - "~>"
|
|
71
|
-
- !ruby/object:Gem::Version
|
|
72
|
-
version: '1.7'
|
|
73
|
-
- - ">="
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: 1.7.0
|
|
76
|
-
type: :runtime
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - "~>"
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: '1.7'
|
|
83
|
-
- - ">="
|
|
84
|
-
- !ruby/object:Gem::Version
|
|
85
|
-
version: 1.7.0
|
|
86
46
|
- !ruby/object:Gem::Dependency
|
|
87
47
|
name: forwardable
|
|
88
48
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -156,6 +116,10 @@ files:
|
|
|
156
116
|
- LICENSE.txt
|
|
157
117
|
- README.md
|
|
158
118
|
- Rakefile
|
|
119
|
+
- benchmarks/profile_sign_ed25519.rb
|
|
120
|
+
- benchmarks/profile_verify_ed25519.rb
|
|
121
|
+
- benchmarks/sign.rb
|
|
122
|
+
- benchmarks/verify.rb
|
|
159
123
|
- examples/sinatra/Gemfile
|
|
160
124
|
- examples/sinatra/config.ru
|
|
161
125
|
- examples/sinatra/http-signatures.yml
|
|
@@ -175,6 +139,7 @@ files:
|
|
|
175
139
|
- lib/linzer/http.rb
|
|
176
140
|
- lib/linzer/http/bootstrap.rb
|
|
177
141
|
- lib/linzer/http/signature_feature.rb
|
|
142
|
+
- lib/linzer/http/structured_field.rb
|
|
178
143
|
- lib/linzer/jws.rb
|
|
179
144
|
- lib/linzer/key.rb
|
|
180
145
|
- lib/linzer/key/helper.rb
|
|
@@ -195,11 +160,18 @@ files:
|
|
|
195
160
|
- lib/linzer/message/adapter/rack/response.rb
|
|
196
161
|
- lib/linzer/message/field.rb
|
|
197
162
|
- lib/linzer/message/field/parser.rb
|
|
163
|
+
- lib/linzer/message/overlay.rb
|
|
198
164
|
- lib/linzer/message/wrapper.rb
|
|
199
165
|
- lib/linzer/options.rb
|
|
166
|
+
- lib/linzer/rack.rb
|
|
200
167
|
- lib/linzer/rsa.rb
|
|
201
168
|
- lib/linzer/rsa_pss.rb
|
|
202
169
|
- lib/linzer/signature.rb
|
|
170
|
+
- lib/linzer/signature/context.rb
|
|
171
|
+
- lib/linzer/signature/profile.rb
|
|
172
|
+
- lib/linzer/signature/profile/base.rb
|
|
173
|
+
- lib/linzer/signature/profile/example.rb
|
|
174
|
+
- lib/linzer/signature/profile/web_bot_auth.rb
|
|
203
175
|
- lib/linzer/signer.rb
|
|
204
176
|
- lib/linzer/verifier.rb
|
|
205
177
|
- lib/linzer/version.rb
|