Skip to content

Commit 450988d

Browse files
moozzipostmodern
authored andcommitted
Refactor ronin/support/encoding/base64 to not use the Base64 library
1 parent 113dfb7 commit 450988d

File tree

3 files changed

+116
-20
lines changed

3 files changed

+116
-20
lines changed

lib/ronin/support/encoding/base64.rb

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
# along with ronin-support. If not, see <https://www.gnu.org/licenses/>.
1717
#
1818

19-
require 'base64'
20-
2119
module Ronin
2220
module Support
2321
class Encoding < ::Encoding
@@ -48,9 +46,9 @@ module Base64
4846
#
4947
def self.encode(data, mode: nil)
5048
case mode
51-
when :strict then ::Base64.strict_encode64(data)
52-
when :url_safe then ::Base64.urlsafe_encode64(data)
53-
when nil then ::Base64.encode64(data)
49+
when :strict then strict_encode(data)
50+
when :url_safe then encode_urlsafe(data)
51+
when nil then [data].pack("m")
5452
else
5553
raise(ArgumentError,"Base64 mode must be either :string, :url_safe, or nil: #{mode.inspect}")
5654
end
@@ -70,13 +68,74 @@ def self.encode(data, mode: nil)
7068
#
7169
def self.decode(data, mode: nil)
7270
case mode
73-
when :strict then ::Base64.strict_decode64(data)
74-
when :url_safe then ::Base64.urlsafe_decode64(data)
75-
when nil then ::Base64.decode64(data)
71+
when :strict then strict_decode(data)
72+
when :url_safe then decode_urlsafe(data)
73+
when nil then data.unpack1("m")
7674
else
7775
raise(ArgumentError,"Base64 mode must be either :string, :url_safe, or nil: #{mode.inspect}")
7876
end
7977
end
78+
79+
#
80+
# Base64 strict encodes the given data.
81+
#
82+
# @param [String] data
83+
# The data to Base64 encode.
84+
#
85+
# @return [String]
86+
# The Base64 strict encoded data.
87+
#
88+
def self.strict_encode(data)
89+
[data].pack("m0")
90+
end
91+
92+
#
93+
# Base64 strict decodes the given data.
94+
#
95+
# @param [String] data
96+
# The Base64 data to decode.
97+
#
98+
# @return [String]
99+
# The strict decoded data.
100+
#
101+
def self.strict_decode(data)
102+
data.unpack1("m0")
103+
end
104+
105+
#
106+
# Base64 url-safe encodes the given data.
107+
#
108+
# @param [String] data
109+
# The data to Base64 encode.
110+
#
111+
# @return [String]
112+
# The Base64 url-safe encoded data.
113+
#
114+
def self.encode_urlsafe(data, padding: true)
115+
str = strict_encode(data)
116+
str.chomp!("==") or str.chomp!("=") unless padding
117+
str.tr!("+/", "-_")
118+
str
119+
end
120+
121+
#
122+
# Base64 url-safe decodes the given data.
123+
#
124+
# @param [String] data
125+
# The Base64 data to decode.
126+
#
127+
# @return [String]
128+
# The url-safe decoded data.
129+
#
130+
def self.decode_urlsafe(data)
131+
if !data.end_with?("=") && data.length % 4 != 0
132+
data = data.ljust((str.length + 3) & ~3, "=")
133+
data.tr!("-_", "+/")
134+
else
135+
data = data.tr("-_", "+/")
136+
end
137+
strict_decode(data)
138+
end
80139
end
81140
end
82141
end

spec/encoding/base64/core_ext/string_spec.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313
subject { "hello" }
1414

1515
it "must Base64 encode the String" do
16-
expect(subject.base64_encode).to eq(Base64.encode64(subject))
16+
expect(subject.base64_encode).to eq(Ronin::Support::Encoding::Base64.encode(subject))
1717
end
1818

1919
context "when given the mode: keyword of :strict" do
2020
subject { 'A' * 256 }
2121

2222
it "must strict encode the String" do
2323
expect(subject.base64_encode(mode: :strict)).to eq(
24-
Base64.strict_encode64(subject)
24+
Ronin::Support::Encoding::Base64.strict_encode(subject)
2525
)
2626
end
2727
end
@@ -31,7 +31,7 @@
3131

3232
it "must URL-safe encode the String" do
3333
expect(subject.base64_encode(mode: :url_safe)).to eq(
34-
Base64.strict_encode64(subject)
34+
Ronin::Support::Encoding::Base64.encode_urlsafe(subject)
3535
)
3636
end
3737
end
@@ -49,15 +49,15 @@
4949

5050
describe "#base64_decode" do
5151
let(:data) { "hello" }
52-
let(:subject) { Base64.encode64(data) }
52+
let(:subject) { Ronin::Support::Encoding::Base64.encode(data) }
5353

5454
it "must Base64 decode the given data" do
5555
expect(subject.base64_decode).to eq(data)
5656
end
5757

5858
context "when given the mode: keyword of :strict" do
5959
let(:data) { 'A' * 256 }
60-
let(:subject) { Base64.strict_encode64(data) }
60+
let(:subject) { Ronin::Support::Encoding::Base64.strict_encode(data) }
6161

6262
it "must strict decode the given data" do
6363
expect(subject.base64_decode(mode: :strict)).to eq(data)
@@ -66,7 +66,7 @@
6666

6767
context "when given the mode: keyword of :url_safe" do
6868
let(:data) { 'A' * 256 }
69-
let(:subject) { Base64.urlsafe_encode64(data) }
69+
let(:subject) { Ronin::Support::Encoding::Base64.encode_urlsafe(data) }
7070

7171
it "must URL-safe decode the given data" do
7272
expect(subject.base64_decode(mode: :url_safe)).to eq(data)

spec/encoding/base64_spec.rb

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@
44
describe Ronin::Support::Encoding::Base64 do
55
describe ".encode" do
66
let(:data) { "hello" }
7+
let(:encoded_data) { [data].pack("m") }
78

89
it "must Base64 encode the given data" do
9-
expect(subject.encode(data)).to eq(Base64.encode64(data))
10+
expect(subject.encode(data)).to eq(encoded_data)
1011
end
1112

1213
context "when given the mode: keyword of :strict" do
1314
let(:data) { 'A' * 256 }
1415

1516
it "must strict encode the given data" do
1617
expect(subject.encode(data, mode: :strict)).to eq(
17-
Base64.strict_encode64(data)
18+
described_class.strict_encode(data)
1819
)
1920
end
2021
end
@@ -24,7 +25,7 @@
2425

2526
it "must URL-safe encode the given data" do
2627
expect(subject.encode(data, mode: :url_safe)).to eq(
27-
Base64.strict_encode64(data)
28+
described_class.encode_urlsafe(data)
2829
)
2930
end
3031
end
@@ -42,15 +43,15 @@
4243

4344
describe ".decode" do
4445
let(:data) { "hello" }
45-
let(:encoded_data) { Base64.encode64(data) }
46+
let(:encoded_data) { [data].pack("m") }
4647

4748
it "must Base64 decode the given data" do
4849
expect(subject.decode(encoded_data)).to eq(data)
4950
end
5051

5152
context "when given the mode: keyword of :strict" do
5253
let(:data) { 'A' * 256 }
53-
let(:encoded_data) { Base64.strict_encode64(data) }
54+
let(:encoded_data) { described_class.strict_encode(data) }
5455

5556
it "must strict decode the given data" do
5657
expect(subject.decode(encoded_data, mode: :strict)).to eq(data)
@@ -59,7 +60,7 @@
5960

6061
context "when given the mode: keyword of :url_safe" do
6162
let(:data) { 'A' * 256 }
62-
let(:encoded_data) { Base64.urlsafe_encode64(data) }
63+
let(:encoded_data) { described_class.encode_urlsafe(data) }
6364

6465
it "must URL-safe decode the given data" do
6566
expect(subject.decode(encoded_data, mode: :url_safe)).to eq(data)
@@ -76,4 +77,40 @@
7677
end
7778
end
7879
end
80+
81+
describe "#strict_encode" do
82+
let(:data) { "AAAA" }
83+
let(:encoded_data) { "QUFBQQ==" }
84+
85+
it "must strict encode the given data" do
86+
expect(subject.strict_encode(data)).to eq(encoded_data)
87+
end
88+
end
89+
90+
describe "#encode_urlsafe" do
91+
let(:data) { "AAAA" }
92+
let(:encoded_data) { "QUFBQQ==" }
93+
94+
it "must URL-safe encode the given data" do
95+
expect(subject.encode_urlsafe(data)).to eq(encoded_data)
96+
end
97+
end
98+
99+
describe "#strict_decod" do
100+
let(:data) { "QUFBQQ==" }
101+
let(:decoded_data) { "AAAA" }
102+
103+
it "must strict decode the given data" do
104+
expect(subject.strict_decode(data)).to eq(decoded_data)
105+
end
106+
end
107+
108+
describe "decode_urlsafe" do
109+
let(:data) { "QUFBQQ==" }
110+
let(:decoded_data) { "AAAA" }
111+
112+
it "must URL-safe decode the given data" do
113+
expect(subject.decode_urlsafe(data)).to eq(decoded_data)
114+
end
115+
end
79116
end

0 commit comments

Comments
 (0)