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