m2m_keygen 0.2.0 → 0.4.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/CHANGELOG.md +28 -1
- data/Gemfile.lock +4 -2
- data/README.md +117 -4
- data/docs/M2mKeygen/Error.html +1 -1
- data/docs/M2mKeygen/ParamsEncoder.html +321 -0
- data/docs/M2mKeygen/RackValidator.html +531 -0
- data/docs/M2mKeygen/Signature.html +680 -0
- data/docs/M2mKeygen/Types.html +147 -0
- data/docs/M2mKeygen.html +7 -5
- data/docs/_index.html +61 -1
- data/docs/class_list.html +1 -1
- data/docs/file.README.html +126 -5
- data/docs/index.html +126 -5
- data/docs/method_list.html +88 -0
- data/docs/top-level-namespace.html +1 -1
- data/lib/m2m_keygen/params_encoder.rb +56 -0
- data/lib/m2m_keygen/rack_validator.rb +34 -0
- data/lib/m2m_keygen/signature.rb +78 -0
- data/lib/m2m_keygen/types/params_type.rb +25 -0
- data/lib/m2m_keygen/version.rb +1 -1
- data/lib/m2m_keygen.rb +5 -2
- data/m2m_keygen.gemspec +4 -0
- data/sorbet/rbi/gems/activesupport@7.0.3.1.rbi +24 -0
- data/sorbet/rbi/gems/rack@2.2.4.rbi +5630 -0
- data/sorbet/rbi/gems/{rb-fsevent@0.11.1.rbi → rb-fsevent@0.11.2.rbi} +0 -0
- data/sorbet/rbi/gems/webrick@1.7.0.rbi +3 -5
- data/sorbet/rbi/gems/yard@0.9.28.rbi +124 -0
- data/sorbet/rbi/gems/zeitwerk@2.6.0.rbi +861 -2
- data/sorbet/rbi/manual.rbi +7 -0
- metadata +27 -3
data/docs/method_list.html
CHANGED
@@ -44,6 +44,94 @@
|
|
44
44
|
<ul id="full_list" class="method">
|
45
45
|
|
46
46
|
|
47
|
+
<li class="odd ">
|
48
|
+
<div class="item">
|
49
|
+
<span class='object_link'><a href="M2mKeygen/Signature.html#algorithm-instance_method" title="M2mKeygen::Signature#algorithm (method)">#algorithm</a></span>
|
50
|
+
<small>M2mKeygen::Signature</small>
|
51
|
+
</div>
|
52
|
+
</li>
|
53
|
+
|
54
|
+
|
55
|
+
<li class="even ">
|
56
|
+
<div class="item">
|
57
|
+
<span class='object_link'><a href="M2mKeygen/ParamsEncoder.html#encode-instance_method" title="M2mKeygen::ParamsEncoder#encode (method)">#encode</a></span>
|
58
|
+
<small>M2mKeygen::ParamsEncoder</small>
|
59
|
+
</div>
|
60
|
+
</li>
|
61
|
+
|
62
|
+
|
63
|
+
<li class="odd ">
|
64
|
+
<div class="item">
|
65
|
+
<span class='object_link'><a href="M2mKeygen/RackValidator.html#header_name-instance_method" title="M2mKeygen::RackValidator#header_name (method)">#header_name</a></span>
|
66
|
+
<small>M2mKeygen::RackValidator</small>
|
67
|
+
</div>
|
68
|
+
</li>
|
69
|
+
|
70
|
+
|
71
|
+
<li class="even ">
|
72
|
+
<div class="item">
|
73
|
+
<span class='object_link'><a href="M2mKeygen/Signature.html#initialize-instance_method" title="M2mKeygen::Signature#initialize (method)">#initialize</a></span>
|
74
|
+
<small>M2mKeygen::Signature</small>
|
75
|
+
</div>
|
76
|
+
</li>
|
77
|
+
|
78
|
+
|
79
|
+
<li class="odd ">
|
80
|
+
<div class="item">
|
81
|
+
<span class='object_link'><a href="M2mKeygen/RackValidator.html#initialize-instance_method" title="M2mKeygen::RackValidator#initialize (method)">#initialize</a></span>
|
82
|
+
<small>M2mKeygen::RackValidator</small>
|
83
|
+
</div>
|
84
|
+
</li>
|
85
|
+
|
86
|
+
|
87
|
+
<li class="even ">
|
88
|
+
<div class="item">
|
89
|
+
<span class='object_link'><a href="M2mKeygen/ParamsEncoder.html#initialize-instance_method" title="M2mKeygen::ParamsEncoder#initialize (method)">#initialize</a></span>
|
90
|
+
<small>M2mKeygen::ParamsEncoder</small>
|
91
|
+
</div>
|
92
|
+
</li>
|
93
|
+
|
94
|
+
|
95
|
+
<li class="odd ">
|
96
|
+
<div class="item">
|
97
|
+
<span class='object_link'><a href="M2mKeygen/Signature.html#secret-instance_method" title="M2mKeygen::Signature#secret (method)">#secret</a></span>
|
98
|
+
<small>M2mKeygen::Signature</small>
|
99
|
+
</div>
|
100
|
+
</li>
|
101
|
+
|
102
|
+
|
103
|
+
<li class="even ">
|
104
|
+
<div class="item">
|
105
|
+
<span class='object_link'><a href="M2mKeygen/Signature.html#sign-instance_method" title="M2mKeygen::Signature#sign (method)">#sign</a></span>
|
106
|
+
<small>M2mKeygen::Signature</small>
|
107
|
+
</div>
|
108
|
+
</li>
|
109
|
+
|
110
|
+
|
111
|
+
<li class="odd ">
|
112
|
+
<div class="item">
|
113
|
+
<span class='object_link'><a href="M2mKeygen/RackValidator.html#signature-instance_method" title="M2mKeygen::RackValidator#signature (method)">#signature</a></span>
|
114
|
+
<small>M2mKeygen::RackValidator</small>
|
115
|
+
</div>
|
116
|
+
</li>
|
117
|
+
|
118
|
+
|
119
|
+
<li class="even ">
|
120
|
+
<div class="item">
|
121
|
+
<span class='object_link'><a href="M2mKeygen/Signature.html#validate-instance_method" title="M2mKeygen::Signature#validate (method)">#validate</a></span>
|
122
|
+
<small>M2mKeygen::Signature</small>
|
123
|
+
</div>
|
124
|
+
</li>
|
125
|
+
|
126
|
+
|
127
|
+
<li class="odd ">
|
128
|
+
<div class="item">
|
129
|
+
<span class='object_link'><a href="M2mKeygen/RackValidator.html#validate-instance_method" title="M2mKeygen::RackValidator#validate (method)">#validate</a></span>
|
130
|
+
<small>M2mKeygen::RackValidator</small>
|
131
|
+
</div>
|
132
|
+
</li>
|
133
|
+
|
134
|
+
|
47
135
|
|
48
136
|
</ul>
|
49
137
|
</div>
|
@@ -100,7 +100,7 @@
|
|
100
100
|
</div>
|
101
101
|
|
102
102
|
<div id="footer">
|
103
|
-
Generated on
|
103
|
+
Generated on Tue Aug 30 15:18:09 2022 by
|
104
104
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
105
|
0.9.28 (ruby-3.1.2).
|
106
106
|
</div>
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module M2mKeygen
|
4
|
+
# Encoder for params hash
|
5
|
+
class ParamsEncoder
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
sig { params(params: Types::ParamsType).void }
|
9
|
+
def initialize(params)
|
10
|
+
@params = T.let(params, Types::ParamsType)
|
11
|
+
end
|
12
|
+
|
13
|
+
sig { returns(String) }
|
14
|
+
def encode
|
15
|
+
return "" if @params.nil? || @params.empty?
|
16
|
+
@params
|
17
|
+
.sort_by { |k, _| k.to_s }
|
18
|
+
.reject { |_, v| (v.is_a?(String) && v == "") || v.nil? }
|
19
|
+
.map { |k, v| "#{k}=#{jsonify_value(encode_value(T.must(v)))}" }
|
20
|
+
.join("&")
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
sig do
|
26
|
+
params(value: Types::ParamsValueType).returns(
|
27
|
+
T.any(String, Symbol, Integer)
|
28
|
+
)
|
29
|
+
end
|
30
|
+
def jsonify_value(value)
|
31
|
+
return value unless value.is_a?(Hash) || value.is_a?(Array)
|
32
|
+
value.to_json
|
33
|
+
end
|
34
|
+
|
35
|
+
sig do
|
36
|
+
params(value: Types::ParamsValueType).returns(Types::ParamsValueType)
|
37
|
+
end
|
38
|
+
def encode_value(value)
|
39
|
+
return encode_hash_value(value) if value.is_a?(Hash)
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
sig do
|
44
|
+
params(value: Types::ParamsHashNotNilType).returns(
|
45
|
+
T::Hash[String, Types::ParamsValueType]
|
46
|
+
)
|
47
|
+
end
|
48
|
+
def encode_hash_value(value)
|
49
|
+
value
|
50
|
+
.sort_by { |k, _| k.to_s }
|
51
|
+
.reject { |_, v| (v.is_a?(String) && v == "") || v.nil? }
|
52
|
+
.map { |k, v| [k.to_s, encode_value(v)] }
|
53
|
+
.to_h
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
require "rack"
|
4
|
+
|
5
|
+
module M2mKeygen
|
6
|
+
class RackValidator
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig { returns(Signature) }
|
10
|
+
attr_reader :signature
|
11
|
+
|
12
|
+
sig { returns(String) }
|
13
|
+
attr_reader :header_name
|
14
|
+
|
15
|
+
sig { params(secret: String, algorithm: String, header_name: String).void }
|
16
|
+
def initialize(secret, algorithm: "sha512", header_name: "X-Signature")
|
17
|
+
@header_name = T.let("HTTP_#{header_name.tr("-", "_").upcase}", String)
|
18
|
+
@signature = T.let(Signature.new(secret, algorithm: algorithm), Signature)
|
19
|
+
end
|
20
|
+
|
21
|
+
sig { params(req: Rack::Request).returns(T::Boolean) }
|
22
|
+
def validate(req)
|
23
|
+
# This will cover the case when Rails is used.
|
24
|
+
req = Rack::Request.new(req.env)
|
25
|
+
@signature.validate(
|
26
|
+
params: req.params,
|
27
|
+
verb: req.request_method,
|
28
|
+
path: req.path,
|
29
|
+
signature: req.env["HTTP_X_SIGNATURE"]
|
30
|
+
) && req.params["expiry"] && req.params["expiry"].to_i > Time.now.to_i &&
|
31
|
+
req.params["expiry"].to_i < Time.now.to_i + 120
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
require "openssl"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module M2mKeygen
|
7
|
+
class Signature
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { returns(String) }
|
11
|
+
attr_reader :secret
|
12
|
+
|
13
|
+
sig { returns(String) }
|
14
|
+
attr_reader :algorithm
|
15
|
+
|
16
|
+
sig { params(secret: String, algorithm: String).void }
|
17
|
+
def initialize(secret, algorithm: "sha512")
|
18
|
+
@secret = T.let(secret, String)
|
19
|
+
@algorithm = T.let(algorithm, String)
|
20
|
+
OpenSSL::HMAC.hexdigest(@algorithm, @secret, "")
|
21
|
+
end
|
22
|
+
|
23
|
+
sig do
|
24
|
+
params(
|
25
|
+
params: Types::ParamsType,
|
26
|
+
verb: T.any(String, Symbol),
|
27
|
+
path: String
|
28
|
+
).returns(String)
|
29
|
+
end
|
30
|
+
def sign(params:, verb:, path:)
|
31
|
+
OpenSSL::HMAC.hexdigest(
|
32
|
+
@algorithm,
|
33
|
+
@secret,
|
34
|
+
"#{verb.to_s.upcase}#{path}#{ParamsEncoder.new(params).encode}"
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
sig do
|
39
|
+
params(
|
40
|
+
params: Types::ParamsType,
|
41
|
+
verb: T.any(String, Symbol),
|
42
|
+
path: String,
|
43
|
+
signature: String
|
44
|
+
).returns(T::Boolean)
|
45
|
+
end
|
46
|
+
def validate(params:, verb:, path:, signature:)
|
47
|
+
if OpenSSL.methods.include?(:fixed_length_secure_compare)
|
48
|
+
OpenSSL.fixed_length_secure_compare(
|
49
|
+
sign(params: params, verb: verb, path: path),
|
50
|
+
signature
|
51
|
+
)
|
52
|
+
else
|
53
|
+
fallback_fixed_length_secure_compare(
|
54
|
+
sign(params: params, verb: verb, path: path),
|
55
|
+
signature
|
56
|
+
)
|
57
|
+
end
|
58
|
+
rescue StandardError
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# Ruby 2.7 openssl lib doesn't have fixed_length_secure_compare method
|
65
|
+
# File activesupport/lib/active_support/security_utils.rb, line 11
|
66
|
+
# With sorbet fix
|
67
|
+
sig { params(str_a: String, str_b: String).returns(T::Boolean) }
|
68
|
+
def fallback_fixed_length_secure_compare(str_a, str_b)
|
69
|
+
return false unless str_a.bytesize == str_b.bytesize
|
70
|
+
|
71
|
+
l = str_a.unpack "C#{str_a.bytesize}"
|
72
|
+
|
73
|
+
res = 0
|
74
|
+
str_b.each_byte { |byte| res |= byte ^ l.shift.to_i }
|
75
|
+
res == 0
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
module M2mKeygen
|
3
|
+
module Types
|
4
|
+
extend T::Sig
|
5
|
+
|
6
|
+
ParamsType =
|
7
|
+
T.type_alias do
|
8
|
+
T.nilable(T::Hash[T.any(String, Symbol), T.nilable(ParamsValueType)])
|
9
|
+
end
|
10
|
+
|
11
|
+
ParamsHashNotNilType =
|
12
|
+
T.type_alias { T::Hash[T.any(String, Symbol), ParamsValueType] }
|
13
|
+
|
14
|
+
ParamsValueType =
|
15
|
+
T.type_alias do
|
16
|
+
T.any(
|
17
|
+
Integer,
|
18
|
+
String,
|
19
|
+
Symbol,
|
20
|
+
T::Array[T.untyped],
|
21
|
+
T::Hash[T.untyped, T.untyped]
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/m2m_keygen/version.rb
CHANGED
data/lib/m2m_keygen.rb
CHANGED
data/m2m_keygen.gemspec
CHANGED
@@ -20,6 +20,9 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.metadata[
|
21
21
|
"changelog_uri"
|
22
22
|
] = "https://github.com/Billcorporate/m2m_keygen_ruby/blob/main/CHANGELOG.md"
|
23
|
+
spec.metadata[
|
24
|
+
"documentation_uri"
|
25
|
+
] = "https://billcorporate.github.io/m2m_keygen_ruby"
|
23
26
|
spec.metadata = { "rubygems_mfa_required" => "true" }
|
24
27
|
|
25
28
|
# Specify which files should be added to the gem when it is released.
|
@@ -38,6 +41,7 @@ Gem::Specification.new do |spec|
|
|
38
41
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
39
42
|
spec.require_paths = ["lib"]
|
40
43
|
|
44
|
+
spec.add_dependency "rack"
|
41
45
|
spec.add_dependency "sorbet-runtime"
|
42
46
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
43
47
|
end
|
@@ -1534,6 +1534,30 @@ class ActiveSupport::Cache::Strategy::LocalCache::LocalStore
|
|
1534
1534
|
def write_entry(key, entry); end
|
1535
1535
|
end
|
1536
1536
|
|
1537
|
+
# --
|
1538
|
+
# This class wraps up local storage for middlewares. Only the middleware method should
|
1539
|
+
# construct them.
|
1540
|
+
#
|
1541
|
+
# source://activesupport-7.0.3.1/lib/active_support/cache/strategy/local_cache_middleware.rb:13
|
1542
|
+
class ActiveSupport::Cache::Strategy::LocalCache::Middleware
|
1543
|
+
# @return [Middleware] a new instance of Middleware
|
1544
|
+
#
|
1545
|
+
# source://activesupport-7.0.3.1/lib/active_support/cache/strategy/local_cache_middleware.rb:16
|
1546
|
+
def initialize(name, local_cache_key); end
|
1547
|
+
|
1548
|
+
# source://activesupport-7.0.3.1/lib/active_support/cache/strategy/local_cache_middleware.rb:27
|
1549
|
+
def call(env); end
|
1550
|
+
|
1551
|
+
# source://activesupport-7.0.3.1/lib/active_support/cache/strategy/local_cache_middleware.rb:14
|
1552
|
+
def local_cache_key; end
|
1553
|
+
|
1554
|
+
# source://activesupport-7.0.3.1/lib/active_support/cache/strategy/local_cache_middleware.rb:14
|
1555
|
+
def name; end
|
1556
|
+
|
1557
|
+
# source://activesupport-7.0.3.1/lib/active_support/cache/strategy/local_cache_middleware.rb:22
|
1558
|
+
def new(app); end
|
1559
|
+
end
|
1560
|
+
|
1537
1561
|
# These options mean something to all cache implementations. Individual cache
|
1538
1562
|
# implementations may support additional options.
|
1539
1563
|
#
|