ctf-party 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|