dmp 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: 7c33588e32e9693257674adf835c326a0b83a014c12d75066565cabea7ed2433
4
- data.tar.gz: 8397f78e47f38861dac4ff9ec777aec17066f5bc7c063bedaf23647556ea7a1e
3
+ metadata.gz: 9c9dd7398d91356cc90ab8d3d0add83edc0d50d45663a811d6121d0c16cde8b8
4
+ data.tar.gz: b60f942b8c163e50ab11e713fc4740fb29ae3c19e4fc9ed75398223b22a75525
5
5
  SHA512:
6
- metadata.gz: d5121963b6b32b5fdb74a19a258bd238699c4aa6d15b08b31e345ad6de8c2cbdbdd6e1ed389bc97791c14626ae9f1c0669203dd8657f7357c626f92cd1999b54
7
- data.tar.gz: edbb9e39035a8b6189949e52c037118c7ad2a695e504e93d48e7ccb81ac86042821976230420b9056e712a2f45ad25e574ac60ac35458c8f7fc1df1bb33f75e6
6
+ metadata.gz: cf84ddb9185de60859708642a2773cf7a38a87f2dd80e0c6540f209ac194e2556fcc601c74d251e4e9db1ccb36a7c2eb1a577d4167211fda3c648d87b68ed16c
7
+ data.tar.gz: 83f6b8e648e564ca1b7c80979a6c9167228f0c18f940474f416941f94970a632973b326a7bd426f31bee12823721b5c7456991aeacba47f9f00dbcebcbb6ea93
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dmp (0.2.2)
4
+ dmp (0.2.3)
5
5
  clipboard (~> 1.1)
6
6
  colorize (~> 0.8)
7
7
  thor (~> 0)
data/README.md CHANGED
@@ -3,19 +3,9 @@
3
3
 
4
4
  **DMP** (or _Dice My Pass_) is a simple passphrase generator that gives you a passphrase of the desired length using [EFF's long wordlist](http://eff.org/dice). **This little tool was only created for a blog post on how to create a Ruby gem at codingdose.info (WIP) and should be NOT used for production**, can't say much if you like it though.
5
5
 
6
- ```bash
7
- $ dmp about
8
- ____ __ __ ____
9
- | _ \ | \/ | | _ \
10
- | | | | | |\/| | | |_) |
11
- | |_| | | | | | | __/
12
- |____/ |_| |_| |_|
13
-
14
- version: 0.2.2
15
- author: @__franccesco
16
- homepage: https://github.com/franccesco/dmp
17
- learn more: https://codingdose.info
18
- ```
6
+ <p align="center">
7
+ <img src="images/dmp.gif" />
8
+ </p>
19
9
 
20
10
  ## Installation
21
11
 
@@ -57,16 +47,31 @@ $ dmp
57
47
  - Copied to clipboard.
58
48
  ```
59
49
 
60
- **Generate a passphrase of your desired length**
50
+ **Generate a passphrase of your desired length and check if the password appears in HIBP datasets**
61
51
  ```
62
- $ dmp gen 5
52
+ $ dmp gen 5 -H
63
53
  - Passphrase: tavern silly afar luncheon cement
54
+ - Password is safe to use.
55
+ ```
56
+
57
+ **Warns you if your password has been discovered in a HIBP dataset.**
58
+ ```
59
+ - Passphrase: angular
60
+ - WARNING: Passphrase vulnerable 91 times!
61
+ ```
62
+ **Check a password of yours**
63
+ ```
64
+ $ dmp check
65
+ Enter your password, press ENTER when you're done.
66
+ Password (hidden): ****
67
+ - Your password appears in 213580 data sets!
64
68
  ```
65
69
 
66
70
  **Help**
67
71
  ```
68
72
  Commands:
69
73
  dmp about # Displays version number and information
74
+ dmp check # Check if a password/passphrase is vulnerable.
70
75
  dmp gen [length] # Generate a passphrase of the desired length.
71
76
  dmp help [COMMAND] # Describe available commands or one specific command
72
77
  ```
Binary file
data/lib/dmp.rb CHANGED
@@ -2,37 +2,44 @@ require 'dmp/version'
2
2
  require 'net/http'
3
3
  require 'digest/sha1'
4
4
 
5
- # Module to manage DMP operations
6
5
  module Dmp
6
+ # Module to manage DMP operations.
7
+ # gen_passphrase generates a new passphrase of a desired length.
8
+ # check_pwned checks the password string against the HIBP datasets.
7
9
  # default wordlist provided by EFF https://www.eff.org/dice
8
10
  @eff_wordlist = File.dirname(__FILE__) + '/dmp/assets/eff_long_wordlist.txt'
9
11
 
10
12
  def self.gen_passphrase(pass_length = 7)
11
- # load eff_wordlist as a list and strip new lines
12
- pass_list = File.readlines(@eff_wordlist)
13
- pass_list.map(&:strip!)
14
-
15
- # randomize wordlist and strip it to the desired length
16
- random_pass = pass_list.shuffle[0...pass_length]
17
- random_pass
13
+ wordlist = File.readlines(@eff_wordlist)
14
+ wordlist.map(&:strip!)
15
+ wordlist.shuffle[0...pass_length]
18
16
  end
19
17
 
20
18
  def self.check_pwned(passphrase)
21
- if passphrase.kind_of?(Array)
22
- passphrase = passphrase.join(' ')
23
- end
19
+ # This module follows the k-Anonymity principle described in
20
+ # https://haveibeenpwned.com/API/v2#PwnedPasswords
21
+ # that allows you to search for the first 5 characters of the hash and
22
+ # returns a list of hashes for you to search the rest of the hash locally,
23
+ # followed by the number of times the hash appears in a data set
24
+ # e.g: 0018A45C4D1DEF81644B54AB7F969B88D65:21
25
+ passphrase = passphrase.join(' ') if passphrase.is_a?(Array)
24
26
 
25
- hex_pass = Digest::SHA1.hexdigest(passphrase)
26
- hex_pass_sample = hex_pass[0...5]
27
- hex_pass_rest = hex_pass[5..-1]
27
+ sha1_pass = Digest::SHA1.hexdigest(passphrase)
28
+ sha1_excerpt = sha1_pass[0...5]
29
+ sha1_to_look_for = sha1_pass[5..-1]
28
30
 
29
- # request a sample to HIBP to avoid disclosing the full pwd
30
- uri = URI("https://api.pwnedpasswords.com/range/#{hex_pass_sample}")
31
- req = Net::HTTP.get(uri)
31
+ api_url = URI("https://api.pwnedpasswords.com/range/#{sha1_excerpt}")
32
+ api_request = Net::HTTP.get(api_url)
32
33
 
33
- clean_list = req.split("\r\n")
34
- pass_list = clean_list.map { |hash| hash.split(':') }
35
- pass_hash = Hash[*pass_list.flatten!]
36
- pass_hash[hex_pass_rest.upcase]
34
+ # Response is text instead of JSON, needs to format the response
35
+ # to a dictionary so the rest of the hash can be located easier.
36
+ # => String '0018A45C4D1DEF81644B54AB7F969B88D65:21'
37
+ # => Array ['0018A45C4D1DEF81644B54AB7F969B88D65:21', ...]
38
+ # => 2D Array [['0018A45C4D1DEF81644B54AB7F969B88D65', '21'], ...]
39
+ # => Hash {'0018A45C4D1DEF81644B54AB7F969B88D65': 21, ...}
40
+ striped_list = api_request.split("\r\n")
41
+ pass_list = striped_list.map { |hash| hash.split(':') }
42
+ hash_list = Hash[*pass_list.flatten!]
43
+ hash_list[sha1_to_look_for.upcase]
37
44
  end
38
45
  end
@@ -7,6 +7,16 @@ module Dmp
7
7
  # Command line interface for DMP
8
8
  class CLI < Thor
9
9
  default_task :gen_pass
10
+
11
+ # Define option 'gen' that accepts a flag to copy to clipboard ('-c')
12
+ # and another one to check the generated password agains HIBP ('-H')
13
+ # This argument is the default task and it generates a 7 passphrase lenght.
14
+ # Usage:
15
+ # $ dmp gen [optional_length] [optional flags]
16
+ # Example:
17
+ # $ dmp gen 8 -c -H
18
+ # Or:
19
+ # $ dmp 8
10
20
  desc 'gen [length]', 'Generate a passphrase of the desired length.'
11
21
  method_option :clipboard,
12
22
  aliases: '-c',
@@ -17,59 +27,47 @@ module Dmp
17
27
  type: :boolean,
18
28
  desc: 'Check if passphrase is vulnerable in HIBP database.'
19
29
  def gen_pass(pass_length = 7)
20
- # Generate colored passphrase
21
- passphrase = Dmp.gen_passphrase(pass_length.to_i)
22
-
23
- # if flag clipboard is 'true' then copy passphrase to clipboard
24
- if options[:clipboard]
25
- Clipboard.copy(passphrase.join(' '))
26
- end
30
+ new_passphrase = Dmp.gen_passphrase(pass_length.to_i)
31
+ Clipboard.copy(new_passphrase.join(' ')) if options[:clipboard]
32
+ dataset_count = Dmp.check_pwned(new_passphrase) if options[:hibp]
27
33
 
28
- # if flag hibp is 'true' then alert the user
29
- if options[:hibp]
30
- vuln_count = Dmp.check_pwned(passphrase)
34
+ colors = String.colors
35
+ colors.delete(:black) # black color looks ugly in the terminal
36
+ new_passphrase.map! do |phrase|
37
+ random_color = colors.sample
38
+ phrase.colorize(random_color)
31
39
  end
32
40
 
33
- # colors array will be used to pick a randomized sample
34
- # removing black cause it looks ugly in terminals
35
- colors = String.colors
36
- colors.delete(:black)
41
+ copy_msg = '- Copied to clipboard.'.bold.green
42
+ vuln_pass_msg = "- WARNING: Passphrase appears in #{dataset_count} datasets!".red.bold
43
+ safe_pass_msg = '- Password was not found in a dataset.'.green.bold
37
44
 
38
- passphrase.map! do |phrase|
39
- rand_color = colors.sample
40
- phrase.colorize(rand_color)
41
- end
42
- puts '- Passphrase: '.bold + passphrase.join(' ')
43
- puts '- Copied to clipboard.'.bold.green if options[:clipboard]
44
- if vuln_count
45
- puts "- WARNING: Passphrase appears in #{vuln_count} datasets!".red.bold
46
- elsif options[:hibp]
47
- puts '- Password was not found in a dataset.'.green.bold
48
- end
45
+ puts '- Passphrase: '.bold + new_passphrase.join(' ')
46
+ puts copy_msg if options[:clipboard]
47
+ puts dataset_count ? vuln_pass_msg : safe_pass_msg if options[:hibp]
49
48
  end
50
49
 
50
+ # Check if passphrase or password is vulnerable interatively
51
+ # This feature disables echo to avoid making the password visible.
52
+ # This feature should not ask for the password in the terminal command line
53
+ # (e.g: dmp check password) as it would be visible in the terminal history.
54
+ # Usage:
55
+ # $ dmp check
51
56
  desc 'check', 'Check if a password/passphrase is vulnerable.'
52
57
  def check_pass
53
- puts 'Enter your password, press ENTER when you\'re done.'
58
+ puts "Enter your password, press ENTER when you're done."
54
59
  password = ask('Password (hidden):'.yellow, echo: false)
60
+ (puts "Aborted.".red.bold; exit) if password.empty?
55
61
 
56
- # if no password set, just exit
57
- if password.empty?
58
- puts "Aborted.".red.bold
59
- exit
60
- end
61
-
62
- vuln_count = Dmp.check_pwned(password)
63
- if vuln_count
64
- puts " Your password appears in #{vuln_count} datasets!".red.bold
65
- else
66
- puts " Your password was not found in a dataset.".green.bold
67
- end
62
+ dataset_count = Dmp.check_pwned(password)
63
+ vuln_msg = "Your password appears in #{dataset_count} datasets!".red.bold
64
+ safe_msg = "Your password was not found in a dataset.".green.bold
65
+ puts dataset_count ? vuln_msg : safe_msg
68
66
  end
69
67
 
68
+ # Displays banner, version number and author
70
69
  desc 'about', 'Displays version number and information'
71
70
  def about
72
- # Displays banner, version number and author
73
71
  puts Dmp::BANNER.bold.red
74
72
  puts 'version: '.bold + Dmp::VERSION.green
75
73
  puts 'author: '.bold + '@__franccesco'.green
@@ -1,5 +1,5 @@
1
1
  module Dmp
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  BANNER = '''
4
4
  ____ __ __ ____
5
5
  | _ \ | \/ | | _ \
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dmp
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
  - Franccesco Orozco
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-19 00:00:00.000000000 Z
11
+ date: 2018-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -200,6 +200,7 @@ files:
200
200
  - bin/setup
201
201
  - dmp.gemspec
202
202
  - exe/dmp
203
+ - images/dmp.gif
203
204
  - lib/dmp.rb
204
205
  - lib/dmp/assets/eff_long_wordlist.txt
205
206
  - lib/dmp/cli.rb