pontifex 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.rvmrc +1 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +50 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.markdown +53 -0
  6. data/Rakefile +54 -0
  7. data/VERSION +1 -0
  8. data/bin/pontifex +5 -0
  9. data/cucumber.yml +3 -0
  10. data/feature/pontifex_interactive.feature +161 -0
  11. data/feature/pontifex_with_files.feature +137 -0
  12. data/feature/support/env.rb +15 -0
  13. data/lib/pontifex/card.rb +70 -0
  14. data/lib/pontifex/cipher.rb +49 -0
  15. data/lib/pontifex/key_stream.rb +79 -0
  16. data/lib/pontifex.rb +114 -0
  17. data/pontifex.gemspec +99 -0
  18. data/spec/pontifex/card_spec.rb +84 -0
  19. data/spec/pontifex/cipher_spec.rb +23 -0
  20. data/spec/pontifex/key_stream_spec.rb +92 -0
  21. data/spec/pontifex/pontifex_spec.rb +4 -0
  22. data/spec/spec_helper.rb +12 -0
  23. data/vendor/cache/aruba-0.3.6.gem +0 -0
  24. data/vendor/cache/builder-3.0.0.gem +0 -0
  25. data/vendor/cache/childprocess-0.1.9.gem +0 -0
  26. data/vendor/cache/cucumber-0.10.3.gem +0 -0
  27. data/vendor/cache/diff-lcs-1.1.2.gem +0 -0
  28. data/vendor/cache/ffi-1.0.9.gem +0 -0
  29. data/vendor/cache/gherkin-2.3.9.gem +0 -0
  30. data/vendor/cache/git-1.2.5.gem +0 -0
  31. data/vendor/cache/jeweler-1.6.0.gem +0 -0
  32. data/vendor/cache/json-1.5.1.gem +0 -0
  33. data/vendor/cache/rake-0.9.0.gem +0 -0
  34. data/vendor/cache/rcov-0.9.9.gem +0 -0
  35. data/vendor/cache/rspec-2.6.0.gem +0 -0
  36. data/vendor/cache/rspec-core-2.6.3.gem +0 -0
  37. data/vendor/cache/rspec-expectations-2.6.0.gem +0 -0
  38. data/vendor/cache/rspec-mocks-2.6.0.gem +0 -0
  39. data/vendor/cache/term-ansicolor-1.0.5.gem +0 -0
  40. data/vendor/cache/trollop-1.16.2.gem +0 -0
  41. metadata +175 -0
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.9.2-p136
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem "trollop"
6
+
7
+ # Add dependencies to develop your gem here.
8
+ # Include everything needed to run rake, tests, features, etc.
9
+ group :development do
10
+ gem "rspec", "~> 2.6.0"
11
+ gem "cucumber", ">= 0"
12
+ gem "aruba", ">=0"
13
+ gem "bundler", "~> 1.0.0"
14
+ gem "jeweler", "~> 1.6.0"
15
+ gem "rcov", ">= 0"
16
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,50 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ aruba (0.3.6)
5
+ childprocess (>= 0.1.7)
6
+ cucumber (>= 0.10.0)
7
+ rspec (>= 2.5.0)
8
+ builder (3.0.0)
9
+ childprocess (0.1.9)
10
+ ffi (~> 1.0.6)
11
+ cucumber (0.10.3)
12
+ builder (>= 2.1.2)
13
+ diff-lcs (>= 1.1.2)
14
+ gherkin (>= 2.3.8)
15
+ json (>= 1.4.6)
16
+ term-ansicolor (>= 1.0.5)
17
+ diff-lcs (1.1.2)
18
+ ffi (1.0.9)
19
+ gherkin (2.3.9)
20
+ json (>= 1.4.6)
21
+ git (1.2.5)
22
+ jeweler (1.6.0)
23
+ bundler (~> 1.0.0)
24
+ git (>= 1.2.5)
25
+ rake
26
+ json (1.5.1)
27
+ rake (0.9.0)
28
+ rcov (0.9.9)
29
+ rspec (2.6.0)
30
+ rspec-core (~> 2.6.0)
31
+ rspec-expectations (~> 2.6.0)
32
+ rspec-mocks (~> 2.6.0)
33
+ rspec-core (2.6.3)
34
+ rspec-expectations (2.6.0)
35
+ diff-lcs (~> 1.1.2)
36
+ rspec-mocks (2.6.0)
37
+ term-ansicolor (1.0.5)
38
+ trollop (1.16.2)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ aruba
45
+ bundler (~> 1.0.0)
46
+ cucumber
47
+ jeweler (~> 1.6.0)
48
+ rcov
49
+ rspec (~> 2.6.0)
50
+ trollop
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Errin Larsen
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.
data/README.markdown ADDED
@@ -0,0 +1,53 @@
1
+ # Pontifex: a Solitaire Cipher implementation
2
+
3
+ Pontifex provides a CLI interface to encrypt and decrypt messages utilizing [The Solitaire Ciphear](http://www.schneier.com/solitaire.html) as designed by Bruce Schneier and featured in Neal Stephenson's *Cryptonomicon*.
4
+
5
+ This implementation was developed as a solution to [Ruby Quiz #1](http://www.rubyquiz.com/quiz1.html)
6
+
7
+ ## Pontifex
8
+
9
+ Use RubyGems to install pontifex:
10
+
11
+ $ gem install pontifex
12
+
13
+ Once pontifex is installed, you can use it by passing it one of two subcommands: `encrypt` or `decrypt`
14
+
15
+ $ pontifex encrypt
16
+ Enter the message to encrypt.
17
+ enter 'Done' on a line by itself when you are done
18
+
19
+ At this point, type your message into `STDIN`. On a line by itself, enter 'done' to signal that your message is complete.
20
+
21
+ Your encrypted message will be output to the `STDOUT`.
22
+
23
+ ## Key files
24
+
25
+ The Solitaire Cipher requires a keyed deck of cards. By default, the cipher will use a deck of cards ordered Ace to King, suites clubs thru spades, with the two jokers on the bottom of the deck.
26
+
27
+ If you'd like to key the deck in a different way (and you do), pass the `-d` option to pontifex and the name of the key file. This file should have the 54 cards, seperated by commas, in the order you prefer.
28
+
29
+ $ cat some_other.key
30
+ Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,
31
+ Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,ja,
32
+ Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,jb,
33
+ As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks
34
+
35
+ $ pontifex encrypt -d some_other.key
36
+
37
+ ## Output files
38
+
39
+ If you'd like to output your encrypted or decrypted message to a file, just pass the `-o` option and a file name.
40
+
41
+ $ pontifex encrypt -o encrypted_message.txt
42
+
43
+ This option and the `-d` option can (and should) be combined.
44
+
45
+ ## Input files
46
+
47
+ Any files listed on the command line after the above options will be concatenated and will be considered input for whichever sub-command requested. This will turn off input via STDIN.
48
+
49
+ $ pontifex encrypt -d some_other.key -o encrypted_results.txt message_to_be_encrypted.txt [...]
50
+
51
+ ## Copyright
52
+
53
+ Copyright (c) 2008-2010 Errin Larsen. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "pontifex"
18
+ gem.homepage = "http://github.com/errinlarsen/pontifex"
19
+ gem.license = "MIT"
20
+ gem.summary = %{An implementation of the Solitaire Cipher in Ruby}
21
+ gem.description = %Q{This gem is a solution to ruby quiz #1: http://www.rubyquiz.com/quiz1.html}
22
+ gem.email = "errinlarsen@gmail.com"
23
+ gem.authors = ["Errin Larsen"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:rspec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ require 'cucumber/rake/task'
40
+ Cucumber::Rake::Task.new(:cucumber) do |t|
41
+ t.cucumber_opts = "feature"
42
+ end
43
+
44
+ task :default => :spec
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "pontifex-gem #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.1
data/bin/pontifex ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
3
+ require "pontifex"
4
+
5
+ Pontifex.run
data/cucumber.yml ADDED
@@ -0,0 +1,3 @@
1
+ ##YAML Template
2
+ #---
3
+ default: -s
@@ -0,0 +1,161 @@
1
+ Feature: Pontifex (Solitaire) cipher
2
+
3
+ As a spy sending a secret message
4
+ I want to utilize a cipher
5
+ So that I can encrypt my message
6
+
7
+ Scenario: Encrypting a message with Pontifex interactively
8
+ When I run `pontifex encrypt` interactively
9
+ And I type "Code in Ruby, live longer!"
10
+ And I type "Done"
11
+ Then the output should contain:
12
+ """
13
+ Enter the message to encrypt.
14
+ enter 'Done' on a line by itself when you are done
15
+ """
16
+ And the output should contain:
17
+ """
18
+ GLNCQ MJAFF FVOMB JIYCB
19
+ """
20
+
21
+ Scenario: Decrypting a message with Pontifex interactively
22
+ When I run `pontifex decrypt` interactively
23
+ And I type "GLNCQ MJAFF FVOMB JIYCB"
24
+ And I type "Done"
25
+ Then the output should contain:
26
+ """
27
+ Enter the message to encrypt.
28
+ enter 'Done' on a line by itself when you are done
29
+ """
30
+ And the output should contain:
31
+ """
32
+ CODEI NRUBY LIVEL ONGER
33
+ """
34
+
35
+ Scenario: Encrypting a multi-line message, with more than 25 valid characters, interactively
36
+ When I run `pontifex encrypt` interactively
37
+ And I type "abcdefghijklmnopqrstuvwxyz"
38
+ And I type "abcdefghijklmnopqrstuvwxyz"
39
+ And I type "Done"
40
+ Then the output should contain:
41
+ """
42
+ EYMBM EYNMQ EYFVE KLJQD UUTWG
43
+ CPXUP AXBNV IRGUS GIRPI NBDBM
44
+ GAYAC
45
+ """
46
+
47
+ Scenario: Decrypting a multi-line message, with more than 25 valid characters, interactively
48
+ When I run `pontifex decrypt` interactively
49
+ And I type "EYMBM EYNMQ EYFVE KLJQD UUTWG"
50
+ And I type "CPXUP AXBNV IRGUS GIRPI NBDBM"
51
+ And I type "GAYAC"
52
+ And I type "Done"
53
+ Then the output should contain:
54
+ """
55
+ ABCDE FGHIJ KLMNO PQRST UVWXY
56
+ ZABCD EFGHI JKLMN OPQRS TUVWX
57
+ YZXXX
58
+ """
59
+
60
+ Scenario: Encrypting a multi-line message with an alternate key interactively
61
+ Given a file named "alternate_deck.key" with:
62
+ """
63
+ Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,
64
+ Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,ja,
65
+ Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,jb,
66
+ As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks
67
+ """
68
+ When I run `pontifex encrypt -d alternate_deck.key` interactively
69
+ And I type "abcdefghijklmnopqrstuvwxyz"
70
+ And I type "abcdefghijklmnopqrstuvwxyz"
71
+ And I type "Done"
72
+ Then the output should contain:
73
+ """
74
+ CPMJC AEFIK OOXGI VHYTU GYZYA
75
+ VRMKB EFOXV ECFPY KEOBY SXIZE
76
+ WPDFJ
77
+ """
78
+
79
+ Scenario: Decrypting a multi-line message with an alternate key interactively
80
+ Given a file named "alternate_deck.key" with:
81
+ """
82
+ Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,
83
+ Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,ja,
84
+ Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,jb,
85
+ As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks
86
+ """
87
+ When I run `pontifex decrypt -d alternate_deck.key` interactively
88
+ And I type "CPMJC AEFIK OOXGI VHYTU GYZYA"
89
+ And I type "VRMKB EFOXV ECFPY KEOBY SXIZE"
90
+ And I type "WPDFJ"
91
+ And I type "Done"
92
+ Then the output should contain:
93
+ """
94
+ ABCDE FGHIJ KLMNO PQRST UVWXY
95
+ ZABCD EFGHI JKLMN OPQRS TUVWX
96
+ YZXXX
97
+ """
98
+
99
+ Scenario: Encrypting a multi-line message with an output file interactively
100
+ When I run `pontifex encrypt -o encrypted_message.txt` interactively
101
+ And I type "abcdefghijklmnopqrstuvwxyz"
102
+ And I type "abcdefghijklmnopqrstuvwxyz"
103
+ And I type "Done"
104
+ Then the file "encrypted_message.txt" should contain exactly:
105
+ """
106
+ EYMBM EYNMQ EYFVE KLJQD UUTWG
107
+ CPXUP AXBNV IRGUS GIRPI NBDBM
108
+ GAYAC
109
+ """
110
+
111
+ Scenario: Decrypting a multi-line message with an output file interactively
112
+ When I run `pontifex decrypt -o decrypted_message.txt` interactively
113
+ And I type "EYMBM EYNMQ EYFVE KLJQD UUTWG"
114
+ And I type "CPXUP AXBNV IRGUS GIRPI NBDBM"
115
+ And I type "GAYAC"
116
+ And I type "Done"
117
+ Then the file "decrypted_message.txt" should contain exactly:
118
+ """
119
+ ABCDE FGHIJ KLMNO PQRST UVWXY
120
+ ZABCD EFGHI JKLMN OPQRS TUVWX
121
+ YZXXX
122
+ """
123
+
124
+ Scenario: Encrypting a multi-line message with an alternate key and an output file interactively
125
+ Given a file named "alternate_deck.key" with:
126
+ """
127
+ Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,
128
+ Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,ja,
129
+ Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,jb,
130
+ As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks
131
+ """
132
+ When I run `pontifex encrypt -d alternate_deck.key -o encrypted_message.txt` interactively
133
+ And I type "abcdefghijklmnopqrstuvwxyz"
134
+ And I type "abcdefghijklmnopqrstuvwxyz"
135
+ And I type "Done"
136
+ Then the file "encrypted_message.txt" should contain exactly:
137
+ """
138
+ CPMJC AEFIK OOXGI VHYTU GYZYA
139
+ VRMKB EFOXV ECFPY KEOBY SXIZE
140
+ WPDFJ
141
+ """
142
+
143
+ Scenario: Decrypting a multi-line message with an alternate key and an output file interactively
144
+ Given a file named "alternate_deck.key" with:
145
+ """
146
+ Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,
147
+ Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,ja,
148
+ Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,jb,
149
+ As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks
150
+ """
151
+ When I run `pontifex decrypt -d alternate_deck.key -o decrypted_message.txt` interactively
152
+ And I type "CPMJC AEFIK OOXGI VHYTU GYZYA"
153
+ And I type "VRMKB EFOXV ECFPY KEOBY SXIZE"
154
+ And I type "WPDFJ"
155
+ And I type "Done"
156
+ Then the file "decrypted_message.txt" should contain exactly:
157
+ """
158
+ ABCDE FGHIJ KLMNO PQRST UVWXY
159
+ ZABCD EFGHI JKLMN OPQRS TUVWX
160
+ YZXXX
161
+ """
@@ -0,0 +1,137 @@
1
+ Feature: Pontifex (Solitaire) cipher
2
+
3
+ As a spy sending a secret message
4
+ I want to utilize a cipher
5
+ So that I can encrypt my message
6
+
7
+ Scenario: Encrypting a message file with Pontifex
8
+ Given a file named "message_to_encrypt.txt" with:
9
+ """
10
+ Code in Ruby, live longer!"
11
+ """
12
+ When I run `pontifex encrypt message_to_encrypt.txt`
13
+ Then the output should contain:
14
+ """
15
+ GLNCQ MJAFF FVOMB JIYCB
16
+ """
17
+
18
+ Scenario: Decrypting a message file with Pontifex
19
+ Given a file named "message_to_decrypt.txt" with:
20
+ """
21
+ GLNCQ MJAFF FVOMB JIYCB
22
+ """
23
+ When I run `pontifex decrypt message_to_decrypt.txt`
24
+ Then the output should contain:
25
+ """
26
+ CODEI NRUBY LIVEL ONGER
27
+ """
28
+
29
+ Scenario: Encrypting a message file with an alternate deck key
30
+ Given a file named "alternate_deck.key" with:
31
+ """
32
+ Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,
33
+ Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,ja,
34
+ As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks,jb,
35
+ Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,
36
+ """
37
+ And a file named "message_to_encrypt.txt" with:
38
+ """
39
+ Code in Ruby, live longer!"
40
+ """
41
+ When I run `pontifex encrypt -d alternate_deck.key message_to_encrypt.txt`
42
+ Then the output should contain:
43
+ """
44
+ ESBMY NTMCT BVTNL NJWDN
45
+ """
46
+
47
+ Scenario: Decrypting a message file with an alternate deck key
48
+ Given a file named "alternate_deck.key" with:
49
+ """
50
+ Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,
51
+ Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,ja,
52
+ As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks,jb,
53
+ Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,
54
+ """
55
+ And a file named "message_to_decrypt.txt" with:
56
+ """
57
+ ESBMY NTMCT BVTNL NJWDN
58
+ """
59
+ When I run `pontifex decrypt -d alternate_deck.key message_to_decrypt.txt`
60
+ Then the output should contain:
61
+ """
62
+ CODEI NRUBY LIVEL ONGER
63
+ """
64
+
65
+ Scenario: Encrypting a message file with an output file
66
+ Given a file named "message_to_encrypt.txt" with:
67
+ """
68
+ Code in Ruby, live longer!"
69
+ """
70
+ When I run `pontifex encrypt -o encrypted_message.txt message_to_encrypt.txt`
71
+ Then the output should contain:
72
+ """
73
+ Message encrypted. You can find the results in the file: encrypted_message.txt
74
+ """
75
+ And the file "encrypted_message.txt" should contain exactly:
76
+ """
77
+ GLNCQ MJAFF FVOMB JIYCB
78
+ """
79
+
80
+ Scenario: Decrypting a message file with an output file
81
+ Given a file named "message_to_decrypt.txt" with:
82
+ """
83
+ GLNCQ MJAFF FVOMB JIYCB
84
+ """
85
+ When I run `pontifex decrypt -o decrypted_message.txt message_to_decrypt.txt`
86
+ Then the output should contain:
87
+ """
88
+ Message decrypted. You can find the results in the file: decrypted_message.txt
89
+ """
90
+ And the file "decrypted_message.txt" should contain exactly:
91
+ """
92
+ CODEI NRUBY LIVEL ONGER
93
+ """
94
+
95
+ Scenario: Encrypting a message file with an alternate deck key and an output file
96
+ Given a file named "alternate_deck.key" with:
97
+ """
98
+ Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,
99
+ Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,ja,
100
+ As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks,jb,
101
+ Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,
102
+ """
103
+ And a file named "message_to_encrypt.txt" with:
104
+ """
105
+ Code in Ruby, live longer!"
106
+ """
107
+ When I run `pontifex encrypt -d alternate_deck.key -o encrypted_message.txt message_to_encrypt.txt`
108
+ Then the output should contain:
109
+ """
110
+ Message encrypted. You can find the results in the file: encrypted_message.txt
111
+ """
112
+ And the file "encrypted_message.txt" should contain exactly:
113
+ """
114
+ ESBMY NTMCT BVTNL NJWDN
115
+ """
116
+
117
+ Scenario: Decrypting a message file with an alternate deck key and an output file
118
+ Given a file named "alternate_deck.key" with:
119
+ """
120
+ Ah,2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,
121
+ Ac,2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,ja,
122
+ As,2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks,jb,
123
+ Ad,2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,
124
+ """
125
+ And a file named "message_to_decrypt.txt" with:
126
+ """
127
+ ESBMY NTMCT BVTNL NJWDN
128
+ """
129
+ When I run `pontifex decrypt -d alternate_deck.key -o decrypted_message.txt message_to_decrypt.txt`
130
+ Then the output should contain:
131
+ """
132
+ Message decrypted. You can find the results in the file: decrypted_message.txt
133
+ """
134
+ And the file "decrypted_message.txt" should contain exactly:
135
+ """
136
+ CODEI NRUBY LIVEL ONGER
137
+ """
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts "Run `bundle install` to install missing gems"
7
+ exit e.status_code
8
+ end
9
+
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
11
+ require "pontifex"
12
+ require 'rspec/expectations'
13
+ require "aruba/cucumber"
14
+
15
+ ENV["PATH"] += ":" + File.dirname(__FILE__) + "/../../bin"
@@ -0,0 +1,70 @@
1
+ module Pontifex
2
+ class Card
3
+ attr_reader :str
4
+
5
+ def initialize(input_str)
6
+ @str = input_str
7
+ @value = process_input(input_str)
8
+ end
9
+
10
+ def to_i
11
+ @value
12
+ end
13
+
14
+ def to_c
15
+ return nil if str[0] == "j"
16
+ letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split('')
17
+ letters[(@value % 26) - 1]
18
+ end
19
+
20
+ def ==(other)
21
+ self.str == other.str
22
+ end
23
+
24
+
25
+ private
26
+ def process_input(str)
27
+ raise(ArgumentError, "Cards must be 2 characters long") unless str.length == 2
28
+ raise(ArgumentError, "first character of a card must be one of [2-9,j,A,T,J,Q,K]") unless str[0] =~ /[2-9,j,A,T,J,Q,K]/
29
+ raise(ArgumentError, "second character of a card must be one of [a,b,c,d,h,s]") unless str[1] =~ /[a,b,c,d,h,s]/
30
+
31
+ value = 0
32
+ case str[0]
33
+ when /[2-9]/
34
+ value += str[0].to_i
35
+ when /j/
36
+ value = 0
37
+ when /A/
38
+ value = 1
39
+ when /T/
40
+ value = 10
41
+ when /J/
42
+ value = 11
43
+ when /Q/
44
+ value = 12
45
+ when /K/
46
+ value = 13
47
+ end
48
+
49
+ case str[1]
50
+ when /[a,b]/
51
+ raise(ArgumentError, "only Jokers may have a suit of 'a' or 'b'") unless str[0] == "j"
52
+ value = 53
53
+ when /c/
54
+ raise(ArgumentError, "Jokers may not have a suit other than 'a' or 'b'") if str[0] == "j"
55
+ value += 0
56
+ when /d/
57
+ raise(ArgumentError, "Jokers may not have a suit other than 'a' or 'b'") if str[0] == "j"
58
+ value += 13
59
+ when /h/
60
+ raise(ArgumentError, "Jokers may not have a suit other than 'a' or 'b'") if str[0] == "j"
61
+ value += 26
62
+ when /s/
63
+ raise(ArgumentError, "Jokers may not have a suit other than 'a' or 'b'") if str[0] == "j"
64
+ value += 39
65
+ end
66
+
67
+ value
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,49 @@
1
+ require 'pontifex/key_stream'
2
+
3
+ module Pontifex
4
+ class Cipher
5
+ def initialize(str, deck_key=nil)
6
+ @raw = str
7
+ @keystream = deck_key.nil? ? KeyStream.new : KeyStream.new(deck_key)
8
+ end
9
+
10
+ def encrypted
11
+ @keystream.sequence!
12
+ processed = @raw.upcase.gsub(/[^A-Z]/, "")
13
+ processed << "X" * (5 - (processed.length % 5)) unless (processed.length % 5) == 0
14
+
15
+ results = ""
16
+ processed.each_char do |c|
17
+ k = @keystream.letter
18
+ value = (c.ord - 64) + (k.ord - 64)
19
+ results << ((value > 26 ? value - 26 : value) + 64).chr
20
+ @keystream.sequence!
21
+ end
22
+
23
+ output_str = ""
24
+ results.scan(/.{5}/).each_slice(5) { |s| output_str << s.join(" ") + "\n" }
25
+ output_str.chomp
26
+ end
27
+
28
+ def decrypted
29
+ @keystream.sequence!
30
+ processed = @raw.upcase.gsub(/[^A-Z]/, "")
31
+
32
+ results = ""
33
+ processed.each_char do |c|
34
+ k = @keystream.letter
35
+ if (c.ord - 64) <= (k.ord - 64)
36
+ value = (c.ord - 64 + 26) - (k.ord - 64)
37
+ else
38
+ value = (c.ord - 64) - (k.ord - 64)
39
+ end
40
+ results << (value + 64).chr
41
+ @keystream.sequence!
42
+ end
43
+
44
+ output_str = ""
45
+ results.scan(/.{5}/).each_slice(5) { |s| output_str << s.join(" ") + "\n" }
46
+ output_str.chomp
47
+ end
48
+ end
49
+ end