dgen 0.4.0 → 0.5.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 +5 -5
- data/lib/dgen.rb +27 -0
- data/lib/dgen/base.rb +59 -13
- data/lib/dgen/diceware.rb +71 -0
- data/lib/dgen/outputfile.rb +64 -60
- data/lib/dgen/passgen.rb +53 -77
- data/test/assets/word-list.txt +7776 -0
- data/test/test_diceware.rb +61 -0
- data/test/test_passgen.rb +50 -0
- metadata +15 -11
- data/test/test_dgen.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cf8332f7c9acdb62aa98082b4e16cd43b695a8c74fba3352f1dda9b566d0eb31
|
4
|
+
data.tar.gz: ae25ff18757c3665f2315a7069e82070f035ce1c6e7f70659cd5b9664b776cf0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ae75c0ae186f711de9f41f65c78d5b69cf67115f45f18ae80e357540615f160c7dd99267d0b82818ab433e34249b95020112ce9b71f3ace1fa77df2b773f800
|
7
|
+
data.tar.gz: 881aa03f5e9c6a832fac4f7c84021d8bb25c480e54f6bcefd5d132364442bb6b8293ae3bd9f09a06cbbc1ebf1ac6370f0504b2ed0be5c226b4cf98a00af8a761
|
data/lib/dgen.rb
CHANGED
@@ -1 +1,28 @@
|
|
1
|
+
# Copyright 2015-2018 Richard Davis
|
2
|
+
#
|
3
|
+
# This file is part of dgen.
|
4
|
+
#
|
5
|
+
# dgen is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# dgen is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with dgen. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
1
18
|
require 'dgen/base'
|
19
|
+
|
20
|
+
##
|
21
|
+
# = Dgen
|
22
|
+
# Author:: Dick Davis
|
23
|
+
# Copyright:: Copyright 2015-2018 Dick Davis
|
24
|
+
# License:: GNU Public License 3
|
25
|
+
#
|
26
|
+
# The namespace for all Dgen components.
|
27
|
+
module Dgen
|
28
|
+
end
|
data/lib/dgen/base.rb
CHANGED
@@ -1,16 +1,40 @@
|
|
1
|
-
|
2
|
-
#
|
1
|
+
# Copyright 2015-2018 Richard Davis
|
2
|
+
#
|
3
|
+
# This file is part of dgen.
|
4
|
+
#
|
5
|
+
# dgen is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
3
9
|
#
|
4
|
-
#
|
10
|
+
# dgen is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with dgen. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
5
18
|
require 'optparse'
|
6
19
|
require 'dgen/passgen.rb'
|
20
|
+
require 'dgen/diceware.rb'
|
7
21
|
require 'dgen/outputfile.rb'
|
8
22
|
|
23
|
+
##
|
24
|
+
# = base.rb
|
25
|
+
# Author:: Dick Davis
|
26
|
+
# Copyright:: Copyright 2015-2018 Dick Davis
|
27
|
+
# License:: GNU Public License 3
|
28
|
+
#
|
29
|
+
# The main script for program execution.
|
30
|
+
|
31
|
+
# Catches interrupt signal to terminate program execution.
|
9
32
|
trap('INT') do
|
10
33
|
puts "\nTerminating..."
|
11
34
|
exit
|
12
35
|
end
|
13
36
|
|
37
|
+
# Parses command-line options to determine program flow.
|
14
38
|
options = {}
|
15
39
|
|
16
40
|
optparse = OptionParser.new do |opts|
|
@@ -37,11 +61,14 @@ end
|
|
37
61
|
|
38
62
|
optparse.parse!
|
39
63
|
|
64
|
+
# Opens, decrypts, and displays previously saved passphrase file.
|
40
65
|
if options[:open]
|
66
|
+
print 'Enter a key for decryption => '
|
67
|
+
key = gets.chomp
|
41
68
|
begin
|
42
|
-
OutputFile.open_ofile(options[:file])
|
69
|
+
Dgen::OutputFile.open_ofile(options[:file], key)
|
43
70
|
exit
|
44
|
-
rescue
|
71
|
+
rescue IOError
|
45
72
|
puts 'An error occurred while trying to open the file.'
|
46
73
|
exit
|
47
74
|
end
|
@@ -50,30 +77,49 @@ elsif options.empty?
|
|
50
77
|
exit
|
51
78
|
end
|
52
79
|
|
80
|
+
# Initializes generator with user-provided configuration options.
|
53
81
|
print 'Number of words for phrase (recommended minimum is 6 words) => '
|
54
82
|
n_words = gets.chomp.to_i
|
55
83
|
print 'Length of passphrase (recommended minimum is 17 characters) => '
|
56
84
|
p_length = gets.chomp.to_i
|
85
|
+
generator = Dgen::PassGen.new(n_words, p_length)
|
57
86
|
|
87
|
+
# Generates a single passphrase and optionally saves to encrypted file.
|
58
88
|
if options[:single]
|
59
|
-
single_pass =
|
89
|
+
single_pass = generator.single
|
90
|
+
puts "Passphrase: #{single_pass}"
|
60
91
|
puts 'Save this passphrase in an encrypted file? (Y/N) => '
|
61
92
|
save = gets.chomp
|
62
|
-
exit unless save.
|
93
|
+
exit unless save.casecmp('Y').zero?
|
63
94
|
begin
|
64
|
-
|
65
|
-
|
95
|
+
print 'Enter name for output file => '
|
96
|
+
o_file = gets.chomp
|
97
|
+
print 'Enter a key for encryption => '
|
98
|
+
key = gets.chomp
|
99
|
+
Dgen::OutputFile.save_pass(o_file, key, single_pass)
|
100
|
+
rescue IOError
|
66
101
|
puts 'Unable to save passphrase to output file.'
|
67
102
|
exit
|
68
103
|
end
|
104
|
+
|
105
|
+
# Generates multiple passphrases and optionally saves to encrypted file.
|
69
106
|
elsif options[:batch]
|
70
|
-
|
107
|
+
print 'How many passphrases to generate? => '
|
108
|
+
n_pass = gets.chomp.to_i
|
109
|
+
batch_pass = generator.batch(n_pass)
|
110
|
+
batch_pass.each do |pass|
|
111
|
+
puts "Passphrase: '#{pass}'"
|
112
|
+
end
|
71
113
|
print 'Save the passphrases in an encrypted file? (Y/N) => '
|
72
114
|
save = gets.chomp
|
73
|
-
exit unless save.
|
115
|
+
exit unless save.casecmp('Y').zero?
|
74
116
|
begin
|
75
|
-
|
76
|
-
|
117
|
+
print 'Enter name for output file => '
|
118
|
+
o_file = gets.chomp
|
119
|
+
print 'Enter a key for encryption => '
|
120
|
+
key = gets.chomp
|
121
|
+
Dgen::OutputFile.save_batch(o_file, key, batch_pass)
|
122
|
+
rescue IOError
|
77
123
|
puts 'Unable to save passphrases to output file.'
|
78
124
|
exit
|
79
125
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Copyright 2015-2018 Richard Davis
|
2
|
+
#
|
3
|
+
# This file is part of dgen.
|
4
|
+
#
|
5
|
+
# dgen is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# dgen is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with dgen. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require 'securerandom'
|
19
|
+
|
20
|
+
module Dgen
|
21
|
+
##
|
22
|
+
# = Diceware
|
23
|
+
# Author:: Dick Davis
|
24
|
+
# Copyright:: Copyright 2015-2018 Dick Davis
|
25
|
+
# License:: GNU Public License 3
|
26
|
+
#
|
27
|
+
# Methods to generate random numbers, select words from
|
28
|
+
# word list using those numbers, and combine words into
|
29
|
+
# a passphrase.
|
30
|
+
#
|
31
|
+
# The algorithm used to generate passwords is the Diceware method, developed
|
32
|
+
# by Arnold Reinhold.
|
33
|
+
module Diceware
|
34
|
+
##
|
35
|
+
# Creates an array of random numbers generated securely.
|
36
|
+
def self.roll_nums
|
37
|
+
numbers = []
|
38
|
+
5.times do
|
39
|
+
numbers.push(SecureRandom.random_number(6) + 1)
|
40
|
+
end
|
41
|
+
num = numbers.join('')
|
42
|
+
num
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Chooses words from the diceware word list for the passphrase.
|
47
|
+
def self.find_word(number, word_list)
|
48
|
+
File.foreach(word_list) do |line|
|
49
|
+
num = line.slice(0, 5)
|
50
|
+
@word = line.slice(6..-2)
|
51
|
+
break if num == number
|
52
|
+
end
|
53
|
+
@word
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Generates and returns the passphrase.
|
58
|
+
def self.make_phrase(n_words, n_chars, word_list)
|
59
|
+
passphrase = ''
|
60
|
+
loop do
|
61
|
+
words = []
|
62
|
+
n_words.times do
|
63
|
+
words.push(find_word(roll_nums, word_list))
|
64
|
+
end
|
65
|
+
passphrase = words.join(' ')
|
66
|
+
break unless passphrase.length < n_chars
|
67
|
+
end
|
68
|
+
passphrase
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/dgen/outputfile.rb
CHANGED
@@ -1,73 +1,77 @@
|
|
1
|
-
|
2
|
-
# OutputFile Module
|
1
|
+
# Copyright 2015-2018 Richard Davis
|
3
2
|
#
|
4
|
-
#
|
5
|
-
require 'crypt/blowfish'
|
6
|
-
|
7
|
-
##
|
8
|
-
# This module provides the methods that enable saving generated passwords
|
9
|
-
# securely to a file.
|
3
|
+
# This file is part of dgen.
|
10
4
|
#
|
11
|
-
#
|
5
|
+
# dgen is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
12
9
|
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
File.delete("plain_#{file}")
|
21
|
-
end
|
10
|
+
# dgen is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with dgen. If not, see <http://www.gnu.org/licenses/>.
|
22
17
|
|
23
|
-
|
24
|
-
# Decrypts a blowfish encrypted file.
|
25
|
-
#
|
26
|
-
def self.decrypt(file, key)
|
27
|
-
bf = Crypt::Blowfish.new(key)
|
28
|
-
bf.decrypt_file("#{file}", "decrypted_#{file}")
|
29
|
-
end
|
18
|
+
require 'crypt/blowfish'
|
30
19
|
|
20
|
+
module Dgen
|
31
21
|
##
|
32
|
-
#
|
22
|
+
# = OutputFile
|
23
|
+
# Author:: Dick Davis
|
24
|
+
# Copyright:: Copyright 2015-2018 Dick Davis
|
25
|
+
# License:: GNU Public License 3
|
33
26
|
#
|
34
|
-
|
35
|
-
|
36
|
-
o_file = gets.chomp
|
37
|
-
print 'Enter a key for encryption => '
|
38
|
-
key = gets.chomp
|
39
|
-
f = File.open("plain_#{o_file}", 'w+')
|
40
|
-
f.puts phrase
|
41
|
-
f.close
|
42
|
-
encrypt(o_file, key)
|
43
|
-
end
|
44
|
-
|
45
|
-
##
|
46
|
-
# Saves passphrases to a file.
|
27
|
+
# This module provides the methods that enable saving generated passwords
|
28
|
+
# securely to a file.
|
47
29
|
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
30
|
+
# The encryption algorithm used is Blowfish, developed by Bruce Schneier.
|
31
|
+
module OutputFile
|
32
|
+
##
|
33
|
+
# Encrypts a plaintext file using blowfish encryption.
|
34
|
+
def self.encrypt(file, key)
|
35
|
+
bf = Crypt::Blowfish.new(key)
|
36
|
+
bf.encrypt_file("plain_#{file}", file.to_s)
|
37
|
+
File.delete("plain_#{file}")
|
56
38
|
end
|
57
|
-
f.close
|
58
|
-
encrypt(o_file, key)
|
59
|
-
end
|
60
39
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
40
|
+
##
|
41
|
+
# Decrypts a blowfish encrypted file.
|
42
|
+
def self.decrypt(file, key)
|
43
|
+
bf = Crypt::Blowfish.new(key)
|
44
|
+
bf.decrypt_file(file.to_s, "decrypted_#{file}")
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Saves passphrase to a file.
|
49
|
+
def self.save_pass(o_file, key, phrase)
|
50
|
+
f = File.open("plain_#{o_file}", 'w+')
|
51
|
+
f.puts phrase
|
52
|
+
f.close
|
53
|
+
encrypt(o_file, key)
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Saves passphrases to a file.
|
58
|
+
def self.save_batch(o_file, key, phrases)
|
59
|
+
f = File.open("plain_#{o_file}", 'w+')
|
60
|
+
phrases.each do |phrase|
|
61
|
+
f.write phrase + "\n"
|
62
|
+
end
|
63
|
+
f.close
|
64
|
+
encrypt(o_file, key)
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Opens a previously saved output file for reading.
|
69
|
+
def self.open_ofile(file, key)
|
70
|
+
decrypt(file, key)
|
71
|
+
File.foreach("decrypted_#{file}") do |l|
|
72
|
+
puts "Decrypted passphrase: '#{l.chomp}'"
|
73
|
+
end
|
74
|
+
File.delete("decrypted_#{file}")
|
70
75
|
end
|
71
|
-
File.delete("decrypted_#{file}")
|
72
76
|
end
|
73
77
|
end
|
data/lib/dgen/passgen.rb
CHANGED
@@ -1,91 +1,67 @@
|
|
1
|
-
|
2
|
-
# PassGen Module
|
1
|
+
# Copyright 2015-2018 Richard Davis
|
3
2
|
#
|
4
|
-
#
|
5
|
-
require 'securerandom'
|
6
|
-
|
7
|
-
##
|
8
|
-
# This module provides the methods that compose the password generator.
|
3
|
+
# This file is part of dgen.
|
9
4
|
#
|
10
|
-
#
|
11
|
-
#
|
5
|
+
# dgen is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
12
9
|
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
numbers.push(SecureRandom.random_number(6) + 1)
|
21
|
-
end
|
22
|
-
num = numbers.join('')
|
23
|
-
num
|
24
|
-
end
|
10
|
+
# dgen is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with dgen. If not, see <http://www.gnu.org/licenses/>.
|
25
17
|
|
26
|
-
|
27
|
-
# Opens and returns the file containing the diceware word list.
|
28
|
-
#
|
29
|
-
def self.open_wordlist
|
30
|
-
path = File.expand_path(File.join(File.dirname(__FILE__),
|
31
|
-
'..',
|
32
|
-
'assets',
|
33
|
-
'word-list.txt'))
|
34
|
-
wordlist = File.new(path, 'r')
|
35
|
-
wordlist
|
36
|
-
end
|
18
|
+
require 'dgen/diceware'
|
37
19
|
|
20
|
+
module Dgen
|
38
21
|
##
|
39
|
-
#
|
22
|
+
# = PassGen
|
23
|
+
# Author:: Dick Davis
|
24
|
+
# Copyright:: Copyright 2015-2018 Dick Davis
|
25
|
+
# License:: GNU Public License 3
|
40
26
|
#
|
41
|
-
|
42
|
-
File.foreach(file) do |line|
|
43
|
-
num = line.slice(0, 5)
|
44
|
-
@word = line.slice(6..-2)
|
45
|
-
break if num == number
|
46
|
-
end
|
47
|
-
@word
|
48
|
-
end
|
49
|
-
|
50
|
-
##
|
51
|
-
# Generates and returns the passphrase.
|
27
|
+
# Generates secure diceware passphrases.
|
52
28
|
#
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
29
|
+
# The algorithm used to generate passwords is the Diceware method, developed
|
30
|
+
# by Arnold Reinhold.
|
31
|
+
class PassGen
|
32
|
+
# Number of words to use in passphrase.
|
33
|
+
attr_reader :n_words
|
34
|
+
# Minimum character length of passphrase.
|
35
|
+
attr_reader :n_chars
|
36
|
+
# File containing the list of words to select words from.
|
37
|
+
attr_reader :word_list
|
38
|
+
|
39
|
+
##
|
40
|
+
# Initializes a PassGen instance
|
41
|
+
def initialize(n_words, n_chars)
|
42
|
+
@n_words = n_words
|
43
|
+
@n_chars = n_chars
|
44
|
+
path = File.expand_path(File.join(File.dirname(__FILE__),
|
45
|
+
'..',
|
46
|
+
'assets',
|
47
|
+
'word-list.txt'))
|
48
|
+
@word_list = File.new(path, 'r')
|
61
49
|
end
|
62
|
-
@pass_phrase
|
63
|
-
end
|
64
50
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
phrase = make_phrase(n_words, p_length, f)
|
71
|
-
puts "Passphrase: '#{phrase}'"
|
72
|
-
f.close
|
73
|
-
phrase
|
74
|
-
end
|
51
|
+
##
|
52
|
+
# Produces and displays a single passphrase.
|
53
|
+
def single
|
54
|
+
Dgen::Diceware.make_phrase(@n_words, @n_chars, @word_list)
|
55
|
+
end
|
75
56
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
num_pass.times do |i|
|
85
|
-
phrase.push(make_phrase(n_words, p_length, f))
|
86
|
-
puts "Passphrase: '#{phrase[i]}'"
|
57
|
+
##
|
58
|
+
# Produces and displays multiple passphrases.
|
59
|
+
def batch(n_pass)
|
60
|
+
phrases = []
|
61
|
+
n_pass.times do
|
62
|
+
phrases.push(Dgen::Diceware.make_phrase(@n_words, @n_chars, @word_list))
|
63
|
+
end
|
64
|
+
phrases
|
87
65
|
end
|
88
|
-
f.close
|
89
|
-
phrase
|
90
66
|
end
|
91
67
|
end
|