coder_decorator 1.1.1 → 2.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 +4 -4
- data/README.md +12 -42
- data/lib/coder_decorator.rb +13 -0
- data/lib/coder_decorator/coders/base64.rb +1 -2
- data/lib/coder_decorator/coders/cipher.rb +14 -21
- data/lib/coder_decorator/coders/coder.rb +7 -22
- data/lib/coder_decorator/coders/hmac.rb +6 -3
- data/lib/coder_decorator/coders/identity.rb +1 -0
- data/lib/coder_decorator/coders/json.rb +1 -2
- data/lib/coder_decorator/coders/marshal.rb +2 -2
- data/lib/coder_decorator/coders/rescue.rb +2 -1
- data/lib/coder_decorator/coders/zip.rb +1 -2
- metadata +5 -8
- data/lib/coder_decorator/builder.rb +0 -46
- data/lib/coder_decorator/errors.rb +0 -5
- data/lib/coder_decorator/name_converter.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7155de757d7a11efebe6aaee8a3cdb785fde54cf
|
4
|
+
data.tar.gz: fa86ce84c8c168822da29def9df4b93786fbdc01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77458a9ed211be9a4770bd7a91d3e88343ccfe7da701beb1e220b580db1a7689478a5666c8392ef7830af6244e1d6bd0d258ab3177a50df91cd537eb6e545f9d
|
7
|
+
data.tar.gz: b7fd8de88992caaa41dcd38ab35287f5d6e38b3dedf0304ea8c4beae84f09c202b183ee1029bb04b2ab7e4dcdb558d706041380e49fa809307590be8bb89e495
|
data/README.md
CHANGED
@@ -15,8 +15,7 @@ gem install 'coder_decorator'
|
|
15
15
|
Encode data with Marshal and Base64:
|
16
16
|
|
17
17
|
```ruby
|
18
|
-
require 'coder_decorator
|
19
|
-
require 'coder_decorator/coders/marshal'
|
18
|
+
require 'coder_decorator'
|
20
19
|
include CoderDecorator
|
21
20
|
coder = Coders::Base64.new(Coders::Marshal.new)
|
22
21
|
encoded_data = coder.encode(data)
|
@@ -26,52 +25,20 @@ coder.decode(encoded_data)
|
|
26
25
|
Encode data with JSON and Zip:
|
27
26
|
|
28
27
|
```ruby
|
29
|
-
require 'coder_decorator
|
30
|
-
require 'coder_decorator/coders/zip'
|
28
|
+
require 'coder_decorator'
|
31
29
|
include CoderDecorator
|
32
30
|
coder = Coders::Zip.new(Coders::JSON.new)
|
33
31
|
encoded_data = coder.encode(data)
|
34
32
|
coder.decode(encoded_data)
|
35
33
|
```
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
```ruby
|
40
|
-
require 'coder_decorator'
|
41
|
-
```
|
42
|
-
|
43
|
-
All built-in coders are listed in [lib/coder_decorator/coders](lib/coder_decorator/coders).
|
44
|
-
|
45
|
-
## Use `CoderDecorator::Builder` to construct coders
|
46
|
-
|
47
|
-
`CoderDecorator::Builder` provides a convenient interface to build a coder by passing arguments instead of tediously initializing and wrapping coders, for example:
|
48
|
-
|
49
|
-
```ruby
|
50
|
-
require 'coder_decorator/builder'
|
51
|
-
CoderDecorator::Builder.build(:marshal, :base64)
|
52
|
-
```
|
53
|
-
|
54
|
-
is equivalent to:
|
55
|
-
|
56
|
-
```ruby
|
57
|
-
require 'coder_decorator/coders/marshal'
|
58
|
-
require 'coder_decorator/coders/base64'
|
59
|
-
CoderDecorator::Coders::Marshal.new(CoderDecorator::Coders::Base64.new)
|
60
|
-
```
|
61
|
-
|
62
|
-
Use array to pass arguments to the coder:
|
63
|
-
|
64
|
-
```ruby
|
65
|
-
CoderDecorator::Builder.build(:marshal, [:base64, {strict: true}])
|
66
|
-
```
|
67
|
-
|
68
|
-
Use `CoderDecorator.coder_names` to see all available coder names.
|
35
|
+
Coders are listed in [lib/coder_decorator/coders](lib/coder_decorator/coders).
|
69
36
|
|
70
37
|
## Integration with Rack
|
71
38
|
|
72
39
|
```ruby
|
73
40
|
require 'rack'
|
74
|
-
require 'coder_decorator
|
41
|
+
require 'coder_decorator'
|
75
42
|
|
76
43
|
include CoderDecorator
|
77
44
|
|
@@ -82,11 +49,14 @@ app = lambda do |env|
|
|
82
49
|
[200, {}, [session[:count].to_s]]
|
83
50
|
end
|
84
51
|
|
85
|
-
coder =
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
52
|
+
coder = Coders::Rescue.new(
|
53
|
+
Coders::HMAC.new(
|
54
|
+
Coders::Cipher.new(
|
55
|
+
Coders::JSON.new,
|
56
|
+
secret: 'x' * 32
|
57
|
+
),
|
58
|
+
secret: 'y' * 32
|
59
|
+
)
|
90
60
|
)
|
91
61
|
|
92
62
|
app = Rack::Builder.app(app) do
|
data/lib/coder_decorator.rb
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module CoderDecorator # :nodoc:
|
4
|
+
module Coders # :nodoc:
|
5
|
+
autoload :Base64, 'coder_decorator/coders/base64'
|
6
|
+
autoload :Cipher, 'coder_decorator/coders/cipher'
|
7
|
+
autoload :Coder, 'coder_decorator/coders/coder'
|
8
|
+
autoload :HMAC, 'coder_decorator/coders/hmac'
|
9
|
+
autoload :Identity, 'coder_decorator/coders/identity'
|
10
|
+
autoload :JSON, 'coder_decorator/coders/json'
|
11
|
+
autoload :Marshal, 'coder_decorator/coders/marshal'
|
12
|
+
autoload :Rescue, 'coder_decorator/coders/rescue'
|
13
|
+
autoload :Zip, 'coder_decorator/coders/zip'
|
14
|
+
end
|
15
|
+
|
3
16
|
def self.coder_names
|
4
17
|
@coder_names ||= begin
|
5
18
|
coder_names = Dir["#{__dir__}/coder_decorator/coders/*"].map! { |name| File.basename(name, '.rb') }
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'coder_decorator/coders/coder'
|
3
4
|
module CoderDecorator
|
4
5
|
module Coders
|
@@ -14,8 +15,6 @@ module CoderDecorator
|
|
14
15
|
|
15
16
|
def decode(str)
|
16
17
|
coder.decode(str.unpack(@template_str).first)
|
17
|
-
rescue ::ArgumentError
|
18
|
-
raise InvalidEncoding
|
19
18
|
end
|
20
19
|
end
|
21
20
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'coder_decorator/coders/coder'
|
3
|
-
require 'coder_decorator/coders/base64'
|
4
4
|
require 'openssl'
|
5
5
|
|
6
6
|
module CoderDecorator
|
@@ -14,8 +14,7 @@ module CoderDecorator
|
|
14
14
|
super(coder)
|
15
15
|
@secret = secret
|
16
16
|
@old_secret = old_secret
|
17
|
-
@cipher =
|
18
|
-
@base64 = Coders::Base64.new
|
17
|
+
@cipher = OpenSSL::Cipher.new(cipher)
|
19
18
|
end
|
20
19
|
|
21
20
|
def encode(obj)
|
@@ -23,29 +22,23 @@ module CoderDecorator
|
|
23
22
|
@cipher.key = @secret
|
24
23
|
iv = @cipher.random_iv
|
25
24
|
encrypted_data = @cipher.update(coder.encode(obj)) << @cipher.final
|
26
|
-
|
27
|
-
@base64.encode(blob)
|
25
|
+
"#{[encrypted_data].pack('m0')}--#{[iv].pack('m0')}"
|
28
26
|
end
|
29
27
|
|
30
|
-
def decode(
|
31
|
-
[@
|
28
|
+
def decode(data)
|
29
|
+
secrets = [@old_secret, @secret]
|
30
|
+
until secrets.empty?
|
31
|
+
secret = secrets.pop
|
32
32
|
begin
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
encrypted_data, iv = data.split('--').map! { |v| v.unpack('m0').first }
|
34
|
+
@cipher.decrypt
|
35
|
+
@cipher.key = secret
|
36
|
+
@cipher.iv = iv
|
37
|
+
return coder.decode(@cipher.update(encrypted_data) << @cipher.final)
|
38
|
+
rescue StandardError
|
39
|
+
secrets.empty? ? raise : next
|
36
40
|
end
|
37
41
|
end
|
38
|
-
raise InvalidEncoding
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def decrypt(secret, data)
|
44
|
-
encrypted_data, iv = @base64.decode(data).split('--').map! { |v| @base64.decode(v) }
|
45
|
-
@cipher.decrypt
|
46
|
-
@cipher.key = secret
|
47
|
-
@cipher.iv = iv
|
48
|
-
coder.decode(@cipher.update(encrypted_data) << @cipher.final)
|
49
42
|
end
|
50
43
|
end
|
51
44
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
3
|
module CoderDecorator
|
4
4
|
module Coders
|
5
5
|
# The abstract class of coder, must implement #encode and #decode.
|
@@ -24,41 +24,26 @@ module CoderDecorator
|
|
24
24
|
# end
|
25
25
|
# end
|
26
26
|
#
|
27
|
-
class Coder
|
28
|
-
|
27
|
+
class Coder
|
28
|
+
attr_reader :coder
|
29
29
|
|
30
30
|
# Can optionally pass a base coder which is going to be decorated.
|
31
31
|
def initialize(coder = nil)
|
32
|
-
@
|
33
|
-
end
|
34
|
-
|
35
|
-
def coder
|
36
|
-
@_coder ||= Null.new
|
32
|
+
@coder = coder || Null.new
|
37
33
|
end
|
38
34
|
|
39
35
|
def encode(_obj)
|
40
|
-
|
36
|
+
raise NotImplementedError
|
41
37
|
end
|
42
38
|
|
43
39
|
# It decodes +_obj+, returning decoded data,
|
44
40
|
# or +nil+ if it can't decode.
|
45
41
|
def decode(_obj)
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def method_missing(name, *args, &block)
|
52
|
-
super unless DELEGATE.include? name
|
53
|
-
::Kernel.send(name, *args, &block)
|
54
|
-
end
|
55
|
-
|
56
|
-
def respond_to_missing?(name, include_private = false)
|
57
|
-
DELEGATE.include?(name) || super
|
42
|
+
raise NotImplementedError
|
58
43
|
end
|
59
44
|
end
|
60
45
|
|
61
|
-
class Null
|
46
|
+
class Null # :nodoc:
|
62
47
|
def encode(obj)
|
63
48
|
obj
|
64
49
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'coder_decorator/coders/coder'
|
3
4
|
require 'openssl'
|
4
5
|
|
@@ -10,6 +11,8 @@ module CoderDecorator
|
|
10
11
|
# "#{data}--#{hmac}"
|
11
12
|
#
|
12
13
|
class HMAC < Coder
|
14
|
+
class InvalidSignature < StandardError; end
|
15
|
+
|
13
16
|
REGEXP = /\A(.*)--(.*)\z/
|
14
17
|
|
15
18
|
def initialize(coder = nil, secret:, old_secret: nil, digest: 'SHA1')
|
@@ -27,9 +30,9 @@ module CoderDecorator
|
|
27
30
|
|
28
31
|
def decode(str)
|
29
32
|
match_data = REGEXP.match(str)
|
30
|
-
data, hmac = match_data
|
33
|
+
data, hmac = match_data.captures if match_data
|
31
34
|
secrets = [@secret, @old_secret]
|
32
|
-
raise
|
35
|
+
raise InvalidSignature unless data && hmac && secrets.any? { |secret| secure_compare(hmac, generate_hmac(secret, data)) }
|
33
36
|
coder.decode(data)
|
34
37
|
end
|
35
38
|
|
@@ -39,7 +42,7 @@ module CoderDecorator
|
|
39
42
|
::OpenSSL::HMAC.hexdigest(@digest.new, secret, str)
|
40
43
|
end
|
41
44
|
|
42
|
-
def secure_compare(a, b)
|
45
|
+
def secure_compare(a, b) # rubocop:disable Naming/UncommunicativeMethodParamName
|
43
46
|
return false unless a.bytesize == b.bytesize
|
44
47
|
l = a.unpack('C*')
|
45
48
|
r = 0
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'coder_decorator/coders/coder'
|
3
4
|
require 'json'
|
4
5
|
module CoderDecorator
|
@@ -10,8 +11,6 @@ module CoderDecorator
|
|
10
11
|
|
11
12
|
def decode(str)
|
12
13
|
coder.decode(::JSON.parse(str))
|
13
|
-
rescue ::JSON::ParserError
|
14
|
-
raise InvalidEncoding
|
15
14
|
end
|
16
15
|
end
|
17
16
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'coder_decorator/coders/coder'
|
4
|
+
|
3
5
|
module CoderDecorator
|
4
6
|
module Coders
|
5
7
|
class Marshal < Coder # :nodoc:
|
@@ -9,8 +11,6 @@ module CoderDecorator
|
|
9
11
|
|
10
12
|
def decode(str)
|
11
13
|
coder.decode(::Marshal.load(str))
|
12
|
-
rescue ::TypeError
|
13
|
-
raise InvalidEncoding
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'coder_decorator/coders/coder'
|
3
4
|
module CoderDecorator
|
4
5
|
module Coders
|
@@ -10,7 +11,7 @@ module CoderDecorator
|
|
10
11
|
|
11
12
|
def decode(obj)
|
12
13
|
coder.decode(obj)
|
13
|
-
rescue
|
14
|
+
rescue StandardError
|
14
15
|
nil
|
15
16
|
end
|
16
17
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'coder_decorator/coders/coder'
|
3
4
|
require 'zlib'
|
4
5
|
module CoderDecorator
|
@@ -10,8 +11,6 @@ module CoderDecorator
|
|
10
11
|
|
11
12
|
def decode(str)
|
12
13
|
coder.decode(::Zlib::Inflate.inflate(str))
|
13
|
-
rescue ::Zlib::DataError
|
14
|
-
raise InvalidEncoding
|
15
14
|
end
|
16
15
|
end
|
17
16
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coder_decorator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jian Weihang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: 0.53.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.53.0
|
55
55
|
description: An encoding/decoding library with decorator pattern.
|
56
56
|
email: tonytonyjan@gmail.com
|
57
57
|
executables: []
|
@@ -60,7 +60,6 @@ extra_rdoc_files: []
|
|
60
60
|
files:
|
61
61
|
- README.md
|
62
62
|
- lib/coder_decorator.rb
|
63
|
-
- lib/coder_decorator/builder.rb
|
64
63
|
- lib/coder_decorator/coders/base64.rb
|
65
64
|
- lib/coder_decorator/coders/cipher.rb
|
66
65
|
- lib/coder_decorator/coders/coder.rb
|
@@ -70,8 +69,6 @@ files:
|
|
70
69
|
- lib/coder_decorator/coders/marshal.rb
|
71
70
|
- lib/coder_decorator/coders/rescue.rb
|
72
71
|
- lib/coder_decorator/coders/zip.rb
|
73
|
-
- lib/coder_decorator/errors.rb
|
74
|
-
- lib/coder_decorator/name_converter.rb
|
75
72
|
homepage: https://github.com/tonytonyjan/coder_decorator
|
76
73
|
licenses:
|
77
74
|
- MIT
|
@@ -92,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
89
|
version: '0'
|
93
90
|
requirements: []
|
94
91
|
rubyforge_project:
|
95
|
-
rubygems_version: 2.
|
92
|
+
rubygems_version: 2.4.5
|
96
93
|
signing_key:
|
97
94
|
specification_version: 4
|
98
95
|
summary: An encoding/decoding library with decorator pattern.
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'coder_decorator/name_converter'
|
3
|
-
module CoderDecorator
|
4
|
-
# It provides a convenient interface to build a coder by passing arguments
|
5
|
-
# instead of tediously initializing and wrapping, for example:
|
6
|
-
#
|
7
|
-
# require 'coder_decorator/builder'
|
8
|
-
# CoderDecorator::Builder.build(:marshal, :base64)
|
9
|
-
#
|
10
|
-
# is equivalent to:
|
11
|
-
#
|
12
|
-
# require 'coder_decorator/coders/marshal'
|
13
|
-
# require 'coder_decorator/coders/base64'
|
14
|
-
# CoderDecorator::Coders::Marshal.new(CoderDecorator::Coders::Base64.new)
|
15
|
-
#
|
16
|
-
# To pass arguments to a coder, use array:
|
17
|
-
#
|
18
|
-
# CoderDecorator::Builder.build(:marshal, [:base64, {strict: true}])
|
19
|
-
#
|
20
|
-
class Builder
|
21
|
-
# equivalent to +new(*coder_names).build+
|
22
|
-
def self.build(*coder_names)
|
23
|
-
new(*coder_names).build
|
24
|
-
end
|
25
|
-
|
26
|
-
# all coder names are listed as filenames under +lib/coder_decorator/coders+,
|
27
|
-
def initialize(*coder_names)
|
28
|
-
@coder_names = coder_names
|
29
|
-
end
|
30
|
-
|
31
|
-
def build
|
32
|
-
coder = nil
|
33
|
-
@coder_names.each do |coder_name|
|
34
|
-
case coder_name
|
35
|
-
when String, Symbol, Array
|
36
|
-
name, *arguments = Array(coder_name)
|
37
|
-
coder_class = NameConverter.new(name).constantize
|
38
|
-
coder = coder_class.new(coder, *arguments)
|
39
|
-
else
|
40
|
-
raise ArgumentError, "Each argument should be one of Symbol, String or Array instance, but #{coder_name.inspect} was given."
|
41
|
-
end
|
42
|
-
end
|
43
|
-
coder
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module CoderDecorator
|
3
|
-
# It converts coder names into class name or constant, for example:
|
4
|
-
#
|
5
|
-
# NameConverter.new('base64').to_class_name # => 'Base64'
|
6
|
-
# NameConverter.new('base64').constantize # => Coders::Base64
|
7
|
-
# NameConverter.new('json').to_class_name # => 'JSON'
|
8
|
-
# NameConverter.new('json').to_class_name # => Coders::JSON
|
9
|
-
#
|
10
|
-
class NameConverter
|
11
|
-
def initialize(coder_name)
|
12
|
-
@coder_name = coder_name.to_s
|
13
|
-
end
|
14
|
-
|
15
|
-
def constantize
|
16
|
-
@constantize ||= begin
|
17
|
-
require_relative "coders/#{@coder_name}"
|
18
|
-
CoderDecorator.const_get("Coders::#{to_class_name}")
|
19
|
-
rescue LoadError
|
20
|
-
raise "The coder \"#{@coder_name}\" doesn't exist, use `CoderDecorator.coder_names` to see all available coders."
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_class_name
|
25
|
-
case @coder_name
|
26
|
-
when 'hmac', 'json' then @coder_name.upcase
|
27
|
-
else @coder_name.to_s.split('_').map!(&:capitalize!).join
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|