ctf-party 1.0.0
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.
- checksums.yaml +7 -0
- data/.rubocop.yml +29 -0
- data/.yardopts +4 -0
- data/.yardopts-dev +6 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +52 -0
- data/LICENSE.txt +21 -0
- data/README.md +57 -0
- data/Rakefile +11 -0
- data/bin/ctf_party_console +7 -0
- data/bin/ctf_party_setup +6 -0
- data/docs/.nojekyll +0 -0
- data/docs/About.md +5 -0
- data/docs/CHANGELOG.md +5 -0
- data/docs/README.md +52 -0
- data/docs/_coverpage.md +10 -0
- data/docs/_media/logo.png +0 -0
- data/docs/_navbar.md +3 -0
- data/docs/_sidebar.md +13 -0
- data/docs/index.html +31 -0
- data/docs/pages/documentation.md +30 -0
- data/docs/pages/install.md +84 -0
- data/docs/pages/publishing.md +39 -0
- data/docs/pages/quick-start.md +23 -0
- data/docs/pages/usage.md +61 -0
- data/docs/vendor/docsify.js +1 -0
- data/docs/vendor/plugins/emoji.min.js +1 -0
- data/docs/vendor/plugins/search.min.js +1 -0
- data/docs/vendor/prismjs/components/prism-ruby.min.js +1 -0
- data/docs/vendor/themes/vue.css +1 -0
- data/docs/yard/String.html +2909 -0
- data/docs/yard/Version.html +121 -0
- data/docs/yard/_index.html +123 -0
- data/docs/yard/class_list.html +51 -0
- data/docs/yard/css/common.css +1 -0
- data/docs/yard/css/full_list.css +58 -0
- data/docs/yard/css/style.css +496 -0
- data/docs/yard/file.LICENSE.html +70 -0
- data/docs/yard/file.README.html +124 -0
- data/docs/yard/file_list.html +61 -0
- data/docs/yard/frames.html +17 -0
- data/docs/yard/index.html +124 -0
- data/docs/yard/js/app.js +303 -0
- data/docs/yard/js/full_list.js +216 -0
- data/docs/yard/js/jquery.js +4 -0
- data/docs/yard/method_list.html +275 -0
- data/docs/yard/top-level-namespace.html +112 -0
- data/lib/ctf_party.rb +7 -0
- data/lib/ctf_party/base64.rb +99 -0
- data/lib/ctf_party/digest.rb +115 -0
- data/lib/ctf_party/flag.rb +94 -0
- data/lib/ctf_party/rot.rb +47 -0
- data/lib/ctf_party/version.rb +5 -0
- data/test/test_string.rb +134 -0
- metadata +218 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— Documentation by YARD 0.9.20
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
pathId = "";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="class_list.html?1"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
|
41
|
+
|
42
|
+
<span class="title">Top Level Namespace</span>
|
43
|
+
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div id="search">
|
47
|
+
|
48
|
+
<a class="full_list_link" id="class_list_link"
|
49
|
+
href="class_list.html">
|
50
|
+
|
51
|
+
<svg width="24" height="24">
|
52
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
54
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
55
|
+
</svg>
|
56
|
+
</a>
|
57
|
+
|
58
|
+
</div>
|
59
|
+
<div class="clear"></div>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div id="content"><h1>Top Level Namespace
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
</h1>
|
67
|
+
<div class="box_info">
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
</div>
|
80
|
+
|
81
|
+
<h2>Defined Under Namespace</h2>
|
82
|
+
<p class="children">
|
83
|
+
|
84
|
+
|
85
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Version.html" title="Version (module)">Version</a></span>
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
<strong class="classes">Classes:</strong> <span class='object_link'><a href="String.html" title="String (class)">String</a></span>
|
90
|
+
|
91
|
+
|
92
|
+
</p>
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
</div>
|
103
|
+
|
104
|
+
<div id="footer">
|
105
|
+
Generated on Wed Nov 20 19:33:26 2019 by
|
106
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
107
|
+
0.9.20 (ruby-2.6.2).
|
108
|
+
</div>
|
109
|
+
|
110
|
+
</div>
|
111
|
+
</body>
|
112
|
+
</html>
|
data/lib/ctf_party.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Ruby standard library
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
class String
|
7
|
+
# Encode the string into base64
|
8
|
+
# @param opts [Hash] optional parameters
|
9
|
+
# @option opts [Symbol] :mode Default value: +:strict+.
|
10
|
+
# Other values are +:strict+ (+:rfc4648+) or +:urlsafe+.
|
11
|
+
# @see https://ruby-doc.org/stdlib-2.6.5/libdoc/base64/rdoc/Base64.html
|
12
|
+
# @return [String] the Base64 encoded string
|
13
|
+
# @example
|
14
|
+
# 'Super lib!'.to_b64 # => "U3VwZXIgbGliIQ=="
|
15
|
+
def to_b64(opts = {})
|
16
|
+
opts[:mode] ||= :strict
|
17
|
+
return Base64.strict_encode64(self) if opts[:mode] == :strict ||
|
18
|
+
opts[:mode] == :rfc4648
|
19
|
+
return Base64.encode64(self) if opts[:mode] == :rfc2045
|
20
|
+
return Base64.urlsafe_encode64(self) if opts[:mode] == :urlsafe
|
21
|
+
end
|
22
|
+
|
23
|
+
# Encode the string into base64 in place as described for {String#to_b64}.
|
24
|
+
# @return [nil]
|
25
|
+
# @example
|
26
|
+
# myStr = 'Ruby' # => "Ruby"
|
27
|
+
# myStr.to_b64! # => nil
|
28
|
+
# myStr # => "UnVieQ=="
|
29
|
+
def to_b64!(opts = {})
|
30
|
+
opts[:mode] ||= :strict
|
31
|
+
replace(to_b64) if opts[:mode] == :strict ||
|
32
|
+
opts[:mode] == :rfc4648
|
33
|
+
replace(to_b64(mode: :rfc2045)) if opts[:mode] == :rfc2045
|
34
|
+
replace(to_b64(mode: :urlsafe)) if opts[:mode] == :urlsafe
|
35
|
+
end
|
36
|
+
|
37
|
+
# Decode the string from base64
|
38
|
+
# @param opts [Hash] optional parameters
|
39
|
+
# @option opts [Symbol] :mode Default value: +:strict+.
|
40
|
+
# Other values are +:strict+ (+:rfc4648+) or +:urlsafe+.
|
41
|
+
# @see https://ruby-doc.org/stdlib-2.6.5/libdoc/base64/rdoc/Base64.html
|
42
|
+
# @return [String] the Base64 decoded string
|
43
|
+
# @example
|
44
|
+
# 'UnVieQ=='.from_b64 # => "Ruby"
|
45
|
+
def from_b64(opts = {})
|
46
|
+
opts[:mode] ||= :strict
|
47
|
+
return Base64.strict_decode64(self) if opts[:mode] == :strict ||
|
48
|
+
opts[:mode] == :rfc4648
|
49
|
+
return Base64.decode64(self) if opts[:mode] == :rfc2045
|
50
|
+
return Base64.urlsafe_decode64(self) if opts[:mode] == :urlsafe
|
51
|
+
end
|
52
|
+
|
53
|
+
# Decode the string from base64 in place as described for {String#from_b64}.
|
54
|
+
# @return [nil]
|
55
|
+
# @example
|
56
|
+
# a = 'SGVsbG8gd29ybGQh' # => "SGVsbG8gd29ybGQh"
|
57
|
+
# a.from_b64! # => nil
|
58
|
+
# a # => "Hello world!"
|
59
|
+
def from_b64!(opts = {})
|
60
|
+
opts[:mode] ||= :strict
|
61
|
+
replace(from_b64) if opts[:mode] == :strict ||
|
62
|
+
opts[:mode] == :rfc4648
|
63
|
+
replace(from_b64(mode: :rfc2045)) if opts[:mode] == :rfc2045
|
64
|
+
replace(from_b64(mode: :urlsafe)) if opts[:mode] == :urlsafe
|
65
|
+
end
|
66
|
+
|
67
|
+
# Is the string encoded in base64?
|
68
|
+
# @param opts [Hash] optional parameters
|
69
|
+
# @option opts [Symbol] :mode Default value: +:strict+.
|
70
|
+
# Other values are +:strict+ (+:rfc4648+) or +:urlsafe+.
|
71
|
+
# @see https://ruby-doc.org/stdlib-2.6.5/libdoc/base64/rdoc/Base64.html
|
72
|
+
# @return [Boolean] +true+ if the string is a valid base64 string, +false+
|
73
|
+
# else.
|
74
|
+
# @example
|
75
|
+
# 'SGVsbG8gd29ybGQh'.b64? # => true
|
76
|
+
# 'SGVsbG8g@@d29ybGQh'.b64? # => false
|
77
|
+
def b64?(opts = {})
|
78
|
+
opts[:mode] ||= :strict
|
79
|
+
b64 = false
|
80
|
+
# https://www.rexegg.com/regex-ruby.html
|
81
|
+
reg1 = %r{\A(?:[a-zA-Z0-9+/]{4})*(?:|(?:[a-zA-Z0-9+/]{3}=)|
|
82
|
+
(?:[a-zA-Z0-9+/]{2}==)|(?:[a-zA-Z0-9+/]{1}===))\Z}xn
|
83
|
+
reg3 = /\A(?:[a-zA-Z0-9\-_]{4})*(?:|(?:[a-zA-Z0-9\-_]{3}=)|
|
84
|
+
(?:[a-zA-Z0-9\-_]{2}==)|(?:[a-zA-Z0-9\-_]{1}===))\Z/xn
|
85
|
+
if opts[:mode] == :strict || opts[:mode] == :rfc4648
|
86
|
+
b64 = true if reg1.match?(self)
|
87
|
+
elsif opts[:mode] == :rfc2045
|
88
|
+
b64 = true
|
89
|
+
split("\n").each do |s|
|
90
|
+
b64 = false unless reg1.match?(s)
|
91
|
+
end
|
92
|
+
elsif opts[:mode] == :urlsafe
|
93
|
+
b64 = true if reg3.match?(self)
|
94
|
+
else
|
95
|
+
raise ArgumentError 'Wrong mode'
|
96
|
+
end
|
97
|
+
return b64
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Ruby standard library
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
class String
|
7
|
+
# Calculate the md5 hash of the string.
|
8
|
+
# @see https://ruby-doc.org/stdlib-2.6.1/libdoc/digest/rdoc/Digest/MD5.html
|
9
|
+
# @return [String] md5 hash
|
10
|
+
# @example
|
11
|
+
# 'noraj'.md5 # => "556cc23863fef20fab5c456db166bc6e"
|
12
|
+
def md5
|
13
|
+
Digest::MD5.hexdigest self
|
14
|
+
end
|
15
|
+
|
16
|
+
# Calculate the md5 hash of the string in place as described for {#md5}.
|
17
|
+
# @example
|
18
|
+
# a = '\o/' # => "\\o/"
|
19
|
+
# a.md5! # => "881419964e480e66162da521ccc25ebf"
|
20
|
+
# a # => "881419964e480e66162da521ccc25ebf"
|
21
|
+
def md5!
|
22
|
+
replace(md5)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Calculate the sha1 hash of the string.
|
26
|
+
# @see https://ruby-doc.org/stdlib-2.6.1/libdoc/digest/rdoc/Digest/SHA1.html
|
27
|
+
# @return [String] sha1 hash
|
28
|
+
# @example
|
29
|
+
# 'ctf-party'.sha1 # => "5a64f3bc491d0977e1e3578a48c65a89a16a5fe8"
|
30
|
+
def sha1
|
31
|
+
Digest::SHA1.hexdigest self
|
32
|
+
end
|
33
|
+
|
34
|
+
# Calculate the sha1 hash of the string in place as described for {#sha1}.
|
35
|
+
# @example
|
36
|
+
# bob = 'alice' # => "alice"
|
37
|
+
# bob.sha1! # => "522b276a356bdf39013dfabea2cd43e141ecc9e8"
|
38
|
+
# bob # => "522b276a356bdf39013dfabea2cd43e141ecc9e8"
|
39
|
+
def sha1!
|
40
|
+
replace(sha1)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Calculate the sha2 hash of the string.
|
44
|
+
# @param opts [Hash] optional parameters
|
45
|
+
# @option opts [Integer] :bitlen Defines the bit lenght of the digest.
|
46
|
+
# Default value: 256 (SHA2-256). other valid vales are 384 (SHA2-384)
|
47
|
+
# and 512 (SHA2-512).
|
48
|
+
# @see https://ruby-doc.org/stdlib-2.6.1/libdoc/digest/rdoc/Digest/SHA2.html
|
49
|
+
# @return [String] sha hash
|
50
|
+
# @example
|
51
|
+
# 'try harder'.sha2 # => "5321ff2d4b1389b3a350dfe8ca77e3889dc6259bb233ad..."
|
52
|
+
# 'try harder'.sha2(bitlen: 512) # => "a7b73a98c095b22e25407b15c4dec128c..."
|
53
|
+
def sha2(opts = {})
|
54
|
+
opts[:bitlen] ||= 256
|
55
|
+
Digest::SHA2.new(opts[:bitlen]).hexdigest self
|
56
|
+
end
|
57
|
+
|
58
|
+
# Calculate the sha2 hash of the string in place as described for {#sha2}.
|
59
|
+
# @example
|
60
|
+
# th = 'try harder' # => "try harder"
|
61
|
+
# th.sha2!(bitlen: 384) # => "bb7f60b9562a19c3a83c23791440af11591c42ede9..."
|
62
|
+
# th # => "bb7f60b9562a19c3a83c23791440af11591c42ede9988334cdfd7efa4261a..."
|
63
|
+
def sha2!(opts = {})
|
64
|
+
replace(sha2(opts))
|
65
|
+
end
|
66
|
+
|
67
|
+
# Alias for {#sha2} with default value ( +sha2(bitlen: 256)+ ).
|
68
|
+
def sha2_256
|
69
|
+
sha2
|
70
|
+
end
|
71
|
+
|
72
|
+
# Alias for {#sha2!} with default value ( +sha2!(bitlen: 256)+ ).
|
73
|
+
def sha2_256!
|
74
|
+
replace(sha2)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Alias for {#sha2} with default value ( +sha2(bitlen: 384)+ ).
|
78
|
+
def sha2_384
|
79
|
+
sha2(bitlen: 384)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Alias for {#sha2!} with default value ( +sha2!(bitlen: 384)+ ).
|
83
|
+
def sha2_384!
|
84
|
+
replace(sha2(bitlen: 384))
|
85
|
+
end
|
86
|
+
|
87
|
+
# Alias for {#sha2} with default value ( +sha2(bitlen: 512)+ ).
|
88
|
+
def sha2_512
|
89
|
+
sha2(bitlen: 512)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Alias for {#sha2!} with default value ( +sha2!(bitlen: 512)+ ).
|
93
|
+
def sha2_512!
|
94
|
+
replace(sha2(bitlen: 512))
|
95
|
+
end
|
96
|
+
|
97
|
+
# Calculate the RIPEMD-160 hash of the string.
|
98
|
+
# @see https://ruby-doc.org/stdlib-2.6.1/libdoc/digest/rdoc/Digest/RMD160.html
|
99
|
+
# @return [String] RIPEMD-160 hash
|
100
|
+
# @example
|
101
|
+
# 'payload'.rmd160 # => "3c6255c112d409dafdb84d5b0edba98dfd27b44f"
|
102
|
+
def rmd160
|
103
|
+
Digest::RMD160.hexdigest self
|
104
|
+
end
|
105
|
+
|
106
|
+
# Calculate the RIPEMD-160 hash of the string in place as described for
|
107
|
+
# {#rmd160}.
|
108
|
+
# @example
|
109
|
+
# pl = 'payload' # => "payload"
|
110
|
+
# pl.rmd160! # => "3c6255c112d409dafdb84d5b0edba98dfd27b44f"
|
111
|
+
# pl # => "3c6255c112d409dafdb84d5b0edba98dfd27b44f"
|
112
|
+
def rmd160!
|
113
|
+
replace(rmd160)
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ctf_party/digest'
|
4
|
+
|
5
|
+
class String
|
6
|
+
# The flag configuration hash. See {.flag=}.
|
7
|
+
@@flag = {
|
8
|
+
prefix: '',
|
9
|
+
suffix: '',
|
10
|
+
enclosing: ['{', '}'],
|
11
|
+
digest: nil
|
12
|
+
}
|
13
|
+
|
14
|
+
# Show the actual flag configuration. See {.flag=}.
|
15
|
+
def self.flag
|
16
|
+
@@flag
|
17
|
+
end
|
18
|
+
|
19
|
+
# rubocop:disable Metrics/LineLength
|
20
|
+
|
21
|
+
# Update the flag configuration.
|
22
|
+
# @param hash [Hash] flag configuration
|
23
|
+
# @option hash [String] :prefix prefix of the flag. Default: none.
|
24
|
+
# @option hash [String] :suffix suffix of the flag. Default: none.
|
25
|
+
# @option hash [Array<String>] :enclosing the characters used to surround
|
26
|
+
# the flag. Default are curly braces: +{+, +}+. The array must contain
|
27
|
+
# exactly 2 elements.
|
28
|
+
# @option hash [String] :digest the hash algorithm to apply on the flag.
|
29
|
+
# Default: none. Allowed values: md5, sha1, sha2_256, sha2_384, sha2_512,
|
30
|
+
# rmd160.
|
31
|
+
# @return [Hash] hash of the updated options.
|
32
|
+
# @note You can provide the full hash or only the key to update.
|
33
|
+
# @example
|
34
|
+
# String.flag # => {:prefix=>"", :suffix=>"", :enclosing=>["{", "}"], :digest=>nil}
|
35
|
+
# String.flag = {prefix: 'sigsegv', digest: 'md5'}
|
36
|
+
# String.flag # => {:prefix=>"sigsegv", :suffix=>"", :enclosing=>["{", "}"], :digest=>"md5"}
|
37
|
+
# 'this_1s_a_fl4g'.flag # => "sigsegv{a5bec9e2a86b6b70d288451eb38dfec8}"
|
38
|
+
def self.flag=(hash)
|
39
|
+
hash.select! { |k, _v| @@flag.key?(k) }
|
40
|
+
@@flag.merge!(hash)
|
41
|
+
end
|
42
|
+
|
43
|
+
# rubocop:enable Metrics/LineLength
|
44
|
+
|
45
|
+
# Format the current string into the configured flag format. See {.flag=}
|
46
|
+
# example.
|
47
|
+
# @return [String] the format flag.
|
48
|
+
def flag
|
49
|
+
flag = ''
|
50
|
+
flag += @@flag[:prefix]
|
51
|
+
flag += @@flag[:enclosing][0]
|
52
|
+
if @@flag[:digest].nil?
|
53
|
+
flag += self
|
54
|
+
else
|
55
|
+
case @@flag[:digest]
|
56
|
+
when 'md5'
|
57
|
+
flag += md5
|
58
|
+
when 'sha1'
|
59
|
+
flag += sha1
|
60
|
+
when 'sha2_256'
|
61
|
+
flag += sha2_256
|
62
|
+
when 'sha2_384'
|
63
|
+
flag += sha2_384
|
64
|
+
when 'sha2_512'
|
65
|
+
flag += sha2_512
|
66
|
+
when 'rmd160'
|
67
|
+
flag += rmd160
|
68
|
+
end
|
69
|
+
end
|
70
|
+
flag += @@flag[:enclosing][1]
|
71
|
+
flag + @@flag[:suffix]
|
72
|
+
end
|
73
|
+
|
74
|
+
# Format the current string into the configured flag format in place as
|
75
|
+
# described for {#flag}.
|
76
|
+
def flag!
|
77
|
+
replace(flag)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Check if the string respect the defined flag format.
|
81
|
+
# @return [Boolean] true if it respects the configured flag format. but it
|
82
|
+
# does not check digest used.
|
83
|
+
# @example
|
84
|
+
# String.flag = {prefix: 'flag'}
|
85
|
+
# flag = 'Brav0!'
|
86
|
+
# flag.flag! # => "flag{Brav0!}"
|
87
|
+
# flag.flag? # => true
|
88
|
+
# flag = 'ctf{Brav0!}'
|
89
|
+
# flag.flag? # => false
|
90
|
+
def flag?
|
91
|
+
/#{@@flag[:prefix]}#{@@flag[:enclosing][0]}[[:print:]]+
|
92
|
+
#{@@flag[:enclosing][1]}#{@@flag[:suffix]}/ox.match?(self)
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class String
|
4
|
+
# "Encrypt / Decrypt" the string with Caesar cipher. This will shift the
|
5
|
+
# alphabet letters by +n+, where +n+ is the integer key. The same function
|
6
|
+
# is used for encryption / decryption.
|
7
|
+
# @param opts [Hash] optional parameters
|
8
|
+
# @option opts [Integer] :shift The shift key. Default value: 13.
|
9
|
+
# @see https://en.wikipedia.org/wiki/Caesar_cipher
|
10
|
+
# @return [String] the (de)ciphered string
|
11
|
+
# @example
|
12
|
+
# 'Hello world!'.rot # => "Uryyb jbeyq!"
|
13
|
+
# 'Hello world!'.rot(shift: 11) # => "Spwwz hzcwo!"
|
14
|
+
# 'Uryyb jbeyq!'.rot # => "Hello world!"
|
15
|
+
# 'Spwwz hzcwo!'.rot(shift: 26-11) # => "Hello world!"
|
16
|
+
def rot(opts = {})
|
17
|
+
opts[:shift] ||= 13
|
18
|
+
alphabet = Array('a'..'z')
|
19
|
+
lowercase = Hash[alphabet.zip(alphabet.rotate(opts[:shift]))]
|
20
|
+
alphabet = Array('A'..'Z')
|
21
|
+
uppercasecase = Hash[alphabet.zip(alphabet.rotate(opts[:shift]))]
|
22
|
+
encrypter = lowercase.merge(uppercasecase)
|
23
|
+
chars.map { |c| encrypter.fetch(c, c) }.join
|
24
|
+
end
|
25
|
+
|
26
|
+
# "Encrypt / Decrypt" the string with Caesar cipher in place as described for
|
27
|
+
# {String#rot}.
|
28
|
+
# @return [String] the (de)ciphered string as well as changing changing the
|
29
|
+
# object in place.
|
30
|
+
# @example
|
31
|
+
# a = 'Bonjour le monde !' # => "Bonjour le monde !"
|
32
|
+
# a.rot! # => "Obawbhe yr zbaqr !"
|
33
|
+
# a # => "Obawbhe yr zbaqr !"
|
34
|
+
def rot!(opts = {})
|
35
|
+
replace(rot(opts))
|
36
|
+
end
|
37
|
+
|
38
|
+
# Alias for {#rot} with default value ( +rot(shift: 13)+ ).
|
39
|
+
def rot13
|
40
|
+
rot
|
41
|
+
end
|
42
|
+
|
43
|
+
# Alias for {#rot!} with default value ( +rot!(shift: 13)+ ).
|
44
|
+
def rot13!
|
45
|
+
rot!
|
46
|
+
end
|
47
|
+
end
|