Sha256: c8eca1c8ca82de6005c484214ed201c17faf04770b181bb16bfb42a40041f75b

Contents?: true

Size: 2 KB

Versions: 1

Compression:

Stored size: 2 KB

Contents

require_relative "bloomed/version"
require_relative "bloomed/msg_packable"
require "bloomer"
require "bloomer/msgpackable"

module Bloomed
  class PW
    include MsgPackable::Bloomed

    attr_reader :false_positive_probability,
                :top,
                :bloom,
                :cache_dir,
                :filename

    def initialize(top: 100_000,
                   false_positive_probability: 0.001,
                   cache_dir: nil)
      @cache_dir = cache_dir || File.join(File.dirname(__FILE__), "dump")
      @top = top
      @false_positive_probability = false_positive_probability
      @bloom = prepare
    end

    def pwned?(pw)
      @bloom.include?(Digest::SHA1.hexdigest(pw).upcase)
    end

    def memory_size_bytes
      require "objspace"
      ObjectSpace.memsize_of(@bloom)
    end

    def filename
      inverse_probaility = 1.0 / false_positive_probability
      File.join(cache_dir,
                "pwned_top_#{top.to_i}_one_in_#{inverse_probaility.to_i}.msgpk")
    end

    private

    def prepare
      if File.exist? filename
        load_cache
      else
        bloom_filter = generate
        write_cache bloom_filter
        bloom_filter
      end
    end

    def load_cache
      Bloomed::PW.from_msgpack(File.read(filename))
    end

    PWNED_PASSWORDS_FILENAME = "pwned-passwords-ordered-by-count.txt".freeze

    def generate
      unless File.exist? PWNED_PASSWORDS_FILENAME
        raise MissingPasswordListError, "To generate new, optimized pwned passwords bloom filter, run `rake seed` or `rake seed_here`. To generate all variants, even the very large binaries, run `rake seed\[all\]` or `rake seed_here\[all\]`."
      end

      bloom_filter = Bloomer.new(top, false_positive_probability)
      File.open(PWNED_PASSWORDS_FILENAME, "r").first(top).each do |line|
        bloom_filter.add line[0...40]
      end
      bloom_filter
    end

    def write_cache(b)
      File.write(filename, b.to_msgpack)
      b
    end
  end

  class MissingPasswordListError < RuntimeError
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
bloomed-1.1.0 lib/bloomed.rb