sigstore 0.2.2 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adbc9be5acca424a61e1be380b84e86ddfb7752ec1e7e347b974a6dc7a59b34e
4
- data.tar.gz: 8448dc2e3b7db3ac9ce3d187337a18fb9615f8bc7262fe2a3c64e207fd236300
3
+ metadata.gz: 4a9a3ef5da7b2fc632b31f48e168423e1c3d12dd601621937d1dc0ddf27be250
4
+ data.tar.gz: 9daf366761da11b908f6670644976bbb12ac11c6d7037d36c754083a56be9995
5
5
  SHA512:
6
- metadata.gz: '0393afaefba1a158efd80e2e67653a218ef102db3848de301acefc99f5dbcd72c88ebc67cef4b11c573944d57169a2d0a2224cabfe0003899135ca5ba74282ca'
7
- data.tar.gz: 92521025a92dbc5776caf13326e13e0988950e95c5206586674d01a80a25907110af6271dd045f76279e7f1a97fd1aea42e06d451514327e0384d2a7d1d57ebd
6
+ metadata.gz: 7f4ccdeef1781aa702cc3bde7fa2006b0d58d6e89e0eb5ef17cf53db6570bbd50a7d65ba2c33638f09fcd9439fb565566429926497e3aaa9e7e9cee16631b86e
7
+ data.tar.gz: 361d3082ca855a0ed086ffc15cb63c011be86c6bde88afd9c0c88cc916768b8370088e6a488af4316f7e2eec94fee81f72f1f117ff349e44af7c93aad774df0e
@@ -69,7 +69,7 @@ module Sigstore
69
69
 
70
70
  intermediate_result = chain_inner(
71
71
  leaf_hash,
72
- (proof[...inner] || raise(MissingHashError, "missing left hashes")),
72
+ proof[...inner] || raise(MissingHashError, "missing left hashes"),
73
73
  log_index
74
74
  )
75
75
 
@@ -93,7 +93,7 @@ module Sigstore
93
93
 
94
94
  def self.chain_inner(seed, hashes, log_index)
95
95
  hashes.each_with_index do |hash, i|
96
- seed = if ((log_index >> i) & 1).zero?
96
+ seed = if (log_index >> i).nobits?(1)
97
97
  hash_children(seed, hash)
98
98
  else
99
99
  hash_children(hash, seed)
@@ -438,7 +438,7 @@ module Sigstore
438
438
  signature_algorithm
439
439
  entry_type
440
440
  signature]
441
- Timestamp = defined?(Data.define) ? Data.define(*args) : Struct.new(*args, keyword_init: true) # rubocop:disable Naming/ConstantName
441
+ Timestamp = defined?(Data.define) ? Data.define(*args) : Struct.new(*args) # rubocop:disable Naming/ConstantName
442
442
 
443
443
  HASHES = {
444
444
  0 => "none",
@@ -474,11 +474,6 @@ module Sigstore
474
474
  sct_extensions_bytes = string.unpack1("a#{sct_extensions_len}", offset:).b
475
475
  offset += sct_extensions_len
476
476
 
477
- unless sct_extensions_len.zero?
478
- raise Error::Unimplemented,
479
- "sct_extensions_len=#{sct_extensions_len} not supported"
480
- end
481
-
482
477
  sct_signature_alg_hash, sct_signature_alg_sign, sct_signature_len = string.unpack("CCn", offset:)
483
478
  offset += 1 + 1 + 2
484
479
  sct_signature_bytes = string.unpack1("a#{sct_signature_len}", offset:).b
@@ -19,7 +19,7 @@ require_relative "error"
19
19
  require_relative "trusted_root"
20
20
 
21
21
  module Sigstore
22
- VerificationResult = Struct.new(:success, keyword_init: true) do
22
+ VerificationResult = Struct.new(:success) do
23
23
  # @implements VerificationResult
24
24
 
25
25
  alias_method :verified?, :success
@@ -17,9 +17,9 @@
17
17
  module Sigstore
18
18
  module Rekor
19
19
  module Checkpoint
20
- Signature = Struct.new(:name, :sig_hash, :signature, keyword_init: true)
20
+ Signature = Struct.new(:name, :sig_hash, :signature)
21
21
 
22
- SignedCheckpoint = Struct.new(:signed_note, :checkpoint, keyword_init: true) do
22
+ SignedCheckpoint = Struct.new(:signed_note, :checkpoint) do
23
23
  # @implements SignedCheckpoint
24
24
 
25
25
  def self.from_text(text)
@@ -30,7 +30,7 @@ module Sigstore
30
30
  end
31
31
  end
32
32
 
33
- SignedNote = Struct.new(:note, :signatures, keyword_init: true) do
33
+ SignedNote = Struct.new(:note, :signatures) do
34
34
  # @implements SignedNote
35
35
 
36
36
  def self.from_text(text)
@@ -77,7 +77,7 @@ module Sigstore
77
77
  end
78
78
  end
79
79
 
80
- LogCheckpoint = Struct.new(:origin, :log_size, :log_hash, :other_content, keyword_init: true) do
80
+ LogCheckpoint = Struct.new(:origin, :log_size, :log_hash, :other_content) do
81
81
  # @implements LogCheckpoint
82
82
 
83
83
  def self.from_text(text)
@@ -15,6 +15,7 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require "net/http"
18
+ require_relative "../version"
18
19
 
19
20
  module Sigstore
20
21
  module Rekor
@@ -66,7 +67,8 @@ module Sigstore
66
67
 
67
68
  def post(entry)
68
69
  resp = @session.post2(@url.path.chomp("/"), entry.to_json,
69
- { "Content-Type" => "application/json", "Accept" => "application/json" })
70
+ { "Content-Type" => "application/json", "Accept" => "application/json",
71
+ "User-Agent" => Sigstore::USER_AGENT })
70
72
 
71
73
  unless resp.code == "201"
72
74
  raise Error::FailedRekorPost,
@@ -89,7 +91,8 @@ module Sigstore
89
91
  def post(expected_entry)
90
92
  data = { entries: [expected_entry] }
91
93
  resp = @session.post2(@url.path, data.to_json,
92
- { "Content-Type" => "application/json", "Accept" => "application/json" })
94
+ { "Content-Type" => "application/json", "Accept" => "application/json",
95
+ "User-Agent" => Sigstore::USER_AGENT })
93
96
 
94
97
  if resp.code != "200"
95
98
  raise Error::FailedRekorLookup,
@@ -20,6 +20,7 @@ require_relative "models"
20
20
  require_relative "oidc"
21
21
  require_relative "policy"
22
22
  require_relative "verifier"
23
+ require_relative "version"
23
24
 
24
25
  module Sigstore
25
26
  class Signer
@@ -109,7 +110,7 @@ module Sigstore
109
110
  resp = Net::HTTP.post(
110
111
  uri,
111
112
  JSON.dump(csr),
112
- { "Content-Type" => "application/json" }
113
+ { "Content-Type" => "application/json", "User-Agent" => Sigstore::USER_AGENT }
113
114
  )
114
115
 
115
116
  unless resp.code == "200"
data/lib/sigstore/tuf.rb CHANGED
@@ -19,6 +19,7 @@ require "tempfile"
19
19
  require "uri"
20
20
  require "net/http"
21
21
  require "rubygems/remote_fetcher"
22
+ require_relative "version"
22
23
 
23
24
  module Sigstore
24
25
  module TUF
@@ -133,8 +134,8 @@ module Sigstore
133
134
 
134
135
  fetcher = Gem::RemoteFetcher.fetcher
135
136
  begin
136
- response = fetcher.request(uri, Net::HTTP::Get, nil) do
137
- nil
137
+ response = fetcher.request(uri, Net::HTTP::Get, nil) do |req|
138
+ req["User-Agent"] = Sigstore::USER_AGENT
138
139
  end
139
140
  response.uri = uri
140
141
  case response
@@ -173,7 +173,9 @@ module Sigstore
173
173
  rescue JSON::ParserError
174
174
  raise Error::InvalidBundle, "invalid JSON for in-toto statement in DSSE payload"
175
175
  end
176
- verify_in_toto(input, in_toto)
176
+ if (result = verify_in_toto(input, in_toto))
177
+ return result
178
+ end
177
179
  else
178
180
  raise Sigstore::Error::Unimplemented,
179
181
  "unsupported DSSE payload type: #{bundle.dsse_envelope.payloadType.inspect}"
@@ -216,25 +218,27 @@ module Sigstore
216
218
  end
217
219
 
218
220
  def verify_in_toto(input, in_toto_payload)
219
- type = in_toto_payload.fetch("_type")
221
+ type = in_toto_payload["_type"]
220
222
  raise Error::InvalidBundle, "Expected in-toto statement, got #{type.inspect}" unless type == "https://in-toto.io/Statement/v1"
221
223
 
222
- subject = in_toto_payload.fetch("subject")
223
- raise Error::InvalidBundle, "Expected in-toto statement with subject" unless subject && subject.size == 1
224
-
225
- subject = subject.first
226
- digest = subject.fetch("digest")
227
- raise Error::InvalidBundle, "Expected in-toto statement with digest" if !digest || digest.empty?
224
+ subjects = in_toto_payload["subject"]
225
+ raise Error::InvalidBundle, "Expected in-toto statement with subject" if !subjects || subjects.empty?
228
226
 
227
+ expected_algorithm = Internal::Util.hash_algorithm_name(input.hashed_input.algorithm)
229
228
  expected_hexdigest = Internal::Util.hex_encode(input.hashed_input.digest)
230
- digest.each do |name, value|
231
- next if expected_hexdigest == value
232
229
 
233
- return VerificationFailure.new(
234
- "in-toto subject does not match for #{input.hashed_input.algorithm} of #{subject.fetch("name")}: " \
235
- "expected #{name} to be #{value}, got #{expected_hexdigest}"
236
- )
237
- end
230
+ matched = subjects.map do |subject|
231
+ digest = subject["digest"]
232
+ raise Error::InvalidBundle, "Expected in-toto statement with digest" if !digest || digest.empty?
233
+
234
+ digest[expected_algorithm] == expected_hexdigest
235
+ end.any?
236
+
237
+ return if matched
238
+
239
+ VerificationFailure.new(
240
+ "None of in-toto subjects matches artifact for #{expected_algorithm}: #{expected_hexdigest}"
241
+ )
238
242
  end
239
243
 
240
244
  public
@@ -318,13 +322,22 @@ module Sigstore
318
322
  raise Error::Unimplemented, "only x509_entry and precert_entry supported, given #{sct.entry_type.inspect}"
319
323
  end
320
324
 
321
- [sct.version, 0, sct.timestamp, sct.entry_type, signed_entry, 0].pack(<<~PACK)
325
+ [
326
+ sct.version,
327
+ 0,
328
+ sct.timestamp,
329
+ sct.entry_type,
330
+ signed_entry,
331
+ sct.extensions_bytes&.bytesize.to_i,
332
+ sct.extensions_bytes
333
+ ].pack(<<~PACK)
322
334
  C # version
323
335
  C # signature_type
324
336
  Q> # timestamp
325
337
  n # entry_type
326
338
  a#{signed_entry.bytesize} # signed_entry
327
339
  n # extensions length
340
+ a#{sct.extensions_bytes&.bytesize.to_i} # extension
328
341
  PACK
329
342
  end
330
343
 
@@ -15,5 +15,6 @@
15
15
  # limitations under the License.
16
16
 
17
17
  module Sigstore
18
- VERSION = "0.2.2"
18
+ VERSION = "0.2.3"
19
+ USER_AGENT = "sigstore-ruby/#{VERSION}".freeze
19
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sigstore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Sigstore Authors
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2025-10-25 00:00:00.000000000 Z
12
+ date: 2026-03-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: logger