pwnedkeys-filter 0.1.0 → 0.2.0

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: 76391e2ba3bc336b7c1eae6034f034b3fce4bbf01094aa96c3bd76c71d5c9f0e
4
- data.tar.gz: 1a84b07456594a252fd720c9a6152452a89403f5b54c337c4b768d44653b0961
3
+ metadata.gz: 9b916d185473c8a9bb1a2cc28036121d7c015af4abc287a4cc778f91d8184ea5
4
+ data.tar.gz: 3622ef85be404de370844c1fcede849a43e536d4c8261d43285ad45cc5d7ded4
5
5
  SHA512:
6
- metadata.gz: 1e94333e88347be45babe142ceab68301c1897e7f998d0d1cbaa05a9cf9d93eac5cf3e51b363d089f894071793d8bf2309ee30c91d221991e04346a3906a882b
7
- data.tar.gz: ff38e9a11c06de9cf9fb8aa5073010b03d986e33ec58e6d29d77677f3cb34015c386c175dc03f3f015cdeb331999dea42cb7c068184b39be47358b06bcdc3c7a
6
+ metadata.gz: e5a97277a35b9f2dd1901ab599bd3de39954c8bfceb868f3c33a3b275bc7390d2bb81a988d660d5f88d6cb5caf8043cacc830b02ebf14d4cb6d5d92094dce64a
7
+ data.tar.gz: 9d1ee32b9cec58d5d235aa569192ddbd7fecff7db735217d925d2b9ddbaf46d99e0766388300110227edb7e3f5c8dd25f575ccc20654615020cd8e534b783ab5
@@ -117,6 +117,53 @@ module Pwnedkeys
117
117
  nil
118
118
  end
119
119
 
120
+ # Calculate count/length parameters for a given entry count and desired false-positive rate.
121
+ #
122
+ # @param entries [Integer] how many elements the bloom filter should
123
+ # accommodate.
124
+ #
125
+ # @param fp_rate [Float] the maximum false-positive rate you wish to
126
+ # accept.
127
+ #
128
+ # @return [Hash<Symbol, Integer>] the `:hash_count` and `:hash_length` which
129
+ # will produce the desired false-positive rate if the filter is filled
130
+ # with the specified number of entries.
131
+ #
132
+ def self.filter_parameters(entries:, fp_rate:)
133
+ # Blessings unto https://en.wikipedia.org/wiki/Bloom_filter#Optimal_number_of_hash_functions
134
+ optimal_filter_bits = (-1 * entries * Math.log(fp_rate) / Math.log(2) / Math.log(2))
135
+ hash_length = (Math.log2(optimal_filter_bits)).ceil
136
+ actual_filter_bits = 2 ** hash_length
137
+
138
+ # We could, in theory, just use the "optimal k" (hash count), which would
139
+ # often produce an actual false-positive rate much smaller than our
140
+ # target (because actual_filter_bits can be *significantly* larger than
141
+ # optimal_filter_bits). Instead, to minimise the hashing required, we
142
+ # can use the extra filter length available to choose a smaller k that
143
+ # still satisfies the target false positive rate.
144
+ #
145
+ # Because my algebra isn't up to solving the FP rate equation for k, and
146
+ # because the search space of possible values of k is small and bounded
147
+ # (by 1, and by the "optimal k" on the upper bound), brute-forcing things
148
+ # seems the easiest option.
149
+
150
+ upper_bound = (Math.log(2) * actual_filter_bits / entries).ceil
151
+ hash_count = (1..upper_bound).find do |k|
152
+ (1 - (1 - 1.0 / actual_filter_bits) ** (k * entries)) ** k < fp_rate
153
+ end
154
+
155
+ if hash_count.nil?
156
+ #:nocov:
157
+ raise RuntimeError, "CAN'T HAPPEN: Could not determine hash_count for entries: #{entries}, fp_rate: #{fp_rate}. Please report a violation of the laws of mathematics."
158
+ #:nocov:
159
+ end
160
+
161
+ {
162
+ hash_count: hash_count,
163
+ hash_length: hash_length,
164
+ }
165
+ end
166
+
120
167
  # Open an existing pwnedkeys bloom filter data file.
121
168
  #
122
169
  # @param filename [String] the file to open.
@@ -245,7 +292,6 @@ module Pwnedkeys
245
292
  (1 - (1 - 1.0 / filter_bit_count) ** (hash_count * entry_count)) ** hash_count
246
293
  end
247
294
 
248
-
249
295
  private
250
296
 
251
297
  def hash_count
@@ -29,7 +29,6 @@ Gem::Specification.new do |s|
29
29
  s.add_development_dependency 'github-release'
30
30
  s.add_development_dependency 'git-version-bump'
31
31
  s.add_development_dependency 'guard-rspec'
32
- s.add_development_dependency 'rack-test'
33
32
  s.add_development_dependency 'rake', "~> 12.0"
34
33
  s.add_development_dependency 'redcarpet'
35
34
  s.add_development_dependency 'rspec'
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.1.0
4
+ version: 0.2.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: 2019-04-21 00:00:00.000000000 Z
11
+ date: 2020-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: openssl-additions
@@ -94,20 +94,6 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rack-test
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: rake
113
99
  requirement: !ruby/object:Gem::Requirement
@@ -209,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
209
195
  - !ruby/object:Gem::Version
210
196
  version: '0'
211
197
  requirements: []
212
- rubygems_version: 3.0.1
198
+ rubygems_version: 3.0.3
213
199
  signing_key:
214
200
  specification_version: 4
215
201
  summary: Library to query pwnedkeys.com bloom filters