pwnedkeys-filter 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pwnedkeys/filter.rb +42 -22
- 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: d9b4bf18eed6656efcf56a7f0dce23cccf9f088475b5122d7f6bb7f736a06434
|
4
|
+
data.tar.gz: e349b79a836c22e7d59b24c51b839c4c7baa1e05cf8de33ba6538d53e586bc1e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d701e80b8ad0c933c0a12c7901da61257c12f4bb666484d2254df6ed8d2427d7eae6a1ef36d7143230c235db9ab3c10ff1328af4fda0454bcde084110f6bae50
|
7
|
+
data.tar.gz: 914e681aceaecf1614ddf2e3a4f5c85f960fffb3b9532c762c4795c8038f456680bbcc53bad7e0a32284aad1ab1ba22ca1cea341d81ba5efcc0d5ef0c8dfc941
|
data/lib/pwnedkeys/filter.rb
CHANGED
@@ -17,7 +17,8 @@ module Pwnedkeys
|
|
17
17
|
class FilterClosedError < Error; end
|
18
18
|
|
19
19
|
class Header
|
20
|
-
attr_reader :signature, :
|
20
|
+
attr_reader :signature, :update_time, :entry_count, :hash_count, :hash_length
|
21
|
+
attr_accessor :revision
|
21
22
|
|
22
23
|
def self.from_fd(fd)
|
23
24
|
fd.seek(0)
|
@@ -44,14 +45,15 @@ module Pwnedkeys
|
|
44
45
|
to_s.length
|
45
46
|
end
|
46
47
|
|
47
|
-
def update!
|
48
|
-
@revision += 1
|
49
|
-
end
|
50
|
-
|
51
48
|
def entry_added!
|
52
49
|
@update_time = Time.now
|
53
50
|
@entry_count += 1
|
54
51
|
end
|
52
|
+
|
53
|
+
def to_fd(fd)
|
54
|
+
fd.rewind
|
55
|
+
fd.write(self.to_s)
|
56
|
+
end
|
55
57
|
end
|
56
58
|
private_constant :Header
|
57
59
|
|
@@ -168,6 +170,12 @@ module Pwnedkeys
|
|
168
170
|
#
|
169
171
|
# @param filename [String] the file to open.
|
170
172
|
#
|
173
|
+
# @param sync [Boolean] whether or not to sync the data to persistent storage
|
174
|
+
# after each call to `#add`. Turning this off can improve bulk addition
|
175
|
+
# performance, at the cost of potential data loss in the event of catastrophe.
|
176
|
+
#
|
177
|
+
# @param revision [Integer] set an explicit revision number for changes.
|
178
|
+
#
|
171
179
|
# @raise [SystemCallError] if anything low-level goes wrong, you will get some
|
172
180
|
# sort of `Errno`-related exception raised, such as `ENOENT` (the file you
|
173
181
|
# specified does not exist) or `EPERM` (you don't have access to the file
|
@@ -178,8 +186,8 @@ module Pwnedkeys
|
|
178
186
|
#
|
179
187
|
# @return [Pwnedkeys::Filter]
|
180
188
|
#
|
181
|
-
def self.open(filename)
|
182
|
-
filter = Pwnedkeys::Filter.new(filename)
|
189
|
+
def self.open(filename, sync: true, revision: nil)
|
190
|
+
filter = Pwnedkeys::Filter.new(filename, sync: sync, revision: revision)
|
183
191
|
|
184
192
|
if block_given?
|
185
193
|
begin
|
@@ -198,9 +206,11 @@ module Pwnedkeys
|
|
198
206
|
#
|
199
207
|
# @see .open
|
200
208
|
#
|
201
|
-
def initialize(filename)
|
202
|
-
@fd
|
203
|
-
|
209
|
+
def initialize(filename, sync: true, revision: nil)
|
210
|
+
@fd = File.open(filename, File::RDWR, binmode: true)
|
211
|
+
refresh_header
|
212
|
+
|
213
|
+
@sync, @revision = sync, revision
|
204
214
|
end
|
205
215
|
|
206
216
|
# Query the bloom filter.
|
@@ -233,8 +243,8 @@ module Pwnedkeys
|
|
233
243
|
# probabilistic nature of the bloom filter structure, it is possible to
|
234
244
|
# add two completely different keys and yet it looks like the "same"
|
235
245
|
# key to the bloom filter. Adding two colliding keys isn't a fatal
|
236
|
-
# error, but it is a hint that perhaps
|
237
|
-
# a little too full.
|
246
|
+
# error, but if it starts to happen regularly, it is a hint that perhaps
|
247
|
+
# the existing filter is getting a little too full.
|
238
248
|
#
|
239
249
|
# @raise [Pwnedkeys::Filter::FilterClosedError] if you try to add a key
|
240
250
|
# to a filter object which has had {#close} called on it.
|
@@ -248,6 +258,7 @@ module Pwnedkeys
|
|
248
258
|
|
249
259
|
begin
|
250
260
|
@fd.flock(File::LOCK_EX)
|
261
|
+
refresh_header
|
251
262
|
filter_positions(spki.to_der).each do |n|
|
252
263
|
@fd.seek(n / 8 + @header.header_size, :SET)
|
253
264
|
byte = @fd.read(1).ord
|
@@ -259,18 +270,13 @@ module Pwnedkeys
|
|
259
270
|
@fd.write(new_byte.chr)
|
260
271
|
end
|
261
272
|
|
262
|
-
@header.
|
273
|
+
@revision ||= @header.revision + 1
|
263
274
|
|
264
|
-
|
265
|
-
|
266
|
-
# entry counter, and that would be pointless.
|
267
|
-
unless @already_modified
|
268
|
-
@header.update!
|
269
|
-
end
|
275
|
+
@header.revision = @revision
|
276
|
+
@header.entry_added!
|
270
277
|
|
271
|
-
@
|
272
|
-
@fd.
|
273
|
-
@fd.fdatasync
|
278
|
+
@header.to_fd(@fd)
|
279
|
+
@fd.fdatasync if @sync
|
274
280
|
ensure
|
275
281
|
@fd.flock(File::LOCK_UN)
|
276
282
|
end
|
@@ -278,6 +284,16 @@ module Pwnedkeys
|
|
278
284
|
@already_modified = true
|
279
285
|
end
|
280
286
|
|
287
|
+
# Force a sync of newly-added data to disk.
|
288
|
+
#
|
289
|
+
# This method is only of interest if the filter was opened with `sync:
|
290
|
+
# false`, because otherwise data will already have been synced to disk as
|
291
|
+
# part of the call to {#add}.
|
292
|
+
#
|
293
|
+
def sync
|
294
|
+
@fd.fdatasync if @fd
|
295
|
+
end
|
296
|
+
|
281
297
|
# Signal that the filter should be closed for further querying and manipulation.
|
282
298
|
#
|
283
299
|
# @return [void]
|
@@ -304,6 +320,10 @@ module Pwnedkeys
|
|
304
320
|
|
305
321
|
private
|
306
322
|
|
323
|
+
def refresh_header
|
324
|
+
@header = Header.from_fd(@fd)
|
325
|
+
end
|
326
|
+
|
307
327
|
def hash_count
|
308
328
|
@header.hash_count
|
309
329
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pwnedkeys-filter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Palmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-07-
|
11
|
+
date: 2020-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: openssl-additions
|