encoded_token 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 94f6aff78bcde0cd3cd00402ebf39c4ae1967529448e3d3f821329ad2e469e52
4
+ data.tar.gz: 34a07e6096e29a16c13adc2e59add378174d8b43796959d76b0e46e38028ebd8
5
+ SHA512:
6
+ metadata.gz: bffcc7452c6b6edbb1c4e82da354a925c5804583579e537344260c7b1d0f8145a9fd171adc676982a0dc808cf52f3195cb8b6036c9847b2893438d48a864d462
7
+ data.tar.gz: 054e5e5e05415062b40404a5ef0bd231d393840c30169375f6de1257b652b242315b234a14715dad933c3bca584a8ddfeecba070461c28539116e5b239427e2a
@@ -0,0 +1,280 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # EncodedToken::Base
5
+ #
6
+ # The core configuration settings used for encoding and decoding, along
7
+ # with the methods for initialization and verification.
8
+ #
9
+ # Encoding is achived though a variation of Alberti's cipher for
10
+ # multiple Ciphertext Alphabets.
11
+ # (https://en.wikipedia.org/wiki/Alberti_cipher
12
+ #
13
+ class EncodedToken
14
+ module Base
15
+
16
+ # ======================================================================
17
+ # Configuration
18
+ # ======================================================================
19
+
20
+ HEX_NUMS = ('0'..'9').to_a
21
+ HEX_CHARS = ('a'..'f').to_a + ('A'..'F').to_a
22
+ SPECIAL_CHARS = ['-']
23
+ HEX_TEXT = (HEX_NUMS + HEX_CHARS + SPECIAL_CHARS).join # :nodoc:
24
+
25
+ CIPHER_CHARS = ('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a
26
+ CIPHER_TEXT = CIPHER_CHARS.join # :nodoc:
27
+ CIPHER_COUNT = 16 # :nodoc:
28
+ TARGET_SIZE = 55 # :nodoc:
29
+
30
+ private_constant :HEX_NUMS, :HEX_CHARS, :SPECIAL_CHARS, :CIPHER_CHARS
31
+
32
+ @@seed = nil
33
+ @@ciphers = nil
34
+ @@keylist = nil
35
+
36
+
37
+
38
+ # ======================================================================
39
+ # Public Methods
40
+ # ======================================================================
41
+
42
+ ##
43
+ # Sets the seed to be used in generating a random encoding
44
+ #
45
+ # [returns:]
46
+ # - true on success
47
+ #
48
+ # [on error:]
49
+ # - raises an exception
50
+ #
51
+ def seed=(new_seed)
52
+ if @@seed
53
+ fail_with_seed_already_set
54
+ else
55
+ @@seed = parse_seed(new_seed)
56
+ generate_ciphers
57
+ return true
58
+ end
59
+ end
60
+
61
+
62
+
63
+ # ======================================================================
64
+ # Class Private Methods
65
+ # ======================================================================
66
+ private
67
+
68
+
69
+ # parse the new seed to ensure it is an integer
70
+ #
71
+ # return the Integer seed on success, otherwise raises an error
72
+ #
73
+ def parse_seed(new_seed)
74
+ if valid_integer?(new_seed)
75
+ return new_seed.to_i.abs
76
+ else
77
+ fail_with_invalid_seed_argument
78
+ end
79
+ end
80
+
81
+
82
+
83
+ # Generate a set of ciphers
84
+ #
85
+ # returns - a Hash of ciphers with a CIPHER_CHARS character for each key
86
+ #
87
+ def generate_ciphers
88
+ ciphers = {}
89
+ random = Random.new(__seed)
90
+ keys = CIPHER_CHARS.sample(__cipher_count, random: random).sort_by(&:downcase)
91
+ @@keylist = keys
92
+
93
+ # for each key, add a hash of the padding chareacter count
94
+ # and a cipher string to be used for encryption, using a different seed each time
95
+ keys.each_with_index do |key, idx|
96
+ ciphers[key] = {
97
+ padding: random.rand(0..10),
98
+ cipher_text: CIPHER_CHARS.sample(HEX_TEXT.size, random: random).join
99
+ }
100
+ end
101
+
102
+ @@ciphers = ciphers
103
+ end
104
+
105
+
106
+
107
+ # return the next cypher key after the given key, looping to the first when required
108
+ def rotate_cipher_key(key)
109
+ idx = __keylist.index(key) + 1
110
+ __keylist[idx] || __keylist.first
111
+ end
112
+
113
+
114
+
115
+ # Validity
116
+ # ======================================================================
117
+
118
+ # checks if the seed had been set
119
+ # - returns true if the seed is set
120
+ # - set the seed if missing and a valid ENV['ENCODED_TOKEN_SEED'] is present
121
+ #
122
+ def assert_valid_seed!
123
+ case
124
+ when !!@@seed
125
+ true
126
+
127
+ when !!ENV['ENCODED_TOKEN_SEED']
128
+ assert_valid_env!
129
+ self.seed = ENV['ENCODED_TOKEN_SEED'].to_i
130
+
131
+ else
132
+ fail RuntimeError, "Encryption seed must be set before using EncodedToken."\
133
+ " Set the seed with EncodedToken.seed=(xxx)."
134
+ end
135
+ end
136
+
137
+
138
+
139
+ # check ENV['ENCODED_TOKEN_SEED'] is a string integer
140
+ def assert_valid_env!
141
+ begin
142
+ if valid_integer?(ENV['ENCODED_TOKEN_SEED'])
143
+ return true
144
+ else
145
+ fail
146
+ end
147
+ rescue
148
+ fail RuntimeError, "ENV['ENCODED_TOKEN_SEED'] must be a string encoded Integer."
149
+ end
150
+ end
151
+
152
+
153
+
154
+ # Return true if the given String only contains hex text
155
+ def valid_hex_text?(val)
156
+ (val.chars - __hex_text.chars).empty?
157
+ end
158
+
159
+
160
+
161
+ # returns true if the given id is is an integer, else false
162
+ #
163
+ # id - and Inetger or String
164
+ #
165
+ def valid_integer?(id)
166
+ sid = id.to_s
167
+ sid.to_i.to_s == sid
168
+ rescue
169
+ false
170
+ end
171
+
172
+
173
+
174
+ # Return true if the given String only contains cipher text text
175
+ def valid_token_text?(val)
176
+ (val.chars - __cipher_text.chars).empty?
177
+ end
178
+
179
+
180
+
181
+ # returns true if the given id is a UUID, else false
182
+ #
183
+ # id - String uuid
184
+ #
185
+ def valid_uuid_format?(id)
186
+ uuid_regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
187
+ uuid_regex.match?(id.downcase)
188
+ rescue
189
+ false
190
+ end
191
+
192
+
193
+
194
+ # Configuration Attributes
195
+ # ======================================================================
196
+
197
+ # return the number of ciphers
198
+ def __cipher_count
199
+ CIPHER_COUNT
200
+ end
201
+
202
+
203
+
204
+ # return the cipher keylist
205
+ def __keylist
206
+ @@keylist
207
+ end
208
+
209
+
210
+
211
+ # return the constant cypher text
212
+ def __cipher_text
213
+ CIPHER_TEXT
214
+ end
215
+
216
+
217
+
218
+ # return the base ciphers hash
219
+ def __ciphers
220
+ @@ciphers
221
+ end
222
+
223
+
224
+
225
+ # return the constant hex text
226
+ def __hex_text
227
+ HEX_TEXT
228
+ end
229
+
230
+
231
+
232
+ # return seed
233
+ def __seed
234
+ @@seed
235
+ end
236
+
237
+
238
+
239
+ # return the target size
240
+ def __target_size
241
+ TARGET_SIZE
242
+ end
243
+
244
+
245
+
246
+ # Error Messages
247
+ # ======================================================================
248
+
249
+ # error: invalid ID supplied
250
+ def fail_with_invalid_id_argument
251
+ fail_with ArgumentError,
252
+ ":id must be an Integer, a String integer or a String UUID."
253
+ end
254
+
255
+
256
+
257
+ # error: Seed is already set
258
+ def fail_with_seed_already_set
259
+ fail_with ArgumentError,
260
+ "EncodedToken seed has alreay been set to #{@@seed}."
261
+ end
262
+
263
+
264
+
265
+ # error: invalid Seed supplied
266
+ def fail_with_invalid_seed_argument
267
+ fail_with ArgumentError,
268
+ ":seed must be an Integer, preferably with at least 5 digits."
269
+ end
270
+
271
+
272
+
273
+ # default error message header
274
+ def fail_with(error_klass, message)
275
+ fail error_klass, "\n\nERROR :=> EncodedToken: #{message}\n\n"
276
+ end
277
+
278
+
279
+ end #module
280
+ end #class
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # EncodedToken::Encoder
5
+ #
6
+ # The methods required to decode a token.
7
+ #
8
+ class EncodedToken # :nodoc:
9
+ module Decoder
10
+
11
+ # ======================================================================
12
+ # Public Methods
13
+ # ======================================================================
14
+
15
+ ##
16
+ # Decode a previously encoded token to return the original ID
17
+ #
18
+ # [args:]
19
+ # - *token* [String]
20
+ #
21
+ # [returns:]
22
+ # - a String with the original ID
23
+ #
24
+ # [on error:]
25
+ # - an invalid String token returns +nil+
26
+ # - otherwise an exception will be raised
27
+ #
28
+ # *examples:*
29
+ #
30
+ # EncodedToken.decode!("KY3bnaRGmyy6yJS3imWr1dcWtzDYvZjpIAYyCUo5PEKPFvQgtTTed")
31
+ # #=> "12345"
32
+ #
33
+ # EncodedToken.decode!("3gDwO7r4UJYeBYDBLU94MqjZQm0SToSE29ACDNcw0xf4QusZKxQHJ")
34
+ # #=> "12345"
35
+ #
36
+ # EncodedToken.decode!("pAi1SmpKgFAchh76EoLbYLeXVQmLwmMlH2v1zDVeufioKGr0709Qw")
37
+ # #=> "468a5eeb-0cda-4c99-8dba-6a96c33003e0"
38
+ #
39
+ # EncodedToken.decode!("abcdefghijklmnopqrstuvwxyz")
40
+ # #=> nil
41
+ #
42
+ # EncodedToken.decode!(:test)
43
+ # #=> Token is not a string. (RuntimeError)
44
+ #
45
+ def decode!(token)
46
+ assert_valid_seed!
47
+
48
+ token = sanitize_token(token)
49
+ id = parse_token(token)
50
+
51
+ # is it a UUID or numeric ID
52
+ if valid_integer?(id) || valid_uuid_format?(id)
53
+ return id
54
+ else
55
+ return nil
56
+ end
57
+ end
58
+
59
+
60
+
61
+ ##
62
+ # Decode a previously encoded token to return the original ID
63
+ #
64
+ # [args:]
65
+ # - *token* [String]
66
+ #
67
+ # [returns:]
68
+ # - a String with the original ID
69
+ #
70
+ # [on error:]
71
+ # - returns +nil+
72
+ #
73
+ # *examples:*
74
+ #
75
+ # EncodedToken.decode("KY3bnaRGmyy6yJS3imWr1dcWtzDYvZjpIAYyCUo5PEKPFvQgtTTed")
76
+ # #=> "12345"
77
+ #
78
+ # EncodedToken.decode("3gDwO7r4UJYeBYDBLU94MqjZQm0SToSE29ACDNcw0xf4QusZKxQHJ")
79
+ # #=> "12345"
80
+ #
81
+ # EncodedToken.decode("pAi1SmpKgFAchh76EoLbYLeXVQmLwmMlH2v1zDVeufioKGr0709Qw")
82
+ # #=> "4ef2091f-023b-4af6-9e9f-f46465f897ba"
83
+ #
84
+ # EncodedToken.decode("abcdefghijklmnopqrstuvwxyz")
85
+ # #=> nil
86
+ #
87
+ # EncodedToken.decode(:test)
88
+ # #=> nil
89
+ #
90
+ def decode(id)
91
+ decode!(id)
92
+ rescue
93
+ nil
94
+ end
95
+
96
+
97
+ # ======================================================================
98
+ # Private Methods
99
+ # ======================================================================
100
+ #
101
+ private
102
+
103
+
104
+ # ensures the given token is valid to decode
105
+ #
106
+ # token [String] - a properly encoded String
107
+ #
108
+ # returns - a String duplicate of the given token
109
+ #
110
+ # on error: - a RuntimeError is raised
111
+ #
112
+ # NOTE: - we return a duplicate so the original is not changed later
113
+ # in the process when shifting segments
114
+ #
115
+ def sanitize_token(token)
116
+ fail 'Token is not a string.' unless token.is_a?(String)
117
+ fail 'Invalid token characters' unless valid_token_text?(token)
118
+ fail 'Invalid token cipher.' unless __keylist.include?(token[0])
119
+ token.dup
120
+ end
121
+
122
+
123
+
124
+ # Parses the token to retrieve the original ID
125
+ #
126
+ # token [String] - the encoded token
127
+ #
128
+ # returns [String] - the original ID
129
+ #
130
+ def parse_token(token)
131
+ key = token[0]
132
+ id_size = decrypt_size(token[1,2], key)
133
+ padding = __ciphers[key][:padding]
134
+ enc_id = token[padding + 3, id_size]
135
+
136
+ return decrypt(enc_id, key)
137
+ end
138
+
139
+
140
+
141
+ # returns the Integer size of the id
142
+ #
143
+ # enc_size - the encrypted ID
144
+ # key - the cipher key to use
145
+ #
146
+ def decrypt_size(enc_size, key)
147
+ decrypt(enc_size, key).hex
148
+ end
149
+
150
+
151
+
152
+ # decrypt the id using the cipher text from the given key.
153
+ # - rotate the cipher every character
154
+ #
155
+ # enc_id - encoded String ID
156
+ # key - base cipher key to use
157
+ #
158
+ # on error - rasies an exception (invalid cipher chars, etc)
159
+ #
160
+ def decrypt(enc_id, key)
161
+ id = ""
162
+ enc_key = key
163
+
164
+ enc_id.each_char do |char|
165
+ enc_key = rotate_cipher_key(enc_key)
166
+ cipher_text = __ciphers[enc_key][:cipher_text]
167
+
168
+ id += __hex_text[cipher_text.index(char)]
169
+ end
170
+
171
+ return id
172
+ rescue
173
+ fail 'Invalid token characters'
174
+ end
175
+
176
+ end #module
177
+ end #class
178
+
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # EncodedToken::Encoder
5
+ #
6
+ # The methods required to encode a token with an Integer ID or String UUID.
7
+ #
8
+ class EncodedToken # :nodoc:
9
+ module Encoder
10
+
11
+ # Public Methods
12
+ # ======================================================================
13
+
14
+ ##
15
+ # Generates a Secure Token from the given ID
16
+ #
17
+ # [args:]
18
+ # - *id* [Integer, String] - the ID or UUID to encode
19
+ # - eg. 12345, "12345", "468a5eeb-0cda-4c99-8dba-6a96c33003e0"
20
+ #
21
+ # [returns:]
22
+ # - a web-safe, variable length String of alphanumeric characters
23
+ #
24
+ # [on error:]
25
+ # - raises an exception based on the error
26
+ #
27
+ # *examples:*
28
+ #
29
+ # EncodedToken.encode!(12345)
30
+ # # => "KY3bnaRGmyy6yJS3imWr1dcWtzDYvZjpIAYyCUo5PEKPFvQgtTTed"
31
+ #
32
+ # EncodedToken.encode!("12345")
33
+ # # => "3gDwO7r4UJYeBYDBLU94MqjZQm0SToSE29ACDNcw0xf4QusZKxQHJ"
34
+ #
35
+ # EncodedToken.encode!("468a5eeb-0cda-4c99-8dba-6a96c33003e0")
36
+ # # => "pAi1SmpKgFAchh76EoLbYLeXVQmLwmMlH2v1zDVeufioKGr0709Qw"
37
+ #
38
+ # EncodedToken.encode!(:test)
39
+ # # => EncodedToken: :id must be an Integer, a String integer or a String UUID. (RuntimeError)
40
+ #
41
+ def encode!(id)
42
+ assert_valid_seed!
43
+ assert_valid_id!(id)
44
+ generate_token(id)
45
+ end
46
+
47
+
48
+
49
+ ##
50
+ # Generates a Secure Token from the given ID
51
+ #
52
+ # [args:]
53
+ # - *id* [Integer, String] - the ID or UUID to encode
54
+ # - eg. 12345, "12345", "468a5eeb-0cda-4c99-8dba-6a96c33003e0"
55
+ #
56
+ # [returns:]
57
+ # - a web-safe, variable length String of alphanumeric characters
58
+ #
59
+ # [on error:]
60
+ # - raises an ArgumentError
61
+ #
62
+ # *examples:*
63
+ #
64
+ # EncodedToken.encode(12345)
65
+ # # => "KY3bnaRGmyy6yJS3imWr1dcWtzDYvZjpIAYyCUo5PEKPFvQgtTTed"
66
+ #
67
+ # EncodedToken.encode("12345")
68
+ # # => "3gDwO7r4UJYeBYDBLU94MqjZQm0SToSE29ACDNcw0xf4QusZKxQHJ"
69
+ #
70
+ # EncodedToken.encode("468a5eeb-0cda-4c99-8dba-6a96c33003e0")
71
+ # # => "pAi1SmpKgFAchh76EoLbYLeXVQmLwmMlH2v1zDVeufioKGr0709Qw"
72
+ #
73
+ # EncodedToken.encode(:test)
74
+ # # => EncodedToken: :id must be an Integer, a String integer or a String UUID. (RuntimeError)
75
+ #
76
+ #
77
+ def encode(id)
78
+ encode!(id)
79
+ rescue ArgumentError
80
+ fail_with_invalid_id_argument
81
+ end
82
+
83
+
84
+
85
+ # ======================================================================
86
+ # Class Private Methods
87
+ # ======================================================================
88
+ #
89
+ private
90
+
91
+
92
+
93
+ # ensures the given ID is valid to encode
94
+ #
95
+ # id - an Integer, numerical String integer or UUID
96
+ # - max size of 255 characters
97
+ # - contain only hex charatacters + '-'
98
+ #
99
+ # returns - true if valid
100
+ #
101
+ # on error: - an ArgumentError is raised
102
+ #
103
+ def assert_valid_id!(id)
104
+ sid = id.to_s
105
+
106
+ fail if sid.size < 1
107
+ fail if sid.size > 255
108
+ fail unless valid_hex_text?(sid)
109
+ fail unless valid_integer?(id) || valid_uuid_format?(id)
110
+
111
+ return true
112
+
113
+ rescue
114
+ fail_with_invalid_id_argument
115
+ end
116
+
117
+
118
+
119
+ # generates the token
120
+ #
121
+ # id - Integer, String integer or String UUID
122
+ #
123
+ # returns - an alphanumeric String token
124
+ #
125
+ # Note - token comprises [key, id_size, left_padding, enc_id, right_padding]
126
+ #
127
+ def generate_token(id)
128
+ # stringify the id
129
+ sid = id.to_s
130
+
131
+ # select a random cipher key
132
+ token = key = __keylist.sample
133
+
134
+ # encrypt the id size
135
+ token += encrypt_size(sid, key)
136
+
137
+ # generate the left padding
138
+ token += random_characters(__ciphers[key][:padding])
139
+
140
+ # encrypt the id
141
+ token += encrypt(sid, key)
142
+
143
+ # generate right padding
144
+ count = (__target_size - token.size).clamp(0, __target_size)
145
+ token += random_characters(count)
146
+
147
+ # return the new token
148
+ return token
149
+ end
150
+
151
+
152
+
153
+ # return the encrypted size of the id
154
+ #
155
+ # returns a 2-character String
156
+ #
157
+ # note - we convert to hex to allow for strings up to 255 chars
158
+ #
159
+ def encrypt_size(id, key)
160
+ hex_size = id.size.to_s(16).rjust(2, '0')
161
+
162
+ encrypt(hex_size, key)
163
+ end
164
+
165
+
166
+
167
+ # encrypt the id using the cipher text from the given key.
168
+ # - rotate the cipher every character to avoid sequential valuies like id: 1000
169
+ #
170
+ def encrypt(id, key)
171
+ enc_id = []
172
+ encipher_key = key
173
+
174
+ id.to_s.each_char do |char|
175
+ encipher_key = rotate_cipher_key(encipher_key)
176
+ cipher_text = __ciphers[encipher_key][:cipher_text]
177
+
178
+ enc_id << cipher_text[__hex_text.index(char)]
179
+ end
180
+
181
+ return enc_id.join
182
+ end
183
+
184
+
185
+
186
+ # generate a String of alphanumeric characters ot the given size
187
+ #
188
+ def random_characters(size)
189
+ SecureRandom.alphanumeric(size)
190
+ end
191
+
192
+ end #module
193
+ end #class
194
+
195
+
196
+
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ ##
5
+ # EncodedToken version details
6
+ #
7
+ class EncodedToken # :nodoc:
8
+
9
+ ##
10
+ # The EncodedToken gem version.
11
+ #
12
+ # [returns:]
13
+ # - the version of the currently loaded EncodedToken as a <tt>Gem::Version</tt>
14
+ #
15
+ def self.gem_version
16
+ Gem::Version.new VERSION::STRING
17
+ end
18
+
19
+
20
+
21
+ module VERSION # :nodoc: all
22
+
23
+ MAJOR = 1
24
+ MINOR = 0
25
+ TINY = 2
26
+ # MICRO = ''
27
+
28
+ STRING = [MAJOR, MINOR, TINY].compact.join(".")
29
+ # STRING = [MAJOR, MINOR, TINY, MICRO].compact.join(".")
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # = EncodedToken
5
+ #
6
+ # Encodes a UUID or numeric ID to produce a Secure Token,
7
+ # then decodes the Secure Token to return the origianl ID.
8
+ #
9
+ # - The given ID is encoded using a substitution cipher, then padded
10
+ # with alphanumeric characters to a random length.
11
+ #
12
+ # - Multiple substituion ciphers are used to improve security.
13
+ #
14
+ # *examples:*
15
+ #
16
+ # EncodedToken.encode(12345)
17
+ # # => "b4ex6AEB62jlBGpVAGNou8iRmD7pnHGHafQlAHB7w0J"
18
+ #
19
+ # EncodedToken.decode("b4ex6AEB62jlBGpVAGNou8iRmD7pnHGHafQlAHB7w0J")
20
+ # # => "12345"
21
+ #
22
+ class EncodedToken
23
+
24
+
25
+ # ======================================================================
26
+ # Macros
27
+ # ======================================================================
28
+
29
+ require "securerandom"
30
+ require_relative "encoded_token/base.rb"
31
+ require_relative "encoded_token/encoder.rb"
32
+ require_relative "encoded_token/decoder.rb"
33
+
34
+ extend EncodedToken::Base
35
+ extend EncodedToken::Encoder
36
+ extend EncodedToken::Decoder
37
+
38
+
39
+ # ======================================================================
40
+ # Public Instance Methods
41
+ # ======================================================================
42
+
43
+ # This is an abstract class, so ensure no instantiation
44
+ def initialize # :nodoc:
45
+ raise NotImplementedError.new("SecureToken is an abstract class and cannot be instantiated.")
46
+ end
47
+
48
+ end #class
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: encoded_token
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - CodeMeister
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-10-05 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Stop hitting the DB with every secure-token submission. Encoded Tokens
14
+ have the ID, or UUID, encoded within the token itself - increasing both security
15
+ and performance. Coded in plain Ruby, EncodedToken is framework agnostic.
16
+ email: encoded_token@codemeister.dev
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/encoded_token.rb
22
+ - lib/encoded_token/base.rb
23
+ - lib/encoded_token/decoder.rb
24
+ - lib/encoded_token/encoder.rb
25
+ - lib/encoded_token/version.rb
26
+ homepage: https://github.com/Rubology/encoded_token
27
+ licenses:
28
+ - MIT
29
+ metadata:
30
+ homepage_uri: https://github.com/Rubology/encoded_token
31
+ source_code_uri: https://github.com/Rubology/encoded_token
32
+ changelog_uri: https://github.com/Rubology/encoded_token/blob/master/CHANGELOG.md
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 2.5.0
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubygems_version: 3.3.22
49
+ signing_key:
50
+ specification_version: 4
51
+ summary: A better, more secure and efficient way to manage secure-tokens - by encoding
52
+ the ID, or UUID, within the token itself.
53
+ test_files: []