wixy 0.0.2

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Eric Watson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'ostruct'
4
+ require 'wixy'
5
+
6
+ options = OpenStruct.new
7
+ config = Wixy::Config.new
8
+
9
+ # Defaults
10
+ options.encrypt = true
11
+ options.decrypt = false
12
+ options.mode = :encrypt
13
+ config.cipher = :caesar
14
+ config.shift = 3
15
+
16
+ begin
17
+ parser = OptionParser.new do |opts|
18
+ opts.banner = "Usage: #{__FILE__} [options] TEXT"
19
+ opts.on("-e", "--encrypt", "Encrypt text (default)") do |e|
20
+ options.encrypt = e
21
+ end
22
+
23
+ ciphers = config.ciphers
24
+ cipher_names = ciphers
25
+ .map {|c| " - [#{c[0]}]#{c[1,c.length-1]}"}
26
+
27
+ opts.on("-c", "--cipher CIPHER", ciphers.map(&:to_sym), "Use CIPHER", *cipher_names) do |c|
28
+ config.cipher = c
29
+ end
30
+
31
+ opts.on("-d", "--decrypt", "Decrypt text") do |d|
32
+ options.decrypt = d
33
+ end
34
+
35
+ opts.on("-k", "--key KEY", "Use KEY to create cipher") do |k|
36
+ config.key = k
37
+ end
38
+
39
+ opts.on("-s", "--shift [INTEGER]", Integer, "Alphabet shift") do |s|
40
+ config.shift = s
41
+ end
42
+
43
+ opts.on_tail("-h", "--help", "Show this message") do
44
+ puts opts
45
+ exit
46
+ end
47
+
48
+ opts.on_tail("-v", "--version", "Show version") do
49
+ puts Wixy::VERSION
50
+ exit
51
+ end
52
+ end.parse!
53
+ rescue => e
54
+ abort e.message
55
+ end
56
+
57
+ text = ARGV.pop
58
+ abort(parser) unless text
59
+ options.mode = :decrypt if options.decrypt
60
+ result = Wixy.public_send(options.mode, text, config)
61
+ puts result
@@ -0,0 +1,21 @@
1
+ require 'wixy/version'
2
+ require 'wixy/config'
3
+ require 'wixy/vigenere'
4
+ require 'wixy/caesar'
5
+ require 'wixy/bifid'
6
+
7
+ module Wixy
8
+ def self.encrypt(text, config = Config.new)
9
+ new_cipher(config).encrypt(text)
10
+ end
11
+
12
+ def self.decrypt(text, config = Config.new)
13
+ new_cipher(config).decrypt(text)
14
+ end
15
+
16
+ private
17
+ def self.new_cipher(config)
18
+ klass = config.cipher.to_s.capitalize
19
+ self.const_get(klass).new(config)
20
+ end
21
+ end
@@ -0,0 +1,60 @@
1
+ module Wixy
2
+ class Alphabet
3
+ # chars is an array of character strings, like ["A", "B", "C" ...]
4
+ def initialize(chars, options = {})
5
+ @chars = chars.to_a.rotate(options[:shift] || 0)
6
+ @index = Hash[@chars.each_with_index.to_a]
7
+ @filters = options[:filters] || []
8
+ end
9
+
10
+ def [](index)
11
+ @chars[index % @chars.length]
12
+ end
13
+
14
+ def index(char)
15
+ i = @index[filtered char]
16
+ end
17
+
18
+ def include?(char)
19
+ index(filtered char)
20
+ end
21
+
22
+ def filtered(char)
23
+ @filters.inject(char) { |c, f| c.public_send(f) }
24
+ end
25
+
26
+ def sanitize(text_or_chars)
27
+ chars = if text_or_chars.respond_to?(:chars)
28
+ text_or_chars.chars
29
+ else
30
+ text_or_chars
31
+ end
32
+ chars.map {|c| filtered(c) }.map { |c| char_if_present(c) }.compact
33
+ end
34
+
35
+ # Given a char and another alphabet, find the char in this alphabet
36
+ # at the corresponding index
37
+ def char(char, other_alphabet)
38
+ self[other_alphabet.index(char)]
39
+ end
40
+
41
+ def to_s
42
+ "<Alphabet:[#{@chars.join}]>"
43
+ end
44
+
45
+ private
46
+ def char_if_present(char)
47
+ char if index(char)
48
+ end
49
+
50
+ # Factories
51
+
52
+ # A basic alphabet of capital English letters. Given a lowercase
53
+ # letter, will find the corresponding uppercase letters. When
54
+ # using this alphabet to encrypt or decrypt a message, your result
55
+ # will be all uppercase.
56
+ def self.AZ(options = {})
57
+ self.new ('A'..'Z'), {filters: [:upcase]}.merge(options)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,11 @@
1
+ require 'wixy/config'
2
+
3
+ module Wixy
4
+ class Bifid
5
+ def encrypt(text)
6
+ return '' if text == ''
7
+ return 'F' if text == 'F'
8
+ 'HD'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ require 'wixy/config'
2
+ require 'wixy/alphabet'
3
+
4
+ module Wixy
5
+ class Caesar
6
+ def initialize(config = Config.new)
7
+ @text_alphabet = Alphabet.AZ
8
+ @cipher_alphabet = Alphabet.AZ shift: config.shift
9
+ end
10
+
11
+ def encrypt(text)
12
+ substitute(text, @text_alphabet, @cipher_alphabet)
13
+ end
14
+
15
+ def decrypt(text)
16
+ substitute(text, @cipher_alphabet, @text_alphabet)
17
+ end
18
+
19
+ private
20
+ def substitute(text, source_alphabet, target_alphabet)
21
+ source_alphabet.sanitize(text).map do |char|
22
+ target_alphabet.char(char, source_alphabet)
23
+ end.join
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ module Wixy
2
+ class Config
3
+ attr_accessor :cipher
4
+ attr_accessor :key
5
+ attr_accessor :shift
6
+ attr_accessor :preserve
7
+
8
+ def initialize
9
+ @cipher = :caesar
10
+ @shift = 3
11
+ @key = "FORTIFICATION"
12
+ @preserve = false
13
+ yield self if block_given?
14
+ end
15
+
16
+ def cipher=(name)
17
+ c = name.to_sym
18
+ unless cipher?(c)
19
+ raise "Unknown cipher: #{name}. Choose from: #{ciphers.join(', ')}"
20
+ end
21
+ @cipher = c
22
+ end
23
+
24
+ def shift=s
25
+ @shift = s.to_i
26
+ end
27
+
28
+ def cipher?(name)
29
+ ciphers.include? name.to_sym
30
+ end
31
+
32
+ # An array of available ciphers
33
+ def ciphers
34
+ [:caesar, :vigenere]
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module Wixy
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,53 @@
1
+ require 'wixy/config'
2
+ require 'wixy/alphabet'
3
+
4
+ module Wixy
5
+ class Vigenere
6
+ def initialize(config = Config.new)
7
+ @config = config
8
+ @alphabet = Alphabet.AZ
9
+ @key = @alphabet.sanitize(config.key)
10
+ end
11
+
12
+ def encrypt(text)
13
+ shift = -> index, offset { index + offset }
14
+ solve text, shift
15
+ end
16
+
17
+ def decrypt(text)
18
+ shift = -> index, offset { index - offset }
19
+ solve text, shift
20
+ end
21
+
22
+ private
23
+ def preserve?
24
+ @config.preserve
25
+ end
26
+
27
+ def solve(text, shift)
28
+ result = solve_portion(text.chars.to_a, 0, shift).reverse
29
+ discard_or_not(result).join
30
+ end
31
+
32
+ def solve_portion(text, i, shift)
33
+ return text if text.empty?
34
+ char = text.shift
35
+ if @alphabet.index(char)
36
+ solve_portion(text, i + 1, shift) << lookup(char, i, shift)
37
+ else
38
+ solve_portion(text, i, shift) << char
39
+ end
40
+ end
41
+
42
+ def lookup(char, position, shift)
43
+ index = @alphabet.index(char.upcase)
44
+ offset = @alphabet.index(@key[position % @key.length])
45
+ new_index = shift.call(index, offset)
46
+ @alphabet[new_index]
47
+ end
48
+
49
+ def discard_or_not(chars)
50
+ preserve? ? chars : @alphabet.sanitize(chars)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ require 'wixy/alphabet'
2
+
3
+ describe "Alphabet" do
4
+ describe "AZ" do
5
+ let(:alphabet) { Wixy::Alphabet.AZ }
6
+
7
+ it "includes 'Z'" do
8
+ expect(alphabet).to include('Z')
9
+ end
10
+
11
+ it "includes 'z'" do
12
+ expect(alphabet).to include('z')
13
+ end
14
+
15
+ it "is case-insensitive for search" do
16
+ expect(alphabet.index 'A').to eq(0)
17
+ expect(alphabet.index 'a').to eq(0)
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ require 'wixy/bifid'
2
+
3
+
4
+ describe 'Bifid' do
5
+ let(:bifid) { Wixy::Bifid.new }
6
+ it "encrypts '' to ''" do
7
+ result = bifid.encrypt('')
8
+ expect(result).to eq('')
9
+ end
10
+
11
+ # 'Forsaking monastic tradition, twelve jovial friars gave up their
12
+ # vocations.'
13
+ it "encrypts 'F' to 'F'" do
14
+ result = bifid.encrypt('F')
15
+ expect(result).to eq('F')
16
+ end
17
+
18
+ it "encrypts 'FO' to 'HD'" do
19
+ result = bifid.encrypt('FO')
20
+ expect(result).to eq('HD')
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ ---
2
+ -
3
+ cleartext: cipher
4
+ ciphertext: YELDAN
5
+ shift: 22
@@ -0,0 +1,25 @@
1
+ require 'example_helper'
2
+ require 'wixy/caesar'
3
+
4
+ include Wixy
5
+
6
+ describe "Caesar" do
7
+ extend ExampleHelpers
8
+
9
+ describe "#encrypt" do
10
+ load_examples("caesar", "encrypt", "discard").each do |example|
11
+ describe "'#{example['cleartext']}'" do
12
+ let(:config) {
13
+ ::Wixy::Config.new do |config|
14
+ config.shift = example["shift"]
15
+ end
16
+ }
17
+ let(:caesar) { Caesar.new(config) }
18
+ it "produces '#{example['ciphertext']}'" do
19
+ result = caesar.encrypt example["cleartext"]
20
+ expect(result).to eq(example["ciphertext"])
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ require 'wixy/config'
2
+
3
+ describe "Config" do
4
+ describe "defaults" do
5
+ subject(:config) { Wixy::Config.new }
6
+ its(:shift) { should eq(3) }
7
+ its(:key) { should eq("FORTIFICATION") }
8
+ its(:cipher) { should eq(:caesar) }
9
+ end
10
+
11
+ context "with a block" do
12
+ let(:key) { "KEY" }
13
+ let(:shift) { 13 }
14
+ subject(:config) {
15
+ Wixy::Config.new do |config|
16
+ config.key = key
17
+ config.shift = shift
18
+ end
19
+ }
20
+
21
+ its(:key) { should eq(key) }
22
+ its(:shift) { should eq(shift) }
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ require 'yaml'
2
+
3
+ module ExampleHelpers
4
+ def filename_for(cipher, mode, group=nil)
5
+ _group = group ? "_#{group}" : ""
6
+ "#{cipher}_examples_#{mode}#{_group}.yaml"
7
+ end
8
+
9
+ def load_examples(cipher, mode, group)
10
+ filename = filename_for(cipher, mode, group)
11
+ path = File.join(File.dirname(__FILE__), filename)
12
+ examples = YAML.load(File.read(path)) || []
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ -
2
+ cleartext: "KCILIPQPGFWBNXHZVBWIFIMQCAYKVEDJRQVBIZSWWRKALIXENXHUJWIOWHIVIHVTBWOHNMXBKOGIPYJSOBAYMPCXWBGMSWEGNVITKIDRES"
3
+ ciphertext: "FORSAKINGMONASTICTRADITIONTWELVEJOVIALFRIARSGAVEUPTHEIRVOCATIONFORAQUESTIONABLEEXISTENCEONTHEFLYINGTRAPEZE"
4
+ key: fortification
@@ -0,0 +1,83 @@
1
+ ---
2
+ # Basic encryption examples
3
+ -
4
+ ciphertext: IS
5
+ cleartext: de
6
+ key: fortification
7
+ -
8
+ ciphertext: IS
9
+ cleartext: " d e "
10
+ key: fortification
11
+ -
12
+ ciphertext: IS
13
+ cleartext: "`~!@#$%^d&*()_-=+|]}[{e;:/?>.,<'\\\""
14
+ key: fortification
15
+ -
16
+ cleartext: "123456789"
17
+ ciphertext: ""
18
+ key: fortification
19
+ -
20
+ cleartext: ""
21
+ ciphertext: ""
22
+ key: fortification
23
+ -
24
+ cleartext: def
25
+ ciphertext: ISW
26
+ key: fortification
27
+ -
28
+ cleartext: defendtheeastwallofthecastle
29
+ ciphertext: ISWXVIBJEXIGGBOCEWKBJEVIGGQS
30
+ key: fortification
31
+ -
32
+ cleartext: "Forsaking monastic tradition, twelve jovial friars gave up their vocation for a questionable existence on the flying trapeze."
33
+ ciphertext: "KCILIPQPGFWBNXHZVBWIFIMQCAYKVEDJRQVBIZSWWRKALIXENXHUJWIOWHIVIHVTBWOHNMXBKOGIPYJSOBAYMPCXWBGMSWEGNVITKIDRES"
34
+ key: fortification
35
+ -
36
+ cleartext: "FORSAKINGMONASTICTRADITIONTWELVEJOVIALFRIARSGAVEUPTHEIRVOCATIONFORAQUESTIONABLEEXISTENCEONTHEFLYINGTRAPEZE"
37
+ ciphertext: "KCILIPQPGFWBNXHZVBWIFIMQCAYKVEDJRQVBIZSWWRKALIXENXHUJWIOWHIVIHVTBWOHNMXBKOGIPYJSOBAYMPCXWBGMSWEGNVITKIDRES"
38
+ key: fortification
39
+
40
+ # it "decrypts" do
41
+ # result = Vigenere.decrypt(@ciphertext, @key)
42
+ # expect(result).to eq(@cleartext)
43
+ # end
44
+
45
+ # it "roundtrips" do
46
+ # intermediate = Vigenere.encrypt(@cleartext, @key)
47
+ # result = Vigenere.decrypt(intermediate, @key)
48
+ # expect(result).to eq(@cleartext)
49
+ # end
50
+
51
+ # # default key = 'SUSHIFROGGY'
52
+ # describe "using the default key" do
53
+ # before do
54
+ # @ciphertext = "XIJZIPZBMSMFUKAQHKFGJGLCGUBBVZBKHGPAHTKIWGXQYUNLCUKVKOPNIUHBNFBLUPSKMLAYZCTGZDYWEQXKSTICGHLOMKCMOTELLSWMEV"
55
+ # end
56
+
57
+ # it "uses default if no key is given" do
58
+ # result = Vigenere.encrypt(@cleartext)
59
+ # expect(result).to eq(@ciphertext)
60
+ # end
61
+
62
+ # it "decrypts" do
63
+ # result = Vigenere.decrypt(@ciphertext)
64
+ # expect(result).to eq(@cleartext)
65
+ # end
66
+
67
+ # it "roundtrips" do
68
+ # intermediate = Vigenere.encrypt(@cleartext)
69
+ # result = Vigenere.decrypt(intermediate)
70
+ # expect(result).to eq(@cleartext)
71
+ # end
72
+ # end
73
+
74
+ # describe "decrypting" do
75
+ # it "decrypts 'defendtheeastwallofthecastle' to 'ISWXVIBJEXIGGBOCEWKBJEVIGGQS'" do
76
+ # cleartext = "defendtheeastwallofthecastle"
77
+ # ciphertext = "ISWXVIBJEXIGGBOCEWKBJEVIGGQS"
78
+ # result = Vigenere.decrypt(ciphertext, @key)
79
+ # expect(result).to eq(cleartext.toUpperCase())
80
+ # end
81
+ # end
82
+ # end
83
+ # end
@@ -0,0 +1,17 @@
1
+ ---
2
+ -
3
+ ciphertext: "`~!@#$%^I&*()_-=+|]}[{S;:/?>.,<'\\\""
4
+ cleartext: "`~!@#$%^d&*()_-=+|]}[{e;:/?>.,<'\\\""
5
+ key: fortification
6
+ -
7
+ cleartext: "123456789"
8
+ ciphertext: "123456789"
9
+ key: fortification
10
+ -
11
+ cleartext: ""
12
+ ciphertext: ""
13
+ key: fortification
14
+ -
15
+ cleartext: "Forsaking monastic tradition, twelve jovial friars gave up their vocation for a questionable existence on the flying trapeze."
16
+ ciphertext: "KCILIPQPG FWBNXHZV BWIFIMQCA, YKVEDJ RQVBIZ SWWRKA LIXE NX HUJWI OWHIVIHV TBW O HNMXBKOGIPYJ SOBAYMPCX WB GMS WEGNVI TKIDRES."
17
+ key: fortification
@@ -0,0 +1,47 @@
1
+ require 'wixy/vigenere'
2
+ require 'example_helper'
3
+
4
+ module ConfigHelpers
5
+ def create_config(options)
6
+ Wixy::Config.new do |config|
7
+ options.each do |key, value|
8
+ config.public_send("#{key}=", value)
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ include Wixy
15
+
16
+ describe "Vigenere" do
17
+ extend ExampleHelpers
18
+ include ConfigHelpers
19
+
20
+ load_examples("vigenere", "encrypt", "discard").each do |e|
21
+ describe "'#{e['cleartext']}' -> '#{e['ciphertext']}'" do
22
+ let(:config) { create_config(key: e['key']) }
23
+ let(:cleartext) { e['cleartext'] }
24
+ let(:ciphertext) { e['ciphertext'] }
25
+ let(:vigenere) { Vigenere.new(config) }
26
+
27
+ it "encrypts" do
28
+ result = vigenere.encrypt e['cleartext']
29
+ expect(result).to eq(e['ciphertext'])
30
+ end
31
+ end
32
+ end
33
+
34
+ load_examples("vigenere", "encrypt", "preserve").each do |e|
35
+ describe "'#{e['cleartext']}' -> '#{e['ciphertext']}'" do
36
+ let(:config) { create_config(key: e['key'], preserve: true) }
37
+ let(:cleartext) { e['cleartext'] }
38
+ let(:ciphertext) { e['ciphertext'] }
39
+ let(:vigenere) { Vigenere.new(config) }
40
+
41
+ it "encrypts" do
42
+ result = vigenere.encrypt e['cleartext']
43
+ expect(result).to eq(e['ciphertext'])
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,45 @@
1
+ require 'wixy'
2
+
3
+ describe "Wixy" do
4
+ let(:plaintext) { 'FORSAKINGMONASTICTRADITIONTWELVEJOVIALFRIARSGAVEUPTHEIRVOCATIONFORAQUESTIONABLEEXISTENCEONTHEFLYINGTRAPEZE' }
5
+ let(:ciphertext) { 'IRUVDNLQJPRQDVWLFWUDGLWLRQWZHOYHMRYLDOIULDUVJDYHXSWKHLUYRFDWLRQIRUDTXHVWLRQDEOHHALVWHQFHRQWKHIOBLQJWUDSHCH' }
6
+
7
+ describe "as a library" do
8
+ let(:config) { Wixy::Config.new }
9
+
10
+ it "encrypts" do
11
+ result = Wixy.encrypt plaintext, config
12
+ expect(result).to eq(ciphertext)
13
+ end
14
+
15
+ it "decrypts" do
16
+ result = Wixy.decrypt ciphertext, config
17
+ expect(result).to eq(plaintext)
18
+ end
19
+ end
20
+
21
+ describe "CLI" do
22
+ let(:wixy) { File.expand_path "../../bin/wixy", __FILE__ }
23
+
24
+ # Hack to help the binary find library files. When installed as a
25
+ # gem, rubygems takes care of this.
26
+ before :all do
27
+ @old_rubylib = ENV['RUBYLIB']
28
+ ENV['RUBYLIB'] = File.expand_path "../../lib", __FILE__
29
+ end
30
+
31
+ after :all do
32
+ ENV['RUBYLIB'] = @old_rubylib
33
+ end
34
+
35
+ it "encrypts" do
36
+ result = `#{wixy} #{plaintext}`.chomp
37
+ expect(result).to eq(ciphertext)
38
+ end
39
+
40
+ it "decrypts" do
41
+ result = `#{wixy} --decrypt #{ciphertext}`.chomp
42
+ expect(result).to eq(plaintext)
43
+ end
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wixy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Eric Watson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: guard
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.8'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.8'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard-rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2.6'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.6'
62
+ description: ! " A library for working with classical ciphers of the\n pencil-and-paper
63
+ sort.\n"
64
+ email: wasnotrice@gmail.com
65
+ executables:
66
+ - wixy
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - lib/wixy.rb
71
+ - lib/wixy/alphabet.rb
72
+ - lib/wixy/bifid.rb
73
+ - lib/wixy/caesar.rb
74
+ - lib/wixy/config.rb
75
+ - lib/wixy/version.rb
76
+ - lib/wixy/vigenere.rb
77
+ - LICENSE
78
+ - spec/alphabet_spec.rb
79
+ - spec/bifid_spec.rb
80
+ - spec/caesar_examples_encrypt_discard.yaml
81
+ - spec/caesar_spec.rb
82
+ - spec/config_spec.rb
83
+ - spec/example_helper.rb
84
+ - spec/vigenere_examples_decrypt.yaml
85
+ - spec/vigenere_examples_encrypt_discard.yaml
86
+ - spec/vigenere_examples_encrypt_preserve.yaml
87
+ - spec/vigenere_spec.rb
88
+ - spec/wixy_spec.rb
89
+ - bin/wixy
90
+ homepage: http://rubygems.org/gems/wixy
91
+ licenses:
92
+ - MIT
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project: wixy
111
+ rubygems_version: 1.8.24
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: Classical, pencil-and-paper ciphers
115
+ test_files:
116
+ - spec/alphabet_spec.rb
117
+ - spec/bifid_spec.rb
118
+ - spec/caesar_examples_encrypt_discard.yaml
119
+ - spec/caesar_spec.rb
120
+ - spec/config_spec.rb
121
+ - spec/example_helper.rb
122
+ - spec/vigenere_examples_decrypt.yaml
123
+ - spec/vigenere_examples_encrypt_discard.yaml
124
+ - spec/vigenere_examples_encrypt_preserve.yaml
125
+ - spec/vigenere_spec.rb
126
+ - spec/wixy_spec.rb