frasier 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ ��# ��pv�άV�;,����K���x��w&'�m;���ѿTļ��c=_az�o�r�@�>pS��9c7:�̑���`AE����k����B�'y��VS�d2���a����N�EG����ik���>�k�(�F��W��&yHC�+���`x'�
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor/ruby
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - 2.1.0
6
+ - rbx-2
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in frasier.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'pry', '~> 0.9.12.6'
8
+ end
9
+
10
+ group :test do
11
+ # Adding rake for Travis.
12
+ gem 'rake'
13
+ gem 'minitest', '~> 5.3.2'
14
+ gem 'mocha', '~> 1.0.0'
15
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 pjaspers
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,71 @@
1
+ [![Build Status](https://travis-ci.org/pjaspers/frasier.svg?branch=master)](https://travis-ci.org/pjaspers/frasier)
2
+
3
+ ## What does it do?
4
+
5
+ Generates phrases using words out of a book. Using high tech computering.
6
+
7
+ Those phrases can be used as passphrases, you can set how many words and which books, so you can claim to have passphrase inspired by Great Literature.
8
+
9
+ For example using 'The Great Gatsby' it generates easy to remember* phrases like:
10
+
11
+ - `gloved modelling pool daylight longer`
12
+ - `wrong flirtation great bembergs happier`
13
+ - `obscurity flat quarter nodding libel`
14
+
15
+ `gem install frasier` and you're good to go.
16
+
17
+ * Note: not actually easy to remember.
18
+
19
+ ## Isn't this Diceware™?
20
+
21
+ Inspired by [Diceware™](http://world.std.com/~reinhold/diceware.html), except instead of being cryptogaphically sound, this uses not a carefully created word list but uses text from books.
22
+
23
+ ```
24
+ Diceware™ is a method for picking passphrases that uses dice to select
25
+ words at random from a special list called the Diceware Word
26
+ List. Each word in the list is preceded by a five digit number. All
27
+ the digits are between one and six, allowing you to use the outcomes
28
+ of five dice rolls to select one unique word from the list.
29
+ ```
30
+
31
+ It uses a simple `rand` to simulate the dice roll, the original [Diceware™](http://world.std.com/~reinhold/diceware.html) recommends against this.
32
+
33
+ Having said all that, it's safer then creating "th3Ult1mat2Pa$$word" for each service you encounter.
34
+
35
+
36
+ ## How do I get books?
37
+
38
+ [Project Gutenberg](http://www.gutenberg.org) has some classics which can be freely downloaded as plain text, after that save them in `~/.config/frasier/` and you're good to go.
39
+
40
+ ## What's with the name?
41
+
42
+ You're on a need to know basis.
43
+
44
+ ## Usage
45
+
46
+ ```
47
+ Usage: frasier [options]
48
+ -n, --number [NUMBER] Generate passphrase with <n> words
49
+ -l, --list-books List available books
50
+ -b, --book [NAME] Specify book to generate from
51
+ -i, --info Show entropy info
52
+ -h, --help Show this message
53
+ --version Show version
54
+ ```
55
+
56
+ ## Signed gem
57
+
58
+ `frasier` is cryptographically signed. To be sure the gem you install hasn’t been tampered with:
59
+
60
+ 1. Download certificate https://raw.github.com/pjaspers/frasier/certs/pjaspers.pem
61
+ 2. Add `gem cert –add pjaspers.pem`
62
+ 3. gem install frasier -P HighSecurity
63
+
64
+ ## Contributing
65
+
66
+ 1. Fork it
67
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
68
+ 3. Do some awesome computering
69
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
70
+ 5. Push to the branch (`git push origin my-new-feature`)
71
+ 6. Create new Pull Request
@@ -0,0 +1,31 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ def abort_with_error(msg)
4
+ abort "\n\e[31mError:\e[0m #{msg}"
5
+ end
6
+
7
+ task :test do
8
+ $LOAD_PATH.unshift('lib', 'test')
9
+ Dir.glob('./test/**/*_test.rb') { |f| require f }
10
+ end
11
+
12
+ task :default => :test
13
+
14
+ task :console do
15
+ require 'pry'
16
+ require './lib/frasier'
17
+ ARGV.clear
18
+ Pry.start Frasier
19
+ end
20
+
21
+
22
+ task :checksum do
23
+ require 'digest/sha2'
24
+ abort_with_error "Set 'GEM' with name-0.x.x to calculate checksum" unless ENV["GEM"]
25
+ name = ENV["GEM"]
26
+ built_gem_path = 'pkg/frasier-0.5.1.gem'
27
+ checksum = Digest::SHA512.new.hexdigest(File.read(built_gem_path))
28
+ checksum_path = 'checksum/frasier-0.5.1.gem.sha512'
29
+ File.open(checksum_path, 'w' ) {|f| f.write(checksum) }
30
+ puts "Wrote checksum to #{checksum_path}"
31
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ require "pp"
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+
5
+ require 'frasier'
6
+
7
+ options = Frasier::CLI.parse(ARGV)
8
+ Frasier::CLI.new(options)
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDKDCCAhCgAwIBAgIBADANBgkqhkiG9w0BAQUFADA6MQ0wCwYDVQQDDARwaWV0
3
+ MRUwEwYKCZImiZPyLGQBGRYFamFzcGUxEjAQBgoJkiaJk/IsZAEZFgJyczAeFw0x
4
+ NDA0MDcyMTQyMDNaFw0xNTA0MDcyMTQyMDNaMDoxDTALBgNVBAMMBHBpZXQxFTAT
5
+ BgoJkiaJk/IsZAEZFgVqYXNwZTESMBAGCgmSJomT8ixkARkWAnJzMIIBIjANBgkq
6
+ hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+SQ5IzhMaUM/jrUBAP5l0/Z5ttLQb2lT
7
+ hotS1Yraz3hclbGhBhDcQilW11GSftUbWhaiMQwNXqaEN9ctmzE5JukOdwhtNSLq
8
+ IDw+TEEXbg/VImlFhryg9vunffPeOBUlnxdY484DOushNN50H/LA+jAoFST3+oZq
9
+ CXuA3yFi8ZTPqhHrEn1bkycUfLX+TOm07ZfCPly9fAVYhOYaVaPeYkHAO83+Ic63
10
+ 9YGqD1sFeZ7hfSxqfYEBxpiM0+qztqHCVNrehkzX2oUmY06eVpSu2mzLYmcCD58f
11
+ inVDRBe/3ygkACxZCA7pjIuqHOpKxSbYMrgEkrAtpA7lkIMaveMY9QIDAQABozkw
12
+ NzAJBgNVHRMEAjAAMB0GA1UdDgQWBBSSJbKSj/62BYq/1utxyqsShRum8jALBgNV
13
+ HQ8EBAMCBLAwDQYJKoZIhvcNAQEFBQADggEBAJkG60vFt/GBuMvTdMtFCw4jJiRo
14
+ 8n6dMQrL2kZdD0ZNeidLfTMzhflv+9ZrWfcFWzfqaGgKJckBd2wlfQiR78ts9zom
15
+ bX9B9n/Ad32womLnb0aeTuEHX6Vy4qs4zl+VnXy4g1NQ2lfcnksUsjBM8v8GYTjy
16
+ ssiOQnzrWxNyjR01uY5g/ON/IlRKNpihe7Qze1oGWdopZP6Lwfhir5ShbDETCKQv
17
+ CuJWUOdBRsHbSraLW8n/vc/fZGqVzDAghs26bxmwicw+4/VgO2soYka81t8pUuG6
18
+ vLWWrtmIv8+cmMgvltP5AR5j2oYHYPPA9YFXuO9t1JVqJiNHm9JNRseEoBc=
19
+ -----END CERTIFICATE-----
@@ -0,0 +1 @@
1
+ 1a4ea27f78e2adfdfd6805e971af94a43f6e9f94aa7ccb6bca9ebef783e2f449115f9ace8b5615ade181d50d43ae2f3e81cc29a6addcae743f87f571b8bdc2dd
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'frasier/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "frasier"
8
+ spec.version = Frasier::VERSION
9
+ spec.authors = ["pjaspers"]
10
+ spec.email = ["piet@jaspe.rs"]
11
+ spec.description = %q{Passphrase generator using plain text books}
12
+ spec.summary = %q{Inspired by Diceware™, except instead of being cryptogaphically sound, this uses not a carefully created word list but uses text from books.}
13
+ spec.homepage = "https://github.com/pjaspers/frasier"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.cert_chain = ['certs/pjaspers.pem']
22
+ spec.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ end
@@ -0,0 +1,20 @@
1
+ require "frasier/version"
2
+ require "frasier/library"
3
+ require "frasier/book"
4
+ require "frasier/dice_list"
5
+ require "frasier/generator"
6
+ require "frasier/cli"
7
+
8
+ module Frasier
9
+
10
+ # At Cornell University, they have an incredible piece of scientific
11
+ # equipment known as the "tunneling electron microscope."
12
+ #
13
+ # Now, this microscope is so powerful that by firing electrons, you
14
+ # can actually see images of the atom, the infinite decimally minute
15
+ # building block of our universe.
16
+ #
17
+ # Roger, if I were using that microscope right now, I still wouldn't
18
+ # be able to locate my interest in your problem.
19
+
20
+ end
@@ -0,0 +1,22 @@
1
+ module Frasier
2
+
3
+ class Book
4
+ attr_accessor :title, :path
5
+
6
+ def initialize(path)
7
+ raise Errno::ENOENT unless File.exist?(path || "")
8
+ @title = title_from_path(path)
9
+ @path = path
10
+ end
11
+
12
+ def dice_word_list
13
+ DiceList.new(File.open(path)).word_list
14
+ end
15
+
16
+ private
17
+
18
+ def title_from_path(path)
19
+ File.basename(path).split("_").map(&:capitalize).join(" ")
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,108 @@
1
+ require "ostruct"
2
+ require "optparse"
3
+
4
+ module Frasier
5
+
6
+ class CLI
7
+ def self.parse(args)
8
+ options = OpenStruct.new
9
+ options.number_of_words = 5
10
+
11
+ opts = OptionParser.new do |opts|
12
+ opts.banner = "Usage: frasier [options]"
13
+
14
+ opts.on("-n", "--number [NUMBER]", Integer, "Generate passphrase with <n> words") do |n|
15
+ options.number_of_words = n.to_i
16
+ end
17
+
18
+ opts.on("-l", "--list-books", "List available books") do |list|
19
+ books = Library.new.books
20
+ longest_title = books.map(&:title).max.length
21
+ puts books.map{|b| " %s - %s" % [b.title.ljust(longest_title), File.basename(b.path)]}
22
+ exit
23
+ end
24
+
25
+ opts.on("-b", "--book [NAME]", String, "Specify book to generate from") do |book|
26
+ lib = Library.new
27
+ unless lib.book_with_name(book)
28
+ puts "I don't know that book"
29
+ exit
30
+ end
31
+ options.book = book
32
+ end
33
+
34
+ opts.on("-i", "--info", "Show entropy info") do |info|
35
+ options.info = info
36
+ end
37
+
38
+ opts.on_tail("-h", "--help", "Show this message") do
39
+ puts opts
40
+ exit
41
+ end
42
+
43
+ opts.on_tail("--version", "Show version") do
44
+ puts Frasier::VERSION
45
+ exit
46
+ end
47
+ end
48
+
49
+ if Library.new.books.empty?
50
+ puts <<BLURB
51
+
52
+ Please install some books into ~/.config/frasier/
53
+ Example:
54
+ curl -L http://www.gutenberg.org/ebooks/8164.txt.utf-8 -o ~/.config/frasier/my_man_jeeves
55
+ BLURB
56
+ exit
57
+ end
58
+
59
+ opts.parse!(args)
60
+ options
61
+ end
62
+
63
+ def initialize(options)
64
+ library = Library.new
65
+ @book = library.book_with_name(options.book) if options.book
66
+ @book = library.random_book unless @book
67
+ number_of_words = options.number_of_words
68
+
69
+ @generator = Generator.new(@book.dice_word_list, number_of_words)
70
+ print_passphrase(options.info)
71
+ end
72
+
73
+ def print_passphrase(info = true)
74
+ phrase = @generator.passphrase
75
+ # Try to copy it
76
+ copy(phrase) if copy_command
77
+ if info
78
+ number_of_guesses = 100000
79
+ duration_in_years = (@generator.duration_to_guess(number_of_guesses)/60.0/60.0/24.0/360.0).round(2)
80
+ puts "From: #{@book.title}"
81
+ puts "Bits of entropy: #{@generator.bits_of_entropy}"
82
+ puts "At 100 000 guesses/s, it would take %s years to guess" % duration_in_years
83
+ puts ""
84
+ end
85
+ puts red(phrase)
86
+ end
87
+
88
+ def copy_command
89
+ os = RbConfig::CONFIG['host_os']
90
+ return 'pbcopy' if os =~ /mac|darwin/
91
+ return 'xclip -selection clipboard' if os =~ /linux|bsd|cygwin/
92
+ nil
93
+ end
94
+
95
+ def copy(value)
96
+ return unless copy_command
97
+ begin
98
+ IO.popen(copy_command,"w") {|cc| cc.write(value)}
99
+ value
100
+ rescue Errno::ENOENT
101
+ end
102
+ end
103
+
104
+ def red(s)
105
+ "\e[31m#{s}\e[0m"
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,59 @@
1
+ require 'stringio'
2
+ require "set"
3
+ module Frasier
4
+
5
+ class DiceList
6
+
7
+ def initialize(io)
8
+ if io.respond_to? :each_line
9
+ @io = io
10
+ else
11
+ raise ArgumentError, "#{io} does not respond to `each_line`"
12
+ end
13
+ end
14
+
15
+ # [Full list of requirements](http://world.std.com/%7Ereinhold/dicewarekit.html)
16
+ #
17
+ # Not following all the rules since most of the books don't seem to have
18
+ # enough unique words to make a sizeable list. We'd need at least 7776 words,
19
+ # but since you can use multiple sources that's not a hard rule.
20
+ #
21
+ def valid_words
22
+ return @valid_words if @valid_words && @valid_words.length > 0
23
+
24
+ @valid_words = Set.new
25
+ @io.each_line do |l|
26
+ # Funny story, in place methods are faster.
27
+ l.gsub!(/[^[:alnum:]^[:blank:]]/, "")
28
+ l.downcase!
29
+ l.strip!
30
+ # Only 'short' words
31
+ l.split(" ").reject{|w| w.length < 3 || w.length > 10}.each do |w|
32
+ @valid_words.add(w)
33
+ end
34
+ end
35
+ @valid_words
36
+ end
37
+
38
+ def word_list
39
+ return @word_list if @word_list
40
+
41
+ # The coolest line in this whole source.
42
+ #
43
+ # Get all permuations with `1,2,3,4,5,6` (e.g. from '11111' to '66666')
44
+ # only take as many as we need.
45
+ indexes = (1..6).to_a.repeated_permutation(5).map(&:join).first(valid_words.length)
46
+
47
+ # Zip the permutations with the words
48
+ # So this creates a hash like:
49
+ #
50
+ # {'11111': 'first',
51
+ # ...
52
+ # '66665': 'another',
53
+ # '66666': 'last'}
54
+
55
+ @word_list = Hash[indexes.zip(valid_words)]
56
+ @word_list
57
+ end
58
+ end
59
+ end