sha256_seal 0.1.1 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +21 -0
  3. data/README.md +128 -0
  4. data/lib/sha256_seal.rb +41 -0
  5. metadata +96 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e3e09eef3a4f9a606b9ec60aee62845cb3b9ffd1236c6f5d193ee0a5c5c7da6
4
- data.tar.gz: c5b286a0a144c921aaa231770615dbe3d99fd2c04f9498f64813fdd2a2ad7fdc
3
+ metadata.gz: 315fdea0ce5a82dd8d67b01d083282acee522f691cc3f0aa9b1325efb3ee0866
4
+ data.tar.gz: a261366546c346d3e24e3ac1eae6d2d54ef7f01ed54a1fa157d2977c2e60bf92
5
5
  SHA512:
6
- metadata.gz: 4185f71aa478d32065ef07655181289d41283b63c5a422725c7b5d2a99baca033d39b802d55e46e32efd006b9cfc8313e3cbf34bb89b8e22cea797e80ecd3d4f
7
- data.tar.gz: 9afde2db8ccc907ebb7b1f477ab04efb49796e5d265556e77dc5e208bce9ce204943572555cd7bd59a520b896fab829435d512cf8c6d6992d50ef63976bee3cb
6
+ metadata.gz: ab1a96fb6978c03e74d0648bcc4c9c79c272ad8ee91ae11794f179c401ce61e0a9414436f22b3195e929fc4580f7dbff5324dc02eecb7b6e6da9270fb850a6f5
7
+ data.tar.gz: 7a8cdedec7048247f4600cbaa9d84f3060223f45632eb0bd07111fbc19458a37212ea94df3cc7f973d26d6a3e4764e7425e542a4a55a7ba898f0dfe02dd58c05
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017-2021 Cyril Kato
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # Sha256 Seal 🔏
2
+
3
+ A tiny library to sign documents, and check their integrity.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem "sha256_seal"
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install sha256_seal
20
+
21
+ ## Usage
22
+
23
+ Sign values and verify signatures of values.
24
+
25
+ ## Example
26
+
27
+ In the context of a Web application, CSRF tokens could be embedded in URLs.
28
+
29
+ ```ruby
30
+ SECRET = "secret".freeze
31
+
32
+ document_string = "/.__SIGNATURE_HERE__/accounts/42?editable=false"
33
+ signature_field = "__SIGNATURE_HERE__"
34
+
35
+ builder = Sha256Seal::Builder.new(document_string, SECRET, signature_field)
36
+ builder.signed_value? # => false
37
+ builder.signed_value # => "/.a31c3936f236684a8ebc51dcfef168ce124450d71ae1ec404552ec9e0090a8db/accounts/42?editable=false"
38
+
39
+ document_string = "/.a31c3936f236684a8ebc51dcfef168ce124450d71ae1ec404552ec9e0090a8db/accounts/42?editable=false"
40
+ signature_field = "a31c3936f236684a8ebc51dcfef168ce124450d71ae1ec404552ec9e0090a8db"
41
+
42
+ builder = Sha256Seal::Builder.new(document_string, SECRET, signature_field)
43
+ builder.signed_value? # => true
44
+ builder.signed_value # => "/.a31c3936f236684a8ebc51dcfef168ce124450d71ae1ec404552ec9e0090a8db/accounts/42?editable=false"
45
+
46
+ document_string = "/.a31c3936f236684a8ebc51dcfef168ce124450d71ae1ec404552ec9e0090a8db/accounts/42?editable=true"
47
+ signature_field = "a31c3936f236684a8ebc51dcfef168ce124450d71ae1ec404552ec9e0090a8db"
48
+
49
+ builder = Sha256Seal::Builder.new(document_string, SECRET, signature_field)
50
+ builder.signed_value? # => false
51
+ builder.signed_value # => "/.babd3a90b6bc2a4c0c7536a0c4804e5430a5a6df27d223c0f0102edb231de590/accounts/42?editable=true"
52
+ ```
53
+
54
+ ### Rails integration example
55
+
56
+ Environment variable:
57
+
58
+ ```txt
59
+ CSRF_SECRET_KEY=secret
60
+ ```
61
+
62
+ Route:
63
+
64
+ ```ruby
65
+ # config/routes.rb
66
+ Rails.application.routes.draw do
67
+ scope module: :verified_requests, path: ".:csrf", as: "verified_request" do
68
+ get "/accounts/:id", to: "accounts#show", as: "account"
69
+ end
70
+ end
71
+ ```
72
+
73
+ Controller:
74
+
75
+ ```ruby
76
+ # app/controllers/verified_requests/base_controller.rb
77
+ module VerifiedRequests
78
+ class BaseController < ApplicationController
79
+ # @see https://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html#method-i-verified_request-3F
80
+ def verified_request?
81
+ secret = ENV.fetch("CSRF_SECRET_KEY")
82
+ document_string = request.original_url.force_encoding("utf-8")
83
+ signature_field = request.path_parameters.fetch(:csrf)
84
+
85
+ builder = Sha256Seal::Builder.new(document_string, secret, signature_field)
86
+ builder.signed_value? || Rails.env.test?
87
+ end
88
+
89
+ def signed_url(route_method, **options)
90
+ url_route_method = "#{route_method}_url".to_sym
91
+ incorrect_csrf = "__CSRF_SECRET_KEY__"
92
+ url_route_string = public_send(url_route_method, csrf: incorrect_csrf, **options)
93
+
94
+ replace_incorrect_csrf_by_correct_csrf(url_route_string, incorrect_csrf: incorrect_csrf)
95
+ end
96
+ helper_method :signed_url
97
+
98
+ def replace_incorrect_csrf_by_correct_csrf(value, incorrect_csrf:)
99
+ secret = ENV.fetch("CSRF_SECRET_KEY")
100
+ field = incorrect_csrf
101
+ builder = Sha256Seal::Builder.new(value, secret, field)
102
+ value = builder.signed_value
103
+ field = builder.send(:signature)
104
+ builder = Sha256Seal::Builder.new(value, secret, field)
105
+
106
+ builder.signed_value
107
+ end
108
+ end
109
+ end
110
+ ```
111
+
112
+ View:
113
+
114
+ ```erb
115
+ # app/views/verified_requests/accounts/show.html.erb
116
+
117
+ <%
118
+ signed_url(:verified_request_account, id: 'bob', admin: true) # => "http://0.0.0.0:5000/.405d7c8f14389c9ae7f1d97ff66699093bf2d89d13b4f4280a35d62f9e616259/accounts/bob?admin=true"
119
+ %>
120
+ ```
121
+
122
+ ## Versioning
123
+
124
+ __Sha256Seal__ uses [Semantic Versioning 2.0.0](https://semver.org/)
125
+
126
+ ## License
127
+
128
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/sha2"
4
+
5
+ # Namespace for the Sha256Seal library.
6
+ module Sha256Seal
7
+ # Main class for the Sha256Seal library.
8
+ class Builder
9
+ attr_reader :value, :secret, :field
10
+
11
+ def initialize(value, secret, field)
12
+ @value = value.to_s
13
+ @secret = secret.to_s
14
+ @field = field.to_s
15
+
16
+ i = @value.scan(@field).length
17
+
18
+ return if i.equal?(1)
19
+
20
+ raise ::ArgumentError, "#{i} #{@field.inspect} occurrences instead of 1."
21
+ end
22
+
23
+ def signed_value
24
+ value.gsub(field, signature)
25
+ end
26
+
27
+ def signed_value?
28
+ signature.eql?(field)
29
+ end
30
+
31
+ private
32
+
33
+ def signature
34
+ ::Digest::SHA256.hexdigest(salt_value)
35
+ end
36
+
37
+ def salt_value
38
+ value.gsub(field, secret)
39
+ end
40
+ end
41
+ end
metadata CHANGED
@@ -1,111 +1,169 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sha256_seal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-03 00:00:00.000000000 Z
11
+ date: 2021-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.16'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.16'
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: fix
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0.beta4
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.0.beta4
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - "~>"
45
+ - - ">="
32
46
  - !ruby/object:Gem::Version
33
- version: '12.3'
47
+ version: '0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - "~>"
52
+ - - ">="
39
53
  - !ruby/object:Gem::Version
40
- version: '12.3'
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: yard
56
+ name: rubocop-md
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - "~>"
59
+ - - ">="
46
60
  - !ruby/object:Gem::Version
47
- version: '0.9'
61
+ version: '0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - "~>"
66
+ - - ">="
53
67
  - !ruby/object:Gem::Version
54
- version: '0.9'
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: simplecov
70
+ name: rubocop-performance
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - "~>"
73
+ - - ">="
60
74
  - !ruby/object:Gem::Version
61
- version: '0.15'
75
+ version: '0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - "~>"
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
- version: '0.15'
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
- name: rubocop
84
+ name: rubocop-rake
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - "~>"
87
+ - - ">="
74
88
  - !ruby/object:Gem::Version
75
- version: '0.52'
89
+ version: '0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - "~>"
94
+ - - ">="
81
95
  - !ruby/object:Gem::Version
82
- version: '0.52'
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
- name: fix
98
+ name: rubocop-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-thread_safety
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
- - - "~>"
115
+ - - ">="
88
116
  - !ruby/object:Gem::Version
89
- version: '0.17'
117
+ version: '0'
90
118
  type: :development
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
93
121
  requirements:
94
- - - "~>"
122
+ - - ">="
95
123
  - !ruby/object:Gem::Version
96
- version: '0.17'
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
97
153
  description: Seal device with SHA-256 hash function, for Ruby.
98
- email:
99
- - contact@cyril.email
154
+ email: contact@cyril.email
100
155
  executables: []
101
156
  extensions: []
102
157
  extra_rdoc_files: []
103
- files: []
158
+ files:
159
+ - LICENSE.md
160
+ - README.md
161
+ - lib/sha256_seal.rb
104
162
  homepage: https://github.com/cyril/sha256_seal.rb
105
163
  licenses:
106
164
  - MIT
107
165
  metadata: {}
108
- post_install_message:
166
+ post_install_message:
109
167
  rdoc_options: []
110
168
  require_paths:
111
169
  - lib
@@ -113,16 +171,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
171
  requirements:
114
172
  - - ">="
115
173
  - !ruby/object:Gem::Version
116
- version: '0'
174
+ version: '3.0'
117
175
  required_rubygems_version: !ruby/object:Gem::Requirement
118
176
  requirements:
119
177
  - - ">="
120
178
  - !ruby/object:Gem::Version
121
179
  version: '0'
122
180
  requirements: []
123
- rubyforge_project:
124
- rubygems_version: 2.7.3
125
- signing_key:
181
+ rubygems_version: 3.2.15
182
+ signing_key:
126
183
  specification_version: 4
127
184
  summary: Seal device with SHA-256 hash function.
128
185
  test_files: []