Gemnigma 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +14 -0
- data/.travis.yml +17 -0
- data/Gemfile +4 -0
- data/Gemnigma.gemspec +24 -0
- data/LICENSE.txt +22 -0
- data/README.md +87 -0
- data/Rakefile +8 -0
- data/bin/Gemnigma +184 -0
- data/helpers/char_map.rb +11 -0
- data/helpers/cipher_decrypt.rb +9 -0
- data/helpers/cipher_encrypt.rb +10 -0
- data/helpers/key.rb +25 -0
- data/helpers/messages.rb +44 -0
- data/helpers/offset.rb +26 -0
- data/helpers/rotator_decrypt.rb +16 -0
- data/helpers/rotator_encrypt.rb +62 -0
- data/helpers/validate_file_arg.rb +38 -0
- data/lib/Gemnigma/crack.rb +199 -0
- data/lib/Gemnigma/decrypt.rb +64 -0
- data/lib/Gemnigma/encrypt.rb +45 -0
- data/lib/Gemnigma/helpers.rb +4 -0
- data/lib/Gemnigma/version.rb +3 -0
- data/lib/Gemnigma.rb +7 -0
- data/message.txt +1 -0
- data/spec/Gemnigma_spec.rb +55 -0
- data/spec/char_map_spec.rb +38 -0
- data/spec/cipher_decrypt_spec.rb +55 -0
- data/spec/cipher_encrypt_spec.rb +43 -0
- data/spec/crack_spec.rb +170 -0
- data/spec/decrypt_spec.rb +108 -0
- data/spec/encrypt_spec.rb +61 -0
- data/spec/key_spec.rb +48 -0
- data/spec/messages_spec.rb +161 -0
- data/spec/offset_spec.rb +62 -0
- data/spec/rotator_decrypt_spec.rb +21 -0
- data/spec/rotator_encrypt_spec.rb +130 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/validate_file_arg_spec.rb +49 -0
- data/spec/version_spec.rb +11 -0
- metadata +156 -0
@@ -0,0 +1,199 @@
|
|
1
|
+
require_relative "helpers"
|
2
|
+
|
3
|
+
module Gemnigma
|
4
|
+
class Crack
|
5
|
+
include ValidateFileArg
|
6
|
+
|
7
|
+
def get_cmd_args
|
8
|
+
if ARGV.length < 4
|
9
|
+
Messages.new.few_args
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
if ARGV.length == 4
|
14
|
+
@input_file = ARGV[1]
|
15
|
+
@output_file = ARGV[2]
|
16
|
+
@date_gen = ARGV[3]
|
17
|
+
validate { brute_force_key_map(@input_file, @date_gen) }
|
18
|
+
end
|
19
|
+
|
20
|
+
if ARGV.length > 4
|
21
|
+
Messages.new.too_much_args
|
22
|
+
return
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def true_date?(date)
|
29
|
+
(date.to_i ** 2).to_s.chars.last(4).map(&:to_i) == Offset.new.offset
|
30
|
+
end
|
31
|
+
|
32
|
+
def brute_force_key_map(input, date)
|
33
|
+
unless true_date?(date)
|
34
|
+
Messages.new.wrong_date(date)
|
35
|
+
return
|
36
|
+
end
|
37
|
+
|
38
|
+
encrypted_file = File.open(input, "r")
|
39
|
+
index_count = 0
|
40
|
+
crack_key = 0
|
41
|
+
end_char_arr = []
|
42
|
+
@key_map = []
|
43
|
+
|
44
|
+
encrypted_file.read.split("").each do |item|
|
45
|
+
index_count = 0 if index_count > 3
|
46
|
+
end_char_arr << [item, index_count]
|
47
|
+
index_count += 1
|
48
|
+
end
|
49
|
+
|
50
|
+
end_chars = end_char_arr[-7..-4]
|
51
|
+
|
52
|
+
|
53
|
+
while crack_key <= 99
|
54
|
+
if CipherDecrypt.rotate_backward(crack_key)[end_chars[0][0]] == "."
|
55
|
+
@key_map[end_chars[0][1]] = crack_key
|
56
|
+
crack_key = 0
|
57
|
+
break
|
58
|
+
end
|
59
|
+
crack_key += 1
|
60
|
+
end
|
61
|
+
|
62
|
+
while crack_key <= 99
|
63
|
+
if CipherDecrypt.rotate_backward(crack_key)[end_chars[1][0]] == "."
|
64
|
+
@key_map[end_chars[1][1]] = crack_key
|
65
|
+
crack_key = 0
|
66
|
+
break
|
67
|
+
end
|
68
|
+
crack_key += 1
|
69
|
+
end
|
70
|
+
|
71
|
+
while crack_key <= 99
|
72
|
+
if CipherDecrypt.rotate_backward(crack_key)[end_chars[2][0]] == "e"
|
73
|
+
@key_map[end_chars[2][1]] = crack_key
|
74
|
+
crack_key = 0
|
75
|
+
break
|
76
|
+
end
|
77
|
+
crack_key += 1
|
78
|
+
end
|
79
|
+
|
80
|
+
while crack_key <= 99
|
81
|
+
if CipherDecrypt.rotate_backward(crack_key)[end_chars[3][0]] == "n"
|
82
|
+
@key_map[end_chars[3][1]] = crack_key
|
83
|
+
crack_key = 0
|
84
|
+
break
|
85
|
+
end
|
86
|
+
crack_key += 1
|
87
|
+
end
|
88
|
+
|
89
|
+
if @key_map.length == 4
|
90
|
+
crack_file(@input_file, @output_file)
|
91
|
+
end
|
92
|
+
|
93
|
+
encrypted_file.close
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
def map_word_to_crack(word)
|
98
|
+
result = []
|
99
|
+
count_key = 0
|
100
|
+
|
101
|
+
word.downcase.split("").each_with_index do |letter, index|
|
102
|
+
if count_key >= @key_map.length
|
103
|
+
count_key = 0
|
104
|
+
end
|
105
|
+
result << [letter, @key_map[count_key]]
|
106
|
+
count_key += 1
|
107
|
+
end
|
108
|
+
result
|
109
|
+
end
|
110
|
+
|
111
|
+
def brute_crack(word)
|
112
|
+
mapping = map_word_to_crack(word)
|
113
|
+
|
114
|
+
mapping.map! do |arr|
|
115
|
+
CipherDecrypt.rotate_backward(arr.last)[arr.first]
|
116
|
+
end
|
117
|
+
|
118
|
+
mapping.join
|
119
|
+
end
|
120
|
+
|
121
|
+
def pad_key(key)
|
122
|
+
if key.to_s.length == 1
|
123
|
+
key = "0" + key.to_s
|
124
|
+
else
|
125
|
+
key = key.to_s
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def key_gen(init, next_item)
|
130
|
+
new_arr = []
|
131
|
+
|
132
|
+
if pad_key(init)[1] != pad_key(next_item)[0]
|
133
|
+
if pad_key(init + 39)[1] == next_item.to_s[0]
|
134
|
+
new_arr << (init + 39)
|
135
|
+
new_arr << next_item
|
136
|
+
elsif pad_key(init + 78)[1] == next_item.to_s[0]
|
137
|
+
new_arr << (init + 78)
|
138
|
+
new_arr << next_item
|
139
|
+
elsif pad_key(init + 39)[1] == (next_item + 39).to_s[0]
|
140
|
+
new_arr << (init + 39)
|
141
|
+
new_arr << (next_item + 39)
|
142
|
+
elsif pad_key(init + 39)[1] == (next_item + 78).to_s[0]
|
143
|
+
new_arr << (init + 39)
|
144
|
+
new_arr << (next_item + 78)
|
145
|
+
elsif pad_key(init + 78)[1] == (next_item + 39).to_s[0]
|
146
|
+
new_arr << (init + 78)
|
147
|
+
new_arr << (next_item + 39)
|
148
|
+
elsif pad_key(init + 78)[1] == (next_item + 78).to_s[0]
|
149
|
+
new_arr << (init + 78)
|
150
|
+
new_arr << (next_item + 78)
|
151
|
+
elsif pad_key(init)[1] == (next_item + 39).to_s[0]
|
152
|
+
new_arr << init
|
153
|
+
new_arr << (next_item + 39)
|
154
|
+
elsif pad_key(init)[1] == (next_item + 78).to_s[0]
|
155
|
+
new_arr << init
|
156
|
+
new_arr << (next_item + 78)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
if pad_key(init)[1] == pad_key(next_item)[0]
|
161
|
+
new_arr << init
|
162
|
+
new_arr << next_item
|
163
|
+
end
|
164
|
+
|
165
|
+
new_arr
|
166
|
+
end
|
167
|
+
|
168
|
+
def generate_cracked_key
|
169
|
+
@cracked_key = 0
|
170
|
+
date_offset = Offset.new.offset
|
171
|
+
|
172
|
+
key_arr = @key_map.zip(date_offset).map {|arr| arr.inject(&:-)}
|
173
|
+
possible_key_combination = [key_gen(key_arr[0], key_arr[1]), key_gen(key_arr[2], key_arr[3])].flatten
|
174
|
+
|
175
|
+
possible_key_combination.map! do |number|
|
176
|
+
if number == possible_key_combination.last
|
177
|
+
number
|
178
|
+
else
|
179
|
+
number.to_s[0].to_i
|
180
|
+
end
|
181
|
+
end
|
182
|
+
@cracked_key = possible_key_combination.join
|
183
|
+
Messages.new.success_message(@output_file, @secret_key, @date_gen)
|
184
|
+
end
|
185
|
+
|
186
|
+
def crack_file(input, output)
|
187
|
+
encrypted_file = File.open(input, "r+")
|
188
|
+
cracked_file = File.open(output, "w+")
|
189
|
+
input_content = encrypted_file.read
|
190
|
+
|
191
|
+
cracked_file.write(brute_crack(input_content))
|
192
|
+
|
193
|
+
encrypted_file.close
|
194
|
+
cracked_file.close
|
195
|
+
generate_cracked_key
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require_relative "helpers"
|
2
|
+
|
3
|
+
module Gemnigma
|
4
|
+
class Decrypt < RotatorDecrypt
|
5
|
+
include ValidateFileArg
|
6
|
+
|
7
|
+
def get_cmd_args
|
8
|
+
if ARGV.length < 5
|
9
|
+
Messages.new.few_args
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
if ARGV.length == 5
|
14
|
+
@input_file = ARGV[1]
|
15
|
+
@output_file = ARGV[2]
|
16
|
+
@secret_key = ARGV[3]
|
17
|
+
@date_gen = ARGV[4]
|
18
|
+
validate { decrypt_file(@input_file, @output_file,@secret_key,@date_gen) }
|
19
|
+
end
|
20
|
+
|
21
|
+
if ARGV.length > 5
|
22
|
+
Messages.new.too_much_args
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def true_key?(key)
|
31
|
+
key.length == 5 && key.match(/\d\d\d\d\d/) ? true : false
|
32
|
+
end
|
33
|
+
|
34
|
+
def true_date?(date)
|
35
|
+
(date.to_i ** 2).to_s.chars.last(4).map(&:to_i) == Offset.new.offset
|
36
|
+
end
|
37
|
+
|
38
|
+
def decrypt_file(input, output, key, date)
|
39
|
+
unless true_key?(key)
|
40
|
+
puts "#{key} doesn't match the specified key format"
|
41
|
+
puts "Exiting..."
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
unless true_date?(date)
|
46
|
+
puts "#{date} doesn't match the specified date format"
|
47
|
+
puts "Exiting..."
|
48
|
+
return
|
49
|
+
end
|
50
|
+
|
51
|
+
encrypted_file = File.open(input, "r+")
|
52
|
+
decrypted_file = File.open(output, "w+")
|
53
|
+
input_content = encrypted_file.read
|
54
|
+
|
55
|
+
decrypt = RotatorDecrypt.new(Key.new(key.to_i))
|
56
|
+
|
57
|
+
decrypted_file.write(decrypt.rot_decrypt(input_content))
|
58
|
+
|
59
|
+
encrypted_file.close
|
60
|
+
decrypted_file.close
|
61
|
+
Messages.new.success_message(@output_file, @secret_key, @date_gen)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative "helpers"
|
2
|
+
|
3
|
+
module Gemnigma
|
4
|
+
class Encrypt < RotatorEncrypt
|
5
|
+
include ValidateFileArg
|
6
|
+
|
7
|
+
def get_cmd_args
|
8
|
+
if ARGV.length < 3
|
9
|
+
Messages.new.few_args
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
if ARGV.length == 3
|
14
|
+
@input_file = ARGV[1]
|
15
|
+
@output_file = ARGV[2]
|
16
|
+
validate { encrypt_file(@input_file, @output_file) }
|
17
|
+
end
|
18
|
+
|
19
|
+
if ARGV.length > 3
|
20
|
+
Messages.new.too_much_args
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def encrypt_file(input, output)
|
29
|
+
file_input = File.open(input, "r+")
|
30
|
+
encrypted_file = File.open(output, "w+")
|
31
|
+
decryption_key = File.open("#{output.sub('txt', 'secret')}", "w+")
|
32
|
+
input_content = file_input.read
|
33
|
+
@secret_key = rand(10000..99999)
|
34
|
+
@date_gen = Offset.new.full_date
|
35
|
+
encrypt = RotatorEncrypt.new(Key.new(@secret_key))
|
36
|
+
|
37
|
+
encrypted_file.write(encrypt.rot_encrypt(input_content))
|
38
|
+
decryption_key.write("Decrypt #{@output_file} with the key: #{@secret_key} and date: #{@date_gen}")
|
39
|
+
|
40
|
+
file_input.close
|
41
|
+
encrypted_file.close
|
42
|
+
Messages.new.success_message(@output_file, @secret_key, @date_gen)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/Gemnigma.rb
ADDED
data/message.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
This message is secured with the genigma encryption engine ..end..
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe Gemnigma do
|
4
|
+
it "should be a module" do
|
5
|
+
expect(Gemnigma.class).to eql(Module)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have a version constant available to it" do
|
9
|
+
expect(Gemnigma.constants.include? :VERSION).to be true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should have a version number 0.0.1" do
|
13
|
+
expect(Gemnigma::VERSION).to eql("0.0.1")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have access to the char_map module" do
|
17
|
+
expect(Gemnigma.constants.include? :CharMap).to be true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have access to the cipher_decrypt module" do
|
21
|
+
expect(Gemnigma.constants.include? :CipherDecrypt).to be true
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should have access to the cipher_encrypt module" do
|
25
|
+
expect(Gemnigma.constants.include? :CipherEncrypt).to be true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have access to the key class" do
|
29
|
+
expect(Gemnigma.constants.include? :Key).to be true
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have access to the offset class" do
|
33
|
+
expect(Gemnigma.constants.include? :Offset).to be true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have access to the rotator_decrypt class" do
|
37
|
+
expect(Gemnigma.constants.include? :RotatorDecrypt).to be true
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should have access to the rotator_encrypt class" do
|
41
|
+
expect(Gemnigma.constants.include? :RotatorEncrypt).to be true
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have access to the decrypt class" do
|
45
|
+
expect(Gemnigma.constants.include? :Decrypt).to be true
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should have access to the encrypt class" do
|
49
|
+
expect(Gemnigma.constants.include? :Encrypt).to be true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should have access to the crack class" do
|
53
|
+
expect(Gemnigma.constants.include? :Crack).to be true
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe Gemnigma::CharMap do
|
4
|
+
it "should be a module" do
|
5
|
+
expect(Gemnigma::CharMap.class).to eql(Module)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have a method, #generate_char_map" do
|
9
|
+
expect(Gemnigma::CharMap.methods.include? :generate_char_map).to be true
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#generate_char_map" do
|
13
|
+
it "should return an array" do
|
14
|
+
expect(Gemnigma::CharMap.generate_char_map.class).to eql(Array)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return an array of 39 characters" do
|
18
|
+
expect(Gemnigma::CharMap.generate_char_map.length).to eql(39)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return alphabets as it's first 26 characters" do
|
22
|
+
alphabets = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
|
23
|
+
"r", "s", "t", "u", "v", "w", "x", "y", "z", "0"]
|
24
|
+
expect(Gemnigma::CharMap.generate_char_map[0..26]).to eql(alphabets)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return numbers as strings as the next 10 characters" do
|
28
|
+
numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
|
29
|
+
expect(Gemnigma::CharMap.generate_char_map[26...36]).to eql(numbers)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return an empty string, a period and a comma as the last 3 characters" do
|
33
|
+
others = [" ", ".", ","]
|
34
|
+
expect(Gemnigma::CharMap.generate_char_map.last(3)).to eql(others)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe Gemnigma::CipherDecrypt do
|
4
|
+
it "should be a module" do
|
5
|
+
expect(Gemnigma::CipherDecrypt.class).to eql(Module)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have a method #rotate_backward" do
|
9
|
+
expect(Gemnigma::CipherDecrypt.methods.include? :rotate_backward).to be true
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#rotate_backward" do
|
13
|
+
context "without parameters" do
|
14
|
+
it "should raise an exception" do
|
15
|
+
expect { Gemnigma::CipherDecrypt.rotate_backward }.to raise_error(ArgumentError)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with parameters" do
|
20
|
+
it "should return a hash" do
|
21
|
+
expect(Gemnigma::CipherDecrypt.rotate_backward(3).class).to eql(Hash)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return a hash with a length of 39" do
|
25
|
+
expect(Gemnigma::CipherDecrypt.rotate_backward(3).length).to eql(39)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be a reverse of CipherEncrypt #rotate_forward method" do
|
29
|
+
expect(Gemnigma::CipherDecrypt.rotate_backward(3)).to eql(Gemnigma::CipherEncrypt.rotate_forward(3).invert)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should reverse a rotation if the rotation number match" do
|
33
|
+
word = Gemnigma::CipherEncrypt.rotate_forward(3)["a"]
|
34
|
+
expect(Gemnigma::CipherDecrypt.rotate_backward(3)[word]).to eql("a")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should reverse a rotation if the rotation number is an addition of the number and 39" do
|
38
|
+
word = Gemnigma::CipherEncrypt.rotate_forward(3)["a"]
|
39
|
+
expect(Gemnigma::CipherDecrypt.rotate_backward(3 + 39)[word]).to eql("a")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should reverse a rotation with rotation number plus a multiple of 39" do
|
43
|
+
word = Gemnigma::CipherEncrypt.rotate_forward(3)["a"]
|
44
|
+
expect(Gemnigma::CipherDecrypt.rotate_backward(3 + 78)[word]).to eql("a")
|
45
|
+
expect(Gemnigma::CipherDecrypt.rotate_backward(3 + 117)[word]).to eql("a")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should not reverse a rotation if the rotation number doesn't match" do
|
49
|
+
word = Gemnigma::CipherEncrypt.rotate_forward(3)["a"]
|
50
|
+
expect(Gemnigma::CipherDecrypt.rotate_backward(4)[word]).not_to eql("a")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe Gemnigma::CipherEncrypt do
|
4
|
+
it "should be a module" do
|
5
|
+
expect(Gemnigma::CipherEncrypt.class).to eql(Module)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have a method #rotate_forward" do
|
9
|
+
expect(Gemnigma::CipherEncrypt.methods.include? :rotate_forward).to be true
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#rotate_forward" do
|
13
|
+
context "without parameters" do
|
14
|
+
it "should raise an exception" do
|
15
|
+
expect { Gemnigma::CipherEncrypt.rotate_forward }.to raise_error(ArgumentError)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with parameters" do
|
20
|
+
it "should return a hash" do
|
21
|
+
expect(Gemnigma::CipherEncrypt.rotate_forward(3).class).to eql(Hash)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return a hash with a length of 39" do
|
25
|
+
expect(Gemnigma::CipherEncrypt.rotate_forward(3).length).to eql(39)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should rotate characters by passed in rotation number" do
|
29
|
+
expect(Gemnigma::CipherEncrypt.rotate_forward(1)["a"]).to eql("b")
|
30
|
+
expect(Gemnigma::CipherEncrypt.rotate_forward(1)[","]).to eql("a")
|
31
|
+
expect(Gemnigma::CipherEncrypt.rotate_forward(12)["a"]).to eql("m")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should not rotate characters when 0 is passed in or multiples of 39" do
|
35
|
+
expect(Gemnigma::CipherEncrypt.rotate_forward(0)["a"]).to eql("a")
|
36
|
+
expect(Gemnigma::CipherEncrypt.rotate_forward(39)["n"]).to eql("n")
|
37
|
+
expect(Gemnigma::CipherEncrypt.rotate_forward(78)["n"]).to eql("n")
|
38
|
+
expect(Gemnigma::CipherEncrypt.rotate_forward(117)["a"]).to eql("a")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/spec/crack_spec.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe Gemnigma::Crack do
|
4
|
+
before :each do
|
5
|
+
@crack = Gemnigma::Crack.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be an instance of the class Crack" do
|
9
|
+
expect(@crack).to be_an_instance_of Gemnigma::Crack
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#get_cmd_args" do
|
13
|
+
it "should take no arguments" do
|
14
|
+
expect{ @crack.get_cmd_args(2) }.to raise_error(ArgumentError)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should display an error message if few arguments are passed as command line arguments" do
|
18
|
+
|
19
|
+
io = double("io", puts: nil)
|
20
|
+
message = Gemnigma::Messages.new(io)
|
21
|
+
message.few_args
|
22
|
+
|
23
|
+
expect(io).to have_received(:puts).with("Not enough arguments passed in. Run Gemnigma --help for instructions on usage\nExiting...")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should display an error message if too many arguments are passed as command line arguments" do
|
27
|
+
|
28
|
+
io = double("io", puts: nil)
|
29
|
+
message = Gemnigma::Messages.new(io)
|
30
|
+
message.too_much_args
|
31
|
+
|
32
|
+
expect(io).to have_received(:puts).with("Too many arguments passed in. Run Gemnigma --help for instructions on usage\nExiting...")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#true_date?" do
|
37
|
+
it "should be a private method" do
|
38
|
+
expect{ @crack.true_date?(2) }.to raise_error(NoMethodError)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should take one compulsory argument" do
|
42
|
+
expect{ @crack.send(:true_date?) }.to raise_error(ArgumentError)
|
43
|
+
expect{ @crack.send(:true_date?, 123456, 90919) }.to raise_error(ArgumentError)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return true for valid dates" do
|
47
|
+
expect(@crack.send(:true_date?, 11015)).to be true
|
48
|
+
expect(@crack.send(:true_date?, 81015)).to be true
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should return false for invalid dates" do
|
52
|
+
expect(@crack.send(:true_date?, 110152)).to be false
|
53
|
+
expect(@crack.send(:true_date?, "hello")).to be false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#brute_force_key_map" do
|
58
|
+
it "should be a private method" do
|
59
|
+
expect{ @crack.brute_force_key_map }.to raise_error(NoMethodError)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should display an error message if an invalid date is passed in" do
|
63
|
+
|
64
|
+
io = double("io", puts: nil)
|
65
|
+
message = Gemnigma::Messages.new(io)
|
66
|
+
message.wrong_date("hello")
|
67
|
+
|
68
|
+
expect(io).to have_received(:puts).with("hello doesn't match the specified date format\nExiting...")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should throw an error if file to be read from doesn't exist" do
|
72
|
+
expect{ @crack.send(:brute_force_key_map, "unexistent.txt", 11015) }.to raise_error(StandardError)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#pad_key" do
|
78
|
+
it "should be a private method" do
|
79
|
+
expect{ @crack.pad_key(2) }.to raise_error(NoMethodError)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should take one compulsory argument" do
|
83
|
+
expect{ @crack.send(:pad_key) }.to raise_error(ArgumentError)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return a padded key if the length is one" do
|
87
|
+
expect(@crack.send(:pad_key, 0)).to eql("00")
|
88
|
+
expect(@crack.send(:pad_key, 1)).to eql("01")
|
89
|
+
expect(@crack.send(:pad_key, 2)).to eql("02")
|
90
|
+
expect(@crack.send(:pad_key, 3)).to eql("03")
|
91
|
+
expect(@crack.send(:pad_key, 4)).to eql("04")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should return a non-padded key if the length is greater than one" do
|
95
|
+
expect(@crack.send(:pad_key, 10)).to eql("10")
|
96
|
+
expect(@crack.send(:pad_key, 121)).to eql("121")
|
97
|
+
expect(@crack.send(:pad_key, 1234)).to eql("1234")
|
98
|
+
expect(@crack.send(:pad_key, 12345)).to eql("12345")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#key_gen" do
|
103
|
+
it "should be a private method" do
|
104
|
+
expect{ @crack.key_gen(2, 6) }.to raise_error(NoMethodError)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should return an array" do
|
108
|
+
expect(@crack.send(:key_gen, 2, 6).class).to eql(Array)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should return an array of generated keys" do
|
112
|
+
expect(@crack.send(:key_gen, 4, 34)).to eql([43, 34])
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should return an empty array if key could not be generated" do
|
116
|
+
expect(@crack.send(:key_gen, 2, 6)).to eql([])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "#generate_cracked_key" do
|
121
|
+
it "should be a private method" do
|
122
|
+
expect{ @crack.generate_cracked_key }.to raise_error(NoMethodError)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should display a success message if file was successfully created" do
|
126
|
+
io = double("io", puts: nil)
|
127
|
+
message = Gemnigma::Messages.new(io)
|
128
|
+
message.success_message("file.txt", "94704", "81015")
|
129
|
+
|
130
|
+
expect(io).to have_received(:puts).with("\n........................................................")
|
131
|
+
expect(io).to have_received(:puts).with("\nCreated 'file.txt' with secret key 94704 and date 81015")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "#map_word_to_crack" do
|
136
|
+
it "should be a private method" do
|
137
|
+
expect{ @crack.map_word_to_crack }.to raise_error(NoMethodError)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should take one compulsory argument" do
|
141
|
+
expect{ @crack.send(:map_word_to_crack) }.to raise_error(ArgumentError)
|
142
|
+
expect{ @crack.send(:map_word_to_crack, "hello", "ade") }.to raise_error(ArgumentError)
|
143
|
+
expect{ @crack.send(:map_word_to_crack, "hello", "ade", "one") }.to raise_error(ArgumentError)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "#brute_crack" do
|
148
|
+
it "should be a private method" do
|
149
|
+
expect{ @crack.brute_crack }.to raise_error(NoMethodError)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should take one compulsory argument" do
|
153
|
+
expect{ @crack.send(:brute_crack) }.to raise_error(ArgumentError)
|
154
|
+
expect{ @crack.send(:brute_crack, 2, 3) }.to raise_error(ArgumentError)
|
155
|
+
expect{ @crack.send(:brute_crack, 2, 3, "ade") }.to raise_error(ArgumentError)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "#crack_file" do
|
160
|
+
it "should be a private method" do
|
161
|
+
expect{ @crack.crack_file("encoded.txt", "cracked.txt") }.to raise_error(NoMethodError)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should take two compulsory arguments" do
|
165
|
+
expect{ @crack.send(:crack_file) }.to raise_error(ArgumentError)
|
166
|
+
expect{ @crack.send(:crack_file, "file.txt") }.to raise_error(ArgumentError)
|
167
|
+
expect{ @crack.send(:crack_file, "file.txt", "out.txt", "last.txt") }.to raise_error(ArgumentError)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|