hibp 0.0.1
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +64 -0
- data/Rakefile +1 -0
- data/bin/hibp +125 -0
- data/hibp.gemspec +29 -0
- data/lib/hibp.rb +30 -0
- data/lib/hibp/api.rb +18 -0
- data/lib/hibp/http_client.rb +99 -0
- data/lib/hibp/report.rb +24 -0
- data/lib/hibp/version.rb +3 -0
- metadata +173 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Michael Henriksen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# Have I Been Pwned?
|
2
|
+
|
3
|
+
A simple tool to check a bunch of email addresses against the [Have I Been Pwned?](https://haveibeenpwned.com/) API.
|
4
|
+
|
5
|
+

|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
$ gem install hibp
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
HIBP supports different ways of feeding it email addresses:
|
14
|
+
|
15
|
+
### Give it a list:
|
16
|
+
|
17
|
+
$ hibp -l "somone@gmail.com,someoneelse@yahoo.com,johndoe@hotmail.com"
|
18
|
+
|
19
|
+
### Find emails in a file
|
20
|
+
|
21
|
+
$ hibp -f /path/to/some/file.txt
|
22
|
+
|
23
|
+
The file does not need to only contain email addresses, they will be extracted with a regular expression.
|
24
|
+
|
25
|
+
### Find emails on a web page
|
26
|
+
|
27
|
+
$ hibp -w http://somecompany.com/about/employees
|
28
|
+
|
29
|
+
Extracts all e-mails on the web page.
|
30
|
+
|
31
|
+
For more options, see `$ hibp --help`.
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
1. Fork it
|
36
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
37
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
38
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
39
|
+
5. Create new Pull Request
|
40
|
+
|
41
|
+
## License
|
42
|
+
|
43
|
+
Copyright (c) 2014 Michael Henriksen
|
44
|
+
|
45
|
+
MIT License
|
46
|
+
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
48
|
+
a copy of this software and associated documentation files (the
|
49
|
+
"Software"), to deal in the Software without restriction, including
|
50
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
51
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
52
|
+
permit persons to whom the Software is furnished to do so, subject to
|
53
|
+
the following conditions:
|
54
|
+
|
55
|
+
The above copyright notice and this permission notice shall be
|
56
|
+
included in all copies or substantial portions of the Software.
|
57
|
+
|
58
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
59
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
60
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
61
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
62
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
63
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
64
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/hibp
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
require 'net/http'
|
6
|
+
require 'methadone'
|
7
|
+
require 'paint'
|
8
|
+
require 'ruby-progressbar'
|
9
|
+
require 'thread/pool'
|
10
|
+
require 'hibp'
|
11
|
+
|
12
|
+
class App
|
13
|
+
include Methadone::Main
|
14
|
+
|
15
|
+
class FileNotReadableError < StandardError; end
|
16
|
+
|
17
|
+
def self.print_report(report)
|
18
|
+
puts Paint["\n [☠] BREACHED ACCOUNTS:", :red]
|
19
|
+
|
20
|
+
report.breached_accounts.each_pair do |email, pwned_websites|
|
21
|
+
puts Paint[" * #{email}: Found in: #{pwned_websites.join(', ')}", :red]
|
22
|
+
end
|
23
|
+
|
24
|
+
puts "\n ---------------------------------------- \n\n"
|
25
|
+
|
26
|
+
puts Paint[" [✔] CLEAN ACCOUNTS:", :green]
|
27
|
+
|
28
|
+
report.clean_accounts.each do |email|
|
29
|
+
puts Paint[" * #{email}", :green]
|
30
|
+
end
|
31
|
+
|
32
|
+
puts "\n"
|
33
|
+
|
34
|
+
if !report.failed_accounts.count.zero?
|
35
|
+
puts "---------------------------------------- \n\n"
|
36
|
+
|
37
|
+
puts Paint[" [⚡] ACCOUNT CHECKS THAT ENCOUNTERED ERROR:", :red]
|
38
|
+
|
39
|
+
report.failed_accounts.each_pair do |email, exception|
|
40
|
+
puts Paint[" * #{email}: #{exception.class}: #{exception.message}", :red]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
main do
|
46
|
+
begin
|
47
|
+
|
48
|
+
if options.include?('no-color')
|
49
|
+
Paint.mode = 0
|
50
|
+
end
|
51
|
+
|
52
|
+
if !options.include?('no-banner')
|
53
|
+
puts Paint[Hibp.banner, :blue]
|
54
|
+
end
|
55
|
+
|
56
|
+
if options[:list]
|
57
|
+
emails = Hibp.extract_emails(options[:list])
|
58
|
+
elsif options[:file]
|
59
|
+
if File.readable?(options[:file])
|
60
|
+
emails = Hibp.extract_emails(File.read(options[:file]))
|
61
|
+
else
|
62
|
+
raise FileNotReadableError.new("#{options[:file]} does not exist or is not readable")
|
63
|
+
end
|
64
|
+
elsif options[:web]
|
65
|
+
http_client = Hibp::HttpClient.new
|
66
|
+
response = http_client.do_get(options[:web])
|
67
|
+
emails = Hibp.extract_emails(response.body)
|
68
|
+
else
|
69
|
+
help_now!("You must give me some e-mails to check...")
|
70
|
+
end
|
71
|
+
|
72
|
+
if emails.count.zero?
|
73
|
+
puts Paint[" Sorry, I could not find any emails to check; exiting.", :red]
|
74
|
+
exit!
|
75
|
+
end
|
76
|
+
|
77
|
+
puts Paint[" Checking #{emails.count} #{emails.count == 1 ? 'email' : 'emails'}...\n", :blue]
|
78
|
+
|
79
|
+
progress_bar = ProgressBar.create(:total => emails.count, :format => ' %a %B %p%% %t |%e')
|
80
|
+
report = Hibp::Report.new
|
81
|
+
thread_pool = Thread.pool(options[:threads].to_i)
|
82
|
+
|
83
|
+
emails.each do |email|
|
84
|
+
thread_pool.process do
|
85
|
+
begin
|
86
|
+
if pwned_websites = Hibp::Api.breached_account?(email)
|
87
|
+
report.add_breached_account(email, pwned_websites)
|
88
|
+
else
|
89
|
+
report.add_clean_account(email)
|
90
|
+
end
|
91
|
+
rescue => ex
|
92
|
+
report.add_failed_account(email, ex)
|
93
|
+
end
|
94
|
+
progress_bar.increment
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
thread_pool.shutdown
|
99
|
+
print_report(report)
|
100
|
+
|
101
|
+
rescue Exception => e
|
102
|
+
if !e.is_a?(Interrupt)
|
103
|
+
puts Paint[" [⚡] WARP CORE BREACH!", :red]
|
104
|
+
puts Paint[" * #{e.class}: #{e.message}", :red]
|
105
|
+
else
|
106
|
+
print_report(report) if defined?(report)
|
107
|
+
exit!
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
options['threads'] = 3
|
113
|
+
|
114
|
+
on("-l EMAILS", "--list", "List of emails")
|
115
|
+
on("-f FILE", "--file", "Path to a file containing emails")
|
116
|
+
on("-w URL", "--web", "URL to extract emails from")
|
117
|
+
on("-t THREADS", "--threads", "Number of concurrent threads to use")
|
118
|
+
on("--no-banner", "Don't display HIBP banner")
|
119
|
+
on("--no-color", "Don't colorize output")
|
120
|
+
|
121
|
+
description "A simple tool to check a bunch of emails against the haveibeenpwned.com API."
|
122
|
+
version Hibp::VERSION
|
123
|
+
|
124
|
+
go!
|
125
|
+
end
|
data/hibp.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hibp/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "hibp"
|
8
|
+
spec.version = Hibp::VERSION
|
9
|
+
spec.authors = ["Michael Henriksen"]
|
10
|
+
spec.email = ["michenriksen@neomailbox.ch"]
|
11
|
+
spec.description = %q{A simple tool to check a bunch of email addresses against the Have I Been Pwned? API.}
|
12
|
+
spec.summary = %q{A simple tool to check a bunch of email addresses against the Have I Been Pwned? API.}
|
13
|
+
spec.homepage = "https://github.com/michenriksen/hibp"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'httparty'
|
22
|
+
spec.add_dependency 'methadone'
|
23
|
+
spec.add_dependency 'paint'
|
24
|
+
spec.add_dependency 'ruby-progressbar'
|
25
|
+
spec.add_dependency 'thread'
|
26
|
+
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
28
|
+
spec.add_development_dependency 'rake'
|
29
|
+
end
|
data/lib/hibp.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require 'httparty'
|
5
|
+
|
6
|
+
require 'hibp/version'
|
7
|
+
require 'hibp/http_client'
|
8
|
+
require 'hibp/api'
|
9
|
+
require 'hibp/report'
|
10
|
+
|
11
|
+
module Hibp
|
12
|
+
EMAIL_REGEX = /[-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+\.[a-zA-Z]{2,4}/
|
13
|
+
|
14
|
+
def self.banner
|
15
|
+
banner = <<EOB
|
16
|
+
|
17
|
+
### ### # # ### ###### ######
|
18
|
+
### ### # # # # # # #
|
19
|
+
# # # # # # # #
|
20
|
+
# ### ##### ##### ####### # ###### ######
|
21
|
+
### # # # # # #
|
22
|
+
# # # # # # #
|
23
|
+
# # # ### ###### #
|
24
|
+
EOB
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.extract_emails(haystack)
|
28
|
+
haystack.scan(EMAIL_REGEX)
|
29
|
+
end
|
30
|
+
end
|
data/lib/hibp/api.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Hibp
|
2
|
+
class Api
|
3
|
+
BASE_URI = 'https://haveibeenpwned.com/api'
|
4
|
+
|
5
|
+
def self.breached_account?(email)
|
6
|
+
JSON.parse(http_client.do_get("#{BASE_URI}/breachedaccount/#{CGI.escape(email)}").body)
|
7
|
+
rescue Hibp::HttpClient::ClientError => ex
|
8
|
+
return false if ex.status == 404
|
9
|
+
raise ex
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def self.http_client
|
15
|
+
@http_client ||= Hibp::HttpClient.new()
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Hibp
|
2
|
+
class HttpClient
|
3
|
+
include HTTParty
|
4
|
+
|
5
|
+
class HttpError < StandardError; end
|
6
|
+
class ConnectionError < HttpError; end
|
7
|
+
|
8
|
+
class RequestError < HttpError
|
9
|
+
attr_reader :status, :body
|
10
|
+
|
11
|
+
def initialize(method, path, status, body, options)
|
12
|
+
@status = status
|
13
|
+
@body = body
|
14
|
+
super("#{method} to #{path} returned status #{status} - options: #{options.inspect}")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ClientError < RequestError; end
|
19
|
+
class ServerError < RequestError; end
|
20
|
+
|
21
|
+
class UnhandledError < StandardError; end
|
22
|
+
|
23
|
+
DEFAULT_TIMEOUT = 0.5 #seconds
|
24
|
+
DEFAULT_RETRIES = 3
|
25
|
+
|
26
|
+
Response = Struct.new(:status, :headers, :body)
|
27
|
+
|
28
|
+
HANDLED_EXCEPTIONS = [
|
29
|
+
ServerError,
|
30
|
+
ClientError,
|
31
|
+
Timeout::Error,
|
32
|
+
Errno::ETIMEDOUT,
|
33
|
+
Errno::ECONNRESET,
|
34
|
+
Errno::ECONNREFUSED,
|
35
|
+
Errno::ENETUNREACH,
|
36
|
+
Errno::EHOSTUNREACH,
|
37
|
+
EOFError
|
38
|
+
]
|
39
|
+
|
40
|
+
def initialize(config = {})
|
41
|
+
@config = {
|
42
|
+
:timeout => DEFAULT_TIMEOUT,
|
43
|
+
:retries => DEFAULT_RETRIES,
|
44
|
+
}.merge(config)
|
45
|
+
default_timeout = @config[:timeout]
|
46
|
+
end
|
47
|
+
|
48
|
+
def do_get(path, params=nil, opt={})
|
49
|
+
do_request(:get, path, {:query => params}.merge(opt))
|
50
|
+
end
|
51
|
+
|
52
|
+
def do_post(path, params=nil, opt={})
|
53
|
+
do_request(:post, path, {:body => params}.merge(opt))
|
54
|
+
end
|
55
|
+
|
56
|
+
def do_put(path, params=nil, opt={})
|
57
|
+
do_request(:put, path, {:body => params}.merge(opt))
|
58
|
+
end
|
59
|
+
|
60
|
+
def do_delete(path, params=nil, opt={})
|
61
|
+
do_request(:delete, path, {:query => params}.merge(opt))
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def do_request(method, path, options)
|
67
|
+
with_retries do
|
68
|
+
response = self.class.send(method, path, options)
|
69
|
+
|
70
|
+
handle_possible_error(method.to_s.upcase, path, response, options)
|
71
|
+
|
72
|
+
Response.new(response.code, response.headers, response.body)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def handle_possible_error(method, path, response, options)
|
77
|
+
if response.code >= 500
|
78
|
+
raise ServerError.new(method, path, response.code, response.body, options)
|
79
|
+
elsif response.code >= 400
|
80
|
+
raise ClientError.new(method, path, response.code, response.body, options)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def with_retries(&block)
|
85
|
+
tries ||= @config[:retries]
|
86
|
+
yield
|
87
|
+
rescue *HANDLED_EXCEPTIONS, ServerError => ex
|
88
|
+
if (tries -= 1) > 0
|
89
|
+
sleep 0.2
|
90
|
+
retry
|
91
|
+
end
|
92
|
+
raise ex
|
93
|
+
rescue ClientError => ex
|
94
|
+
raise ex
|
95
|
+
rescue => ex
|
96
|
+
raise UnhandledError.new(ex.message)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/hibp/report.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Hibp
|
2
|
+
class Report
|
3
|
+
|
4
|
+
attr_reader :breached_accounts, :clean_accounts, :failed_accounts
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@breached_accounts = {}
|
8
|
+
@clean_accounts = []
|
9
|
+
@failed_accounts = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_breached_account(email, pwned_websites)
|
13
|
+
@breached_accounts[email] = pwned_websites
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_clean_account(email)
|
17
|
+
@clean_accounts << email
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_failed_account(email, exception)
|
21
|
+
@failed_accounts[email] = exception
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/hibp/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hibp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Henriksen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-01-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: methadone
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: paint
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: ruby-progressbar
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: thread
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: bundler
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '1.3'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '1.3'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rake
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description: A simple tool to check a bunch of email addresses against the Have I
|
127
|
+
Been Pwned? API.
|
128
|
+
email:
|
129
|
+
- michenriksen@neomailbox.ch
|
130
|
+
executables:
|
131
|
+
- hibp
|
132
|
+
extensions: []
|
133
|
+
extra_rdoc_files: []
|
134
|
+
files:
|
135
|
+
- .gitignore
|
136
|
+
- Gemfile
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- bin/hibp
|
141
|
+
- hibp.gemspec
|
142
|
+
- lib/hibp.rb
|
143
|
+
- lib/hibp/api.rb
|
144
|
+
- lib/hibp/http_client.rb
|
145
|
+
- lib/hibp/report.rb
|
146
|
+
- lib/hibp/version.rb
|
147
|
+
homepage: https://github.com/michenriksen/hibp
|
148
|
+
licenses:
|
149
|
+
- MIT
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
none: false
|
156
|
+
requirements:
|
157
|
+
- - ! '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
requirements: []
|
167
|
+
rubyforge_project:
|
168
|
+
rubygems_version: 1.8.28
|
169
|
+
signing_key:
|
170
|
+
specification_version: 3
|
171
|
+
summary: A simple tool to check a bunch of email addresses against the Have I Been
|
172
|
+
Pwned? API.
|
173
|
+
test_files: []
|