Class: Linzer::Signature
- Inherits:
-
Object
- Object
- Linzer::Signature
- Defined in:
- lib/linzer/signature.rb
Overview
Represents an HTTP message signature as defined in RFC 9421.
A Signature encapsulates:
-
The raw signature bytes
-
The covered components (fields included in the signature)
-
The signature parameters (created, keyid, etc.)
-
The signature label (for identifying multiple signatures)
Signatures are immutable once created. Use Signature.build to create instances from HTTP headers, or receive them from Linzer::Signer.sign.
Instance Attribute Summary collapse
-
#label ⇒ Object
readonly
Returns the value of attribute label.
-
#metadata ⇒ Object
(also: #serialized_components)
readonly
Returns the value of attribute metadata.
-
#parameters ⇒ Object
readonly
Returns the value of attribute parameters.
-
#value ⇒ Object
(also: #bytes)
readonly
Returns the value of attribute value.
Class Method Summary collapse
-
.build(headers, options = {}) ⇒ Signature
Builds a Signature from HTTP headers.
Instance Method Summary collapse
-
#components ⇒ Array<String>
Returns the deserialized component identifiers.
-
#created ⇒ Integer?
Returns the signature creation timestamp.
-
#initialize(metadata, value, label, parameters = {}) ⇒ Signature
constructor
private
Use Signature.build to create Signature instances.
-
#older_than?(seconds) ⇒ Boolean
Checks if the signature is older than a given number of seconds.
-
#to_h ⇒ Hash{String => String}
Converts the signature to HTTP header format.
Constructor Details
#initialize(metadata, value, label, parameters = {}) ⇒ Signature
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Use build to create Signature instances.
30 31 32 33 34 35 36 |
# File 'lib/linzer/signature.rb', line 30 def initialize(, value, label, parameters = {}) = .clone.freeze @value = value.clone.freeze @parameters = parameters.clone.freeze @label = label.clone.freeze freeze end |
Instance Attribute Details
#label ⇒ Object (readonly)
Returns the value of attribute label.
54 55 56 |
# File 'lib/linzer/signature.rb', line 54 def label @label end |
#metadata ⇒ Object (readonly) Also known as: serialized_components
Returns the value of attribute metadata.
41 42 43 |
# File 'lib/linzer/signature.rb', line 41 def end |
#parameters ⇒ Object (readonly)
Returns the value of attribute parameters.
50 51 52 |
# File 'lib/linzer/signature.rb', line 50 def parameters @parameters end |
#value ⇒ Object (readonly) Also known as: bytes
Returns the value of attribute value.
45 46 47 |
# File 'lib/linzer/signature.rb', line 45 def value @value end |
Class Method Details
.build(headers, options = {}) ⇒ Signature
Builds a Signature from HTTP headers.
Parses the signature and signature-input headers according to RFC 9421 and RFC 8941 (Structured Field Values).
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/linzer/signature.rb', line 158 def build(headers, = {}) basic_validate headers headers.transform_keys!(&:downcase) validate headers input = parse_structured_field(headers, "signature-input") reject_multiple_signatures if input.size > 1 && [:label].nil? label = [:label] || input.keys.first signature = parse_structured_field(headers, "signature") fail_with_signature_not_found label unless signature.key?(label) raw_signature = signature[label].value .force_encoding(Encoding::ASCII_8BIT) fail_due_invalid_components unless input[label].value.respond_to?(:each) components = input[label].value.map { |c| Starry.serialize_item(c) } parameters = input[label].parameters new(components, raw_signature, label, parameters) end |
Instance Method Details
#components ⇒ Array<String>
Returns the deserialized component identifiers.
Unlike #serialized_components, this returns the components in a more human-readable form.
73 74 75 |
# File 'lib/linzer/signature.rb', line 73 def components FieldId.deserialize_components(serialized_components) end |
#created ⇒ Integer?
Returns the signature creation timestamp.
82 83 84 85 86 87 |
# File 'lib/linzer/signature.rb', line 82 def created Integer(parameters["created"]) rescue return nil if parameters["created"].nil? raise Error.new "Signature has a non-integer `created` parameter" end |
#older_than?(seconds) ⇒ Boolean
Checks if the signature is older than a given number of seconds.
This is useful for implementing replay attack protection by rejecting signatures that are too old.
100 101 102 103 |
# File 'lib/linzer/signature.rb', line 100 def older_than?(seconds) raise Error.new "Signature is missing the `created` parameter" if created.nil? (Time.now.to_i - created) > seconds end |
#to_h ⇒ Hash{String => String}
Converts the signature to HTTP header format.
Returns a hash suitable for setting as HTTP headers on a request or response. The hash contains signature and signature-input keys.
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/linzer/signature.rb', line 114 def to_h { "signature" => Starry.serialize({label => value}), "signature-input" => Starry.serialize({ label => Starry::InnerList.new( serialized_components.map { |c| Starry.parse_item(c) }, parameters ) }) } end |