spass 0.0.2 → 0.0.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.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- spass (0.0.1)
4
+ spass (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/History.md CHANGED
@@ -1,6 +1,14 @@
1
1
  History
2
2
  =======
3
3
 
4
+ 0.0.3
5
+ -----
6
+
7
+ - Eliminate -l/--length argument
8
+ - Use -w/--words argument to specify the number of words
9
+ - Default --chars to 8 instead of 10
10
+
11
+
4
12
  0.0.2
5
13
  -----
6
14
 
data/README.md CHANGED
@@ -10,8 +10,9 @@ computer to guess.
10
10
  Prerequisites
11
11
  -------------
12
12
 
13
- Currently, spass only words on Unix-like systems, which are expected to have a
14
- `/usr/share/dict/words` file. Future versions may support other platforms.
13
+ spass assumes you have a dictionary file to use as its source of words. By
14
+ default, `/usr/share/dict/words` is used, but you can pass your own dictionary
15
+ using the `-f/--file` option.
15
16
 
16
17
 
17
18
  Installation
@@ -25,30 +26,38 @@ spass is distributed as a gem, so just do:
25
26
  Usage
26
27
  -----
27
28
 
28
- Run `spass` from the command-line to see usage notes. The first argument is the
29
- minimum passphrase length (in characters). Examples:
29
+ When run without arguments, spass generates 10 passphrases, each 4 words long,
30
+ using words up to 8 characters long. You can configure this behavior by passing
31
+ command-line arguments; run `spass -h` to see full usage notes.
30
32
 
31
- $ spass 12
32
- hive frighten
33
+ Examples:
33
34
 
34
- $ spass 24
35
- moppet castigator harvesters
35
+ $ spass -w 3 # Generate 3-word phrases
36
+ $ spass -w 5 -n 20 # Generate twenty 5-word phrases
37
+ $ spass -c 6 # Limit words to 6 characters
38
+ $ spass -d # Append a digit to each word
39
+ $ spass -f mywords.txt # Get words from mywords.txt (one per line)
36
40
 
37
- $ spass 32
38
- munificent icebound raymond clorets
39
41
 
40
- Passphrases are guaranteed to be at least as long as the given number, but
41
- may be longer. By default, the words are taken from `/usr/share/dict/words`;
42
- if you want to use words from a different dictionary, pass a second argument:
43
42
 
44
- $ spass 12 my_words.txt
43
+ Disclaimer
44
+ ----------
45
+
46
+ spass makes absolutely no guarantee that its output results in secure
47
+ passwords. If you use spass to protect your bank account or your porn
48
+ collection, I cannot be held responsible if you lose your money or marriage.
49
+ [Check your password strength](http://rumkin.com/tools/password/passchk.php)
50
+ before using it for anything important. Passwords generated with spass are
51
+ inherently vulnerable to a dictionary attack; the only thing that can make
52
+ them resistant to such attacks is their length, so always use at least three
53
+ (preferably more) words.
45
54
 
46
55
 
47
56
  Future plans
48
57
  ------------
49
58
 
50
59
  - Optional inclusion of uppercase and symbols
51
- - Avoid word repetition
60
+ - Avoid possible word repetition
52
61
 
53
62
 
54
63
  MIT License
data/bin/spass CHANGED
@@ -5,45 +5,37 @@ require 'optparse'
5
5
 
6
6
  HELP = <<EOF
7
7
 
8
- This script generates a plain-English passphrase of at least the given length
9
- (in characters), using random words from the given dictionary file
10
- (/usr/share/dict/words by default). Only lowercase letters a-z will be included
11
- in the output, making passphrases relatively easy to type (though usually
12
- nonsensical).
8
+ This script generates passphrases using random words from the given dictionary
9
+ file (default: /usr/share/dict/words). It was inspired by http://xkcd.com/936/
13
10
 
14
11
  Examples:
15
12
 
16
- $ spass -l 12
17
- hive frighten
13
+ $ spass -w 3 # Generate 3-word phrases
14
+ $ spass -w 5 -n 20 # Generate twenty 5-word phrases
15
+ $ spass -c 6 # Limit words to 6 characters
16
+ $ spass -d # Append a digit to each word
17
+ $ spass -f mywords.txt # Get words from mywords.txt (one per line)
18
18
 
19
- $ spass -l 24
20
- moppet castigator harvesters
21
-
22
- A 32-character passphrase has about 120 bits of entropy, which is overkill for
23
- most purposes. A 24-character passphrase clocks in at about 90 bits of entropy,
24
- suitable for most high-security applications like root passwords or financial
25
- records. You might want to use a password checker to verify the strength of
26
- your passphrase after generating one that you like:
27
-
28
- http://rumkin.com/tools/password/passchk.php
29
-
30
- Inspired by http://xkcd.com/936/
19
+ Passphrases generated from dictionary words are inherently vulnerable to
20
+ dictionary attacks; using more and/or longer words strengthens them against
21
+ such attacks. The default settings are intended to yield relatively strong,
22
+ easy-to-remember passphrases.
31
23
 
32
24
  EOF
33
25
 
34
26
  options = {
35
- :length => 24,
36
27
  :number => 10,
37
28
  :dict => '/usr/share/dict/words',
38
29
  :digits => false,
39
- :chars => 10,
30
+ :chars => 8,
31
+ :words => 4,
40
32
  }
41
33
 
42
34
  optparse = OptionParser.new do |opts|
43
- opts.on('-l', '--length [NUM]', Integer,
44
- "Ensure passphrases are at least NUM characters.",
45
- "Default: #{options[:length]}") do |len|
46
- options[:length] = len
35
+ opts.on('-w', '--words [NUM]', Integer,
36
+ "Ensure passphrases are at least NUM words long.",
37
+ "Default: #{options[:words]}") do |words|
38
+ options[:words] = words
47
39
  end
48
40
 
49
41
  opts.on('-n', '--number [NUM]', Integer,
@@ -59,14 +51,14 @@ optparse = OptionParser.new do |opts|
59
51
  end
60
52
 
61
53
  opts.on('-d', '--digits',
62
- "Include random numbers from 1-99.",
63
- "Default: False") do |digits|
54
+ "Append a random digit from 0-9 to each word.",
55
+ "Default: #{options[:digits]}") do |digits|
64
56
  options[:digits] = digits
65
57
  end
66
58
 
67
59
  opts.on('-c', '--chars NUM',
68
60
  "Limit words to NUM characters in length.",
69
- "Default: 10") do |chars|
61
+ "Default: #{options[:chars]}") do |chars|
70
62
  options[:chars] = chars
71
63
  end
72
64
 
@@ -86,7 +78,8 @@ rescue OptionParser::InvalidOption => e
86
78
  end
87
79
 
88
80
  sp = Generator.new(options[:dict], options)
81
+ puts "Read #{sp.dict.count} words up to #{sp.chars} characters long from #{sp.file}"
89
82
  options[:number].times do
90
- puts sp.generate(options[:length], :digits=>options[:digits])
83
+ puts sp.generate(options[:words], :digits=>options[:digits])
91
84
  end
92
85
 
data/lib/spass.rb CHANGED
@@ -1,25 +1,25 @@
1
1
 
2
2
  class Generator
3
- # Create a Generator using the given word dictionary, returning
4
- # only words that match the given regular expression
5
- def initialize(dict_path='/usr/share/dict/words', options={})
6
- @dict_path = dict_path
7
- @dict = read_dict(dict_path, options)
3
+ attr_reader :dict, :chars, :allowed, :file
4
+ # Create a Generator using the given word dictionary
5
+ def initialize(file='/usr/share/dict/words', options={})
6
+ @file = file
7
+ @allowed = options[:allowed] || /^[a-z]+$/
8
+ @chars = (options[:chars] || 10).to_i
9
+ @dict = read_dict
8
10
  end
9
11
 
10
12
  # Read a word dictionary from the given file, and return an array
11
13
  # of elements that match the allowed regex. Raise an exception if
12
14
  # the given dictionary file cannot be found.
13
- def read_dict(path, options={})
14
- allowed = options[:allowed] || /^[a-z]+$/
15
- chars = (options[:chars] || 10).to_i
16
- if !File.file?(path)
17
- raise RuntimeError, "Cannot find dict file: #{path}"
15
+ def read_dict
16
+ if !File.file?(@file)
17
+ raise RuntimeError, "Cannot find dict file: #{@file}"
18
18
  end
19
19
  dict = []
20
- IO.readlines(path).each do |line|
20
+ IO.readlines(@file).each do |line|
21
21
  line.strip!
22
- if line.length <= chars && line =~ allowed
22
+ if line.length <= @chars && line =~ @allowed
23
23
  dict << line
24
24
  end
25
25
  end
@@ -31,19 +31,20 @@ class Generator
31
31
  @dict[rand(@dict.count)]
32
32
  end
33
33
 
34
- # Return a random number from 1 to 99
34
+ # Return a random number from 0 to 9
35
35
  def random_number
36
- 1 + rand(99)
36
+ rand(10)
37
37
  end
38
38
 
39
- # Generate a passphrase of at least the given length in characters
40
- def generate(length, options={})
41
- phrase = ''
42
- while phrase.length < length + 1 # to account for trailing space
43
- phrase += "#{random_word} "
44
- phrase += "#{random_number} " if options[:digits]
39
+ # Generate a passphrase with the given number of words
40
+ def generate(num_words, options={})
41
+ words = []
42
+ num_words.times do
43
+ word = random_word
44
+ word += random_number.to_s if options[:digits]
45
+ words << word
45
46
  end
46
- return phrase.chomp
47
+ return words.join(' ')
47
48
  end
48
49
  end
49
50
 
data/spass.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "spass"
3
- s.version = "0.0.2"
3
+ s.version = "0.0.3"
4
4
  s.summary = "Generate passphrases"
5
5
  s.description = <<-EOS
6
6
  spass generates passphrases using random words
data/spec/spass_spec.rb CHANGED
@@ -3,31 +3,35 @@ require 'spass'
3
3
  TEST_DICT = File.expand_path('../data/ten_words', __FILE__)
4
4
 
5
5
  describe Generator do
6
- before(:all) do
6
+ before(:each) do
7
7
  @sp = Generator.new(TEST_DICT)
8
8
  end
9
9
 
10
10
 
11
- describe "#read_dict" do
11
+ describe "#initialize" do
12
12
  it "returns an array of lines from the given file" do
13
- @sp.read_dict(TEST_DICT).should == [
13
+ @sp = Generator.new(TEST_DICT)
14
+ @sp.dict.should == [
14
15
  'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
15
16
  end
16
17
 
17
18
  it "only returns words matching a regex" do
18
- @sp.read_dict(TEST_DICT, :allowed=>/^t/).should == ['two', 'three', 'ten']
19
- @sp.read_dict(TEST_DICT, :allowed=>/^f/).should == ['four', 'five']
20
- @sp.read_dict(TEST_DICT, :allowed=>/e$/).should == ['one', 'three', 'five', 'nine']
19
+ @sp = Generator.new(TEST_DICT, :allowed=>/^t/)
20
+ @sp.dict.should == ['two', 'three', 'ten']
21
+ @sp = Generator.new(TEST_DICT, :allowed=>/^f/)
22
+ @sp.dict.should == ['four', 'five']
23
+ @sp = Generator.new(TEST_DICT, :allowed=>/e$/)
24
+ @sp.dict.should == ['one', 'three', 'five', 'nine']
21
25
  end
22
26
 
23
27
  it "only returns words with N chars or fewer" do
24
- @sp.read_dict(TEST_DICT, :chars=>3).should == ['one', 'two', 'six', 'ten']
28
+ @sp = Generator.new(TEST_DICT, :chars=>3)
29
+ @sp.dict.should == ['one', 'two', 'six', 'ten']
25
30
  end
26
31
 
27
32
  it "raises an exception when the file does not exist" do
28
- path = File.expand_path('non/existent/path')
29
33
  lambda do
30
- @sp.read_dict(path)
34
+ Generator.new(File.expand_path('non/existent/path'))
31
35
  end.should raise_error(RuntimeError, /Cannot find dict file/)
32
36
  end
33
37
  end
@@ -43,28 +47,27 @@ describe Generator do
43
47
 
44
48
 
45
49
  describe "#random_number" do
46
- it "returns a number between 1 and 999" do
47
- 1000.times do
50
+ it "returns a number between 0 and 9" do
51
+ 100.times do
48
52
  num = @sp.random_number
49
- num.should be >= 1
50
- num.should be <= 99
53
+ num.should be >= 0
54
+ num.should be <= 9
51
55
  end
52
56
  end
53
57
  end
54
58
 
55
59
 
56
60
  describe "#generate" do
57
- it "is at least the given length" do
58
- [10, 15, 20, 25, 30, 35, 40].each do |len|
59
- 10.times do
60
- @sp.generate(len).length.should be >= len
61
- end
61
+ it "has the given number of words" do
62
+ [1, 2, 3, 4, 5, 6].each do |words|
63
+ phrase = @sp.generate(words)
64
+ phrase.split.count.should == words
62
65
  end
63
66
  end
64
67
 
65
68
  it "includes digits when :digits is true" do
66
69
  10.times do
67
- @sp.generate(24, :digits=>true).should =~ /^([a-z]+ [0-9]+ ?)+$/
70
+ @sp.generate(24, :digits=>true).should =~ /^([a-z]+[0-9] ?)+$/
68
71
  end
69
72
  end
70
73
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spass
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Eric Pierce
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-01 00:00:00 -06:00
18
+ date: 2011-11-02 00:00:00 -06:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency