pontifex 1.0.1

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.
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