pontifex 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +1 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +50 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +53 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/bin/pontifex +5 -0
- data/cucumber.yml +3 -0
- data/feature/pontifex_interactive.feature +161 -0
- data/feature/pontifex_with_files.feature +137 -0
- data/feature/support/env.rb +15 -0
- data/lib/pontifex/card.rb +70 -0
- data/lib/pontifex/cipher.rb +49 -0
- data/lib/pontifex/key_stream.rb +79 -0
- data/lib/pontifex.rb +114 -0
- data/pontifex.gemspec +99 -0
- data/spec/pontifex/card_spec.rb +84 -0
- data/spec/pontifex/cipher_spec.rb +23 -0
- data/spec/pontifex/key_stream_spec.rb +92 -0
- data/spec/pontifex/pontifex_spec.rb +4 -0
- data/spec/spec_helper.rb +12 -0
- data/vendor/cache/aruba-0.3.6.gem +0 -0
- data/vendor/cache/builder-3.0.0.gem +0 -0
- data/vendor/cache/childprocess-0.1.9.gem +0 -0
- data/vendor/cache/cucumber-0.10.3.gem +0 -0
- data/vendor/cache/diff-lcs-1.1.2.gem +0 -0
- data/vendor/cache/ffi-1.0.9.gem +0 -0
- data/vendor/cache/gherkin-2.3.9.gem +0 -0
- data/vendor/cache/git-1.2.5.gem +0 -0
- data/vendor/cache/jeweler-1.6.0.gem +0 -0
- data/vendor/cache/json-1.5.1.gem +0 -0
- data/vendor/cache/rake-0.9.0.gem +0 -0
- data/vendor/cache/rcov-0.9.9.gem +0 -0
- data/vendor/cache/rspec-2.6.0.gem +0 -0
- data/vendor/cache/rspec-core-2.6.3.gem +0 -0
- data/vendor/cache/rspec-expectations-2.6.0.gem +0 -0
- data/vendor/cache/rspec-mocks-2.6.0.gem +0 -0
- data/vendor/cache/term-ansicolor-1.0.5.gem +0 -0
- data/vendor/cache/trollop-1.16.2.gem +0 -0
- 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
data/cucumber.yml
ADDED
@@ -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
|