dmp 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
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