sub_cipher 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/HISTORY.md +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +112 -0
- data/lib/sub_cipher.rb +161 -0
- data/lib/sub_cipher/sub_cipher_error.rb +46 -0
- data/lib/sub_cipher/version.rb +3 -0
- data/sub_cipher.gemspec +22 -0
- data/test/test_all.rb +97 -0
- data/test/test_helper.rb +1 -0
- metadata +71 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: efc3e2913656d45254d35d24732ffe43218d23e8
|
4
|
+
data.tar.gz: 0425ba813eb72cf118b906863b7ee445564c3c5d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2ed311f95e325bd5c6253c16370e4d4a8bcd7d99fd6accb6412b052a2095973542fe88e5ec04d1ac8cdc8790deb531f930c173c8f7b9332d2f01490109d154af
|
7
|
+
data.tar.gz: f626cd93638eb663944c9b48ddb0ac7f10fcc2fe43be608bdf51326d78047d45f676cf8d22477925cbc80bf93019d659fd1b2716188c60c78497f1a8a9397353
|
data/.gitignore
ADDED
data/HISTORY.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Sibevin Wang
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# Sub(stitution) Cipher
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/sub_cipher.png)][gem]
|
4
|
+
[![Build Status](https://travis-ci.org/sibevin/sub_cipher.png?branch=build)][travis]
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/sibevin/sub_cipher/badge.png?branch=cover-check)][coveralls]
|
6
|
+
|
7
|
+
[gem]: https://rubygems.org/gems/sub_cipher
|
8
|
+
[travis]: https://travis-ci.org/sibevin/sub_cipher
|
9
|
+
[coveralls]:https://coveralls.io/r/sibevin/sub_cipher?branch=cover-check
|
10
|
+
|
11
|
+
Encode/Decode text with the substitution cipher
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
$ gem install sub_cipher
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
Use default seeds(alphabets) to generate the mapping, note that the letters with different cases would be mapped to the same letter, for example: if "a" is mapped to "b", then "A" is mapped to "B".
|
20
|
+
|
21
|
+
sc = SubCipher.gen
|
22
|
+
sc.encode("Here is a secret.")
|
23
|
+
# "Wyky gn q nyakyr."
|
24
|
+
sc.decode("Wyky gn q nyakyr.")
|
25
|
+
# "Here is a secret."
|
26
|
+
sc.seed
|
27
|
+
# "abcdefghijklmnopqrstuvwxyz"
|
28
|
+
sc.map
|
29
|
+
# "qeahyftwgpjixodzbknrlscvum"
|
30
|
+
|
31
|
+
The `seed` and `map` method shows how to map the cipher, the above example means mapping `"abcdefghijklmnopqrstuvwxyz"` to `"qeahyftwgpjixodzbknrlscvum"`
|
32
|
+
|
33
|
+
## Options
|
34
|
+
|
35
|
+
### Seed
|
36
|
+
|
37
|
+
Use `:s` (or `:seed`) to map the given seeds only
|
38
|
+
|
39
|
+
sc = SubCipher.gen(seed: "abcde")
|
40
|
+
sc.encode("Here is a secret.")
|
41
|
+
# "Hcrc is e scbrct."
|
42
|
+
sc.decode("Hcrc is e scbrct.")
|
43
|
+
# "Here is a secret."
|
44
|
+
sc.seed
|
45
|
+
# "abcde"
|
46
|
+
sc.map
|
47
|
+
# "edbac"
|
48
|
+
|
49
|
+
### Map
|
50
|
+
|
51
|
+
Use `:m` (or `:map`) option to initalize cipher with a map. Note that the `:seed` option would be skipped if both `:seed` and `:map` options are given.
|
52
|
+
|
53
|
+
sc = SubCipher.gen(seed: "bdeac")
|
54
|
+
sc.encode("Here is a secret.")
|
55
|
+
# "Hara is b saerat."
|
56
|
+
sc.decode("Hara is b saerat.")
|
57
|
+
# "Here is a secret."
|
58
|
+
sc.seed
|
59
|
+
# "abcde"
|
60
|
+
sc.map
|
61
|
+
# "bdeca"
|
62
|
+
|
63
|
+
### Keep Case
|
64
|
+
|
65
|
+
If you want to map letters with different cases to different letters, use `k: false` (or `keep_case: false`) option.
|
66
|
+
|
67
|
+
sc = SubCipher.gen(keep_case: false)
|
68
|
+
sc.encode("Here is a secret.")
|
69
|
+
# "alXl wE s EleXlk."
|
70
|
+
sc.decode("alXl wE s EleXlk.")
|
71
|
+
# "Here is a secret."
|
72
|
+
sc.seed
|
73
|
+
# "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
74
|
+
sc.map
|
75
|
+
# "PNAgWKOaxtCUdqHpIuJRhjTMnDsbeQlFiGwrzLfBvVYXEkZcoSmy"
|
76
|
+
|
77
|
+
If there is a seed(assigned by `seed` or `map` option) which is not an alphabet, `keep_case: false` would be applied.
|
78
|
+
|
79
|
+
sc = SubCipher.gen(seed: "abcdeABCDE ,.")
|
80
|
+
sc.encode("Here is a secret.")
|
81
|
+
# "HdrdAisA,AsdBrdtE"
|
82
|
+
sc.decode("HdrdAisA,AsdBrdtE")
|
83
|
+
# "Here is a secret."
|
84
|
+
sc.seed
|
85
|
+
# " ,.ABCDEabcde"
|
86
|
+
sc.map
|
87
|
+
# "AaE ebCc,DB.d"
|
88
|
+
|
89
|
+
## Test
|
90
|
+
|
91
|
+
Go to gem folder and run
|
92
|
+
|
93
|
+
ruby ./test/test_all.rb
|
94
|
+
|
95
|
+
(Note that you need minitest ~> 5.0 to run these tests)
|
96
|
+
|
97
|
+
# Contributing
|
98
|
+
|
99
|
+
1. Fork it ( https://github.com/sibevin/sub_cipher/fork )
|
100
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
101
|
+
3. Write tests for your code
|
102
|
+
4. Commit your changes (both code and tests) (`git commit -am 'Add some feature'`)
|
103
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
104
|
+
6. Create a new Pull Request
|
105
|
+
|
106
|
+
## Authors
|
107
|
+
|
108
|
+
Sibevin Wang
|
109
|
+
|
110
|
+
## Copyright
|
111
|
+
|
112
|
+
Copyright (c) 2014 Sibevin Wang. Released under the MIT license.
|
data/lib/sub_cipher.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
require "sub_cipher/sub_cipher_error"
|
2
|
+
|
3
|
+
module SubCipher
|
4
|
+
# The alphabet seed
|
5
|
+
ALPHABETS = ('a'..'z')
|
6
|
+
|
7
|
+
# The supported options
|
8
|
+
SUPPORTED_OPTS = {
|
9
|
+
:seed => {
|
10
|
+
:abbr => :s,
|
11
|
+
:type => String
|
12
|
+
},
|
13
|
+
:map => {
|
14
|
+
:abbr => :m,
|
15
|
+
:type => String
|
16
|
+
},
|
17
|
+
:keep_case => {
|
18
|
+
:abbr => :k
|
19
|
+
},
|
20
|
+
}
|
21
|
+
|
22
|
+
# The default options
|
23
|
+
DEFAULT_OPTS = {
|
24
|
+
:seed => [ALPHABETS.to_a, ALPHABETS.to_a.map{ |a| a.upcase }].flatten.join,
|
25
|
+
:keep_case => true
|
26
|
+
}
|
27
|
+
|
28
|
+
# The major method to generate a sub cipher.
|
29
|
+
# @param options [Hash]
|
30
|
+
# The options to tell sub cipher how to encode/decode.
|
31
|
+
# Three options :seed, :map and :keep_case are supported.
|
32
|
+
# Please see {file:README} to get more examples
|
33
|
+
# @return [SubCipherObject]
|
34
|
+
# The generated sub cipher.
|
35
|
+
# @raise [SubCipherError]
|
36
|
+
# Please see {SubCipher::SubCipherError}
|
37
|
+
def SubCipher.gen(options = {})
|
38
|
+
SubCipherObject.new(options)
|
39
|
+
end
|
40
|
+
|
41
|
+
# The sub cipher class.
|
42
|
+
class SubCipherObject
|
43
|
+
# The sub cipher contructor.
|
44
|
+
# @param options (see SubCipher.gen)
|
45
|
+
# @return (see SubCipher.gen)
|
46
|
+
# @raise (see SubCipher.gen)
|
47
|
+
def initialize(options)
|
48
|
+
opts = check_opt(options)
|
49
|
+
opts.each do |key, value|
|
50
|
+
if (!SUPPORTED_OPTS.key?(key) && !SUPPORTED_OPTS.values.map {|v| v[:abbr]}.include?(key))
|
51
|
+
raise SubCipherError.new(:unknown_option, key)
|
52
|
+
end
|
53
|
+
case key
|
54
|
+
when :seed
|
55
|
+
@map = value.chars.to_a.uniq.shuffle
|
56
|
+
when :map
|
57
|
+
@map = value.chars.to_a.uniq
|
58
|
+
when :keep_case
|
59
|
+
@keep_case = (value ? true : false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
support_keep_case = true
|
63
|
+
@map.each do |m|
|
64
|
+
if !ALPHABETS.include?(m.downcase)
|
65
|
+
support_keep_case = false
|
66
|
+
break
|
67
|
+
end
|
68
|
+
end
|
69
|
+
@keep_case = (support_keep_case && @keep_case ? true : false)
|
70
|
+
if @keep_case
|
71
|
+
@map = @map.map{ |m| m.downcase }.uniq
|
72
|
+
end
|
73
|
+
seed = @map.sort
|
74
|
+
@mapping = {}
|
75
|
+
seed.each_with_index do |s, index|
|
76
|
+
@mapping[s] = @map[index]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Encode the given string.
|
81
|
+
# @param str [String]
|
82
|
+
# The original string to encode.
|
83
|
+
# @return [String]
|
84
|
+
# The encoded result.
|
85
|
+
def encode(str)
|
86
|
+
str.chars.map { |c| convert(c) }.join
|
87
|
+
end
|
88
|
+
|
89
|
+
# Decode the given string.
|
90
|
+
# @param str [String]
|
91
|
+
# The encoded string to decode.
|
92
|
+
# @return [String]
|
93
|
+
# The decoded result.
|
94
|
+
def decode(str)
|
95
|
+
str.chars.map { |c| convert(c, true) }.join
|
96
|
+
end
|
97
|
+
|
98
|
+
# Show the map string, for mapping display.
|
99
|
+
# For example, if the seed string is "abc" and map string is "cab",
|
100
|
+
# then the mapping is "a" => "c", "b" => "a", "c" => "b".
|
101
|
+
# @return [String]
|
102
|
+
# The map string.
|
103
|
+
def map
|
104
|
+
@map.join
|
105
|
+
end
|
106
|
+
|
107
|
+
# Show the seed string, for mapping display.
|
108
|
+
# For example, if the seed string is "abc" and map string is "cab",
|
109
|
+
# then the mapping is "a" => "c", "b" => "a", "c" => "b".
|
110
|
+
# @return [String]
|
111
|
+
# The seed string.
|
112
|
+
def seed
|
113
|
+
@map.sort.join
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
# Covert single char with the mapping.
|
119
|
+
def convert(char, reverse = false)
|
120
|
+
if @keep_case
|
121
|
+
if reverse
|
122
|
+
if @mapping.value?(char)
|
123
|
+
return @mapping.index(char)
|
124
|
+
elsif @mapping.value?(char.downcase)
|
125
|
+
return @mapping.index(char.downcase).upcase
|
126
|
+
else
|
127
|
+
return char
|
128
|
+
end
|
129
|
+
else
|
130
|
+
if @mapping.key?(char)
|
131
|
+
return @mapping[char]
|
132
|
+
elsif @mapping.key?(char.downcase)
|
133
|
+
return @mapping[char.downcase].upcase
|
134
|
+
else
|
135
|
+
return char
|
136
|
+
end
|
137
|
+
end
|
138
|
+
else
|
139
|
+
if reverse
|
140
|
+
@mapping.value?(char) ? @mapping.index(char) : char
|
141
|
+
else
|
142
|
+
@mapping.key?(char) ? @mapping[char] : char
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Check the given options.
|
148
|
+
def check_opt(opts)
|
149
|
+
SUPPORTED_OPTS.each do |key, value|
|
150
|
+
if (opts[key] != nil) && opts.keys.include?(value[:abbr])
|
151
|
+
raise SubCipherError.new(:duplicated_option, opts)
|
152
|
+
end
|
153
|
+
opts.merge!(key => opts[value[:abbr]]) if opts[value[:abbr]] != nil
|
154
|
+
if (opts[key] != nil) && (value[:type] != nil) && !(opts[key]).is_a?(value[:type])
|
155
|
+
raise SubCipherError.new(:invalid_option_value, opts)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
DEFAULT_OPTS.merge(opts)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module SubCipher
|
2
|
+
|
3
|
+
# A customized exception for SubCipher
|
4
|
+
class SubCipherError < StandardError
|
5
|
+
|
6
|
+
# Errors used in SubCipher
|
7
|
+
ERRORS = {
|
8
|
+
:unknown_option => {
|
9
|
+
:value => 1,
|
10
|
+
:msg => "Unknown option"
|
11
|
+
},
|
12
|
+
:duplicated_option => {
|
13
|
+
:value => 2,
|
14
|
+
:msg => "The same options are given."
|
15
|
+
},
|
16
|
+
:invalid_option_value => {
|
17
|
+
:value => 3,
|
18
|
+
:msg => "The given option value is invalid."
|
19
|
+
},
|
20
|
+
}
|
21
|
+
|
22
|
+
attr_reader :code, :value, :msg, :info
|
23
|
+
|
24
|
+
# The SubCipherError constructor.
|
25
|
+
# @param error [Fixnum, String]
|
26
|
+
# You can give a error number defined in the keys of {SubCipher::SubCipherError::ERRORS} or a string message for internal usage.
|
27
|
+
# @param info [Hash]
|
28
|
+
# Anything you want to put in the info attribute of SubCipherError.
|
29
|
+
def initialize(error, info = {})
|
30
|
+
@code = error
|
31
|
+
@info = info
|
32
|
+
if ERRORS.keys.include?(error)
|
33
|
+
@value = ERRORS[error][:value]
|
34
|
+
@msg = ERRORS[error][:msg]
|
35
|
+
elsif error.class.name == 'String'
|
36
|
+
@code = :internal
|
37
|
+
@value = 90000
|
38
|
+
@msg = error
|
39
|
+
else
|
40
|
+
@code = :internal
|
41
|
+
@value = 99999
|
42
|
+
@msg = "Internal Error"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/sub_cipher.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sub_cipher/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sub_cipher"
|
8
|
+
spec.version = SubCipher::VERSION
|
9
|
+
spec.authors = ["Sibevin Wang"]
|
10
|
+
spec.email = ["sibevin@gmail.com"]
|
11
|
+
spec.summary = %q{Encode/Decode text with substitution cipher}
|
12
|
+
spec.description = %q{Encode/Decode text with substitution cipher, please see "README" to get more details.}
|
13
|
+
spec.homepage = "https://github.com/sibevin/sub_cipher"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
22
|
+
end
|
data/test/test_all.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}")
|
4
|
+
require "test_helper"
|
5
|
+
require "sub_cipher"
|
6
|
+
|
7
|
+
class TestByte < Minitest::Test
|
8
|
+
def test_should_encode_and_decode_with_default_seed
|
9
|
+
sc = SubCipher.gen()
|
10
|
+
target_str = 'In cryptography, a substitution cipher is a method of encoding by which units of plaintext are replaced with ciphertext, according to a regular system; the "units" may be single letters (the most common), pairs of letters, triplets of letters, mixtures of the above, and so forth. The receiver deciphers the text by performing an inverse substitution.'
|
11
|
+
encoded_str = sc.encode(target_str)
|
12
|
+
decoded_str = sc.decode(encoded_str)
|
13
|
+
assert_equal(decoded_str, target_str)
|
14
|
+
assert_equal(sc.seed, ('a'..'z').to_a.join)
|
15
|
+
assert_match(/^[a-z]*$/, sc.map)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_encode_and_decode_with_keep_case_false
|
19
|
+
sc = SubCipher.gen(:keep_case => false)
|
20
|
+
target_str = 'In cryptography, a substitution cipher is a method of encoding by which units of plaintext are replaced with ciphertext, according to a regular system; the "units" may be single letters (the most common), pairs of letters, triplets of letters, mixtures of the above, and so forth. The receiver deciphers the text by performing an inverse substitution.'
|
21
|
+
encoded_str = sc.encode(target_str)
|
22
|
+
decoded_str = sc.decode(encoded_str)
|
23
|
+
assert_equal(decoded_str, target_str)
|
24
|
+
assert_equal(sc.seed, [('a'..'z').to_a, ('a'..'z').to_a.map{ |a| a.upcase }].flatten.sort.join)
|
25
|
+
assert_match(/^[a-zA-Z]*$/, sc.map)
|
26
|
+
|
27
|
+
sc = SubCipher.gen(:k => false)
|
28
|
+
target_str = 'In cryptography, a substitution cipher is a method of encoding by which units of plaintext are replaced with ciphertext, according to a regular system; the "units" may be single letters (the most common), pairs of letters, triplets of letters, mixtures of the above, and so forth. The receiver deciphers the text by performing an inverse substitution.'
|
29
|
+
encoded_str = sc.encode(target_str)
|
30
|
+
decoded_str = sc.decode(encoded_str)
|
31
|
+
assert_equal(decoded_str, target_str)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_should_encode_the_given_seed_only
|
35
|
+
seed = "abc"
|
36
|
+
sc = SubCipher.gen(:seed => seed)
|
37
|
+
target_str = "aaabbbcccdddeee"
|
38
|
+
encoded_str = sc.encode(target_str)
|
39
|
+
assert_match(/^[abc]{9}dddeee$/, encoded_str)
|
40
|
+
assert_equal(sc.seed, seed.chars.sort.join)
|
41
|
+
assert_match(/^[abc]*$/, sc.map)
|
42
|
+
|
43
|
+
sc = SubCipher.gen(:s => seed)
|
44
|
+
target_str = "aaabbbcccdddeee"
|
45
|
+
encoded_str = sc.encode(target_str)
|
46
|
+
assert_match(/^[abc]{9}dddeee$/, encoded_str)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_should_encode_with_the_given_map
|
50
|
+
map = "bca"
|
51
|
+
sc = SubCipher.gen(:map => map)
|
52
|
+
target_str = "aaabbbcccdddeee"
|
53
|
+
encoded_str = sc.encode(target_str)
|
54
|
+
assert(encoded_str == "bbbcccaaadddeee")
|
55
|
+
assert_equal(sc.seed, map.chars.to_a.uniq.sort.join)
|
56
|
+
assert_match(/^[abc]*$/, sc.map)
|
57
|
+
|
58
|
+
sc = SubCipher.gen(:m => map)
|
59
|
+
target_str = "aaabbbcccdddeee"
|
60
|
+
encoded_str = sc.encode(target_str)
|
61
|
+
assert(encoded_str == "bbbcccaaadddeee")
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_should_keep_the_case_by_default
|
65
|
+
map = "bca"
|
66
|
+
sc = SubCipher.gen(:map => map)
|
67
|
+
target_str = "AAAbbbcccdddeee"
|
68
|
+
encoded_str = sc.encode(target_str)
|
69
|
+
assert(encoded_str == "BBBcccaaadddeee")
|
70
|
+
assert_equal(sc.seed, map.chars.to_a.uniq.sort.join)
|
71
|
+
assert_match(/^[abc]*$/, sc.map)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_should_mix_cases_if_keep_case_false
|
75
|
+
seed = "abcABC"
|
76
|
+
sc = SubCipher.gen(:seed => seed, :keep_case => false)
|
77
|
+
target_str = "aaabbbcccdddeee"
|
78
|
+
encoded_str = sc.encode(target_str)
|
79
|
+
assert_match(/^[abcABC]{9}dddeee$/, encoded_str)
|
80
|
+
assert_equal(sc.seed, seed.chars.sort.join)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_should_raise_unknown_option_exception
|
84
|
+
e = assert_raises(SubCipher::SubCipherError) { SubCipher.gen(:unknown_option => "unknown_option") }
|
85
|
+
assert(e.code == :unknown_option)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_should_raise_duplicated_option_exception
|
89
|
+
e = assert_raises(SubCipher::SubCipherError) { SubCipher.gen(:map => "abc", :m => "def") }
|
90
|
+
assert(e.code == :duplicated_option)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_should_raise_invalid_option_value_exception
|
94
|
+
e = assert_raises(SubCipher::SubCipherError) { SubCipher.gen(:map => ["a","b","c"]) }
|
95
|
+
assert(e.code == :invalid_option_value)
|
96
|
+
end
|
97
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sub_cipher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sibevin Wang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
description: Encode/Decode text with substitution cipher, please see "README" to get
|
28
|
+
more details.
|
29
|
+
email:
|
30
|
+
- sibevin@gmail.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".gitignore"
|
36
|
+
- HISTORY.md
|
37
|
+
- LICENSE.txt
|
38
|
+
- README.md
|
39
|
+
- lib/sub_cipher.rb
|
40
|
+
- lib/sub_cipher/sub_cipher_error.rb
|
41
|
+
- lib/sub_cipher/version.rb
|
42
|
+
- sub_cipher.gemspec
|
43
|
+
- test/test_all.rb
|
44
|
+
- test/test_helper.rb
|
45
|
+
homepage: https://github.com/sibevin/sub_cipher
|
46
|
+
licenses:
|
47
|
+
- MIT
|
48
|
+
metadata: {}
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
requirements: []
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 2.2.2
|
66
|
+
signing_key:
|
67
|
+
specification_version: 4
|
68
|
+
summary: Encode/Decode text with substitution cipher
|
69
|
+
test_files:
|
70
|
+
- test/test_all.rb
|
71
|
+
- test/test_helper.rb
|