altcha 0.1.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec9e3706caf746807ebb7349d3ab202eb6601b9fed628fe6b5176c5a81ef6118
4
- data.tar.gz: 6d6ddbb904cde1fed358bf6b36e11207c49604d0ecfed0646558c05f9d3e6ad0
3
+ metadata.gz: 26bd90d5f8f25ec3b565a8686fe424421326163149ce34e2fe94d9b335815394
4
+ data.tar.gz: d8a48c54a34721b77847b765c428b1068c1c6f611c4a133c5da6e77074c6e6c2
5
5
  SHA512:
6
- metadata.gz: feed3cad4fe038420c0e1701751d362408b64ef61e3fcb2d09640dcfef9b4566e2b486a3b3ddb8710ec5c4303948cc63eda072032797d5d1def90bd011b22a14
7
- data.tar.gz: cd3a752cdb06111293a949d31fcb5988080d69d779d9db735e2420d9fdf57e0bde82734c0fa38e253f7c46ef30ed16b2707cbe0f39cd664fd9a7fe2a41d2fa83
6
+ metadata.gz: 646c34c483cfbb68003e149b0ccf297d0b57072f6a1df6df3fbae555fd714a1a37dd3c8333e5dec61c024ef92655ba1983333b79984372775559291c2b635db0
7
+ data.tar.gz: 8670ab596f21009624bc1808fc7f952de9431df58a2752b5c2170d34fb8970d953550e35566bdfba7d383a27be09b17fbdecd6b4946becf7fd1b2eac49be98bf
data/.gitignore CHANGED
@@ -10,3 +10,5 @@
10
10
 
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
+
14
+ *.gem
data/Gemfile.lock CHANGED
@@ -1,25 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- altcha (0.1.0)
4
+ altcha (0.2.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- ast (2.4.2)
10
9
  diff-lcs (1.5.1)
11
- json (2.7.2)
12
- language_server-protocol (3.17.0.3)
13
- parallel (1.25.1)
14
- parser (3.3.4.0)
15
- ast (~> 2.4.1)
16
- racc
17
- racc (1.8.1)
18
- rainbow (3.1.1)
19
10
  rake (10.5.0)
20
- regexp_parser (2.9.2)
21
- rexml (3.3.4)
22
- strscan
23
11
  rspec (3.13.0)
24
12
  rspec-core (~> 3.13.0)
25
13
  rspec-expectations (~> 3.13.0)
@@ -33,22 +21,6 @@ GEM
33
21
  diff-lcs (>= 1.2.0, < 2.0)
34
22
  rspec-support (~> 3.13.0)
35
23
  rspec-support (3.13.1)
36
- rubocop (1.65.1)
37
- json (~> 2.3)
38
- language_server-protocol (>= 3.17.0)
39
- parallel (~> 1.10)
40
- parser (>= 3.3.0.2)
41
- rainbow (>= 2.2.2, < 4.0)
42
- regexp_parser (>= 2.4, < 3.0)
43
- rexml (>= 3.2.5, < 4.0)
44
- rubocop-ast (>= 1.31.1, < 2.0)
45
- ruby-progressbar (~> 1.7)
46
- unicode-display_width (>= 2.4.0, < 3.0)
47
- rubocop-ast (1.31.3)
48
- parser (>= 3.3.1.0)
49
- ruby-progressbar (1.13.0)
50
- strscan (3.1.0)
51
- unicode-display_width (2.5.0)
52
24
 
53
25
  PLATFORMS
54
26
  arm64-darwin-23
@@ -59,7 +31,6 @@ DEPENDENCIES
59
31
  bundler (~> 2.5)
60
32
  rake (~> 10.0)
61
33
  rspec (~> 3.0)
62
- rubocop (~> 1.65)
63
34
 
64
35
  BUNDLED WITH
65
36
  2.5.11
data/README.md CHANGED
@@ -17,7 +17,7 @@ This library is compatible with:
17
17
  To install the ALTCHA Ruby Library, add it to your Gemfile:
18
18
 
19
19
  ```ruby
20
- gem 'altcha', git: 'https://github.com/altcha-org/altcha-lib-rb'
20
+ gem 'altcha'
21
21
  ```
22
22
 
23
23
  Then run:
@@ -42,10 +42,10 @@ require 'altcha'
42
42
  hmac_key = 'secret hmac key'
43
43
 
44
44
  # Create a new challenge
45
- options = Altcha::ChallengeOptions.new.tap do |opts|
46
- opts.hmac_key = hmac_key
47
- opts.max_number = 100000 # the maximum random number
48
- end
45
+ options = Altcha::ChallengeOptions.new(
46
+ hmac_key: hmac_key,
47
+ max_number: 100000 # the maximum random number
48
+ )
49
49
 
50
50
  challenge = Altcha.create_challenge(options)
51
51
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Altcha
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.1'
5
5
  end
data/lib/altcha.rb CHANGED
@@ -23,12 +23,31 @@ module Altcha
23
23
  # Class representing options for generating a challenge.
24
24
  class ChallengeOptions
25
25
  attr_accessor :algorithm, :max_number, :salt_length, :hmac_key, :salt, :number, :expires, :params
26
+
27
+ def initialize(algorithm: nil, max_number: nil, salt_length: nil, hmac_key:, salt: nil, number: nil, expires: nil, params: nil)
28
+ @algorithm = algorithm
29
+ @max_number = max_number
30
+ @salt_length = salt_length
31
+ @hmac_key = hmac_key
32
+ @salt = salt
33
+ @number = number
34
+ @expires = expires
35
+ @params = params
36
+ end
26
37
  end
27
38
 
28
39
  # Class representing a challenge with its attributes.
29
40
  class Challenge
30
41
  attr_accessor :algorithm, :challenge, :maxnumber, :salt, :signature
31
42
 
43
+ def initialize(algorithm:, challenge:, maxnumber: nil, salt:, signature:)
44
+ @algorithm = algorithm
45
+ @challenge = challenge
46
+ @maxnumber = maxnumber
47
+ @salt = salt
48
+ @signature = signature
49
+ end
50
+
32
51
  # Converts the Challenge object to a JSON string.
33
52
  # @param options [Hash] options to customize JSON encoding.
34
53
  # @return [String] JSON representation of the Challenge object.
@@ -41,20 +60,20 @@ module Altcha
41
60
  signature: @signature
42
61
  }.to_json(options)
43
62
  end
44
-
45
- # Creates a Challenge object from a JSON string.
46
- # @param string [String] JSON string to parse.
47
- # @return [Challenge] Parsed Challenge object.
48
- def from_json(string)
49
- data = JSON.parse(string)
50
- new data['algorithm'], data['challenge'], data['maxnumber'], data['salt'], data['signature']
51
- end
52
63
  end
53
64
 
54
65
  # Class representing the payload of a challenge.
55
66
  class Payload
56
67
  attr_accessor :algorithm, :challenge, :number, :salt, :signature
57
68
 
69
+ def initialize(algorithm:, challenge:, number:, salt:, signature:)
70
+ @algorithm = algorithm
71
+ @challenge = challenge
72
+ @number = number
73
+ @salt = salt
74
+ @signature = signature
75
+ end
76
+
58
77
  # Converts the Payload object to a JSON string.
59
78
  # @param options [Hash] options to customize JSON encoding.
60
79
  # @return [String] JSON representation of the Payload object.
@@ -71,9 +90,15 @@ module Altcha
71
90
  # Creates a Payload object from a JSON string.
72
91
  # @param string [String] JSON string to parse.
73
92
  # @return [Payload] Parsed Payload object.
74
- def from_json(string)
93
+ def self.from_json(string)
75
94
  data = JSON.parse(string)
76
- new data['algorithm'], data['verificationData'], data['signature'], data['verified']
95
+ new(
96
+ algorithm: data['algorithm'],
97
+ challenge: data['challenge'],
98
+ number: data['number'],
99
+ salt: data['salt'],
100
+ signature: data['signature']
101
+ )
77
102
  end
78
103
  end
79
104
 
@@ -81,6 +106,13 @@ module Altcha
81
106
  class ServerSignaturePayload
82
107
  attr_accessor :algorithm, :verification_data, :signature, :verified
83
108
 
109
+ def initialize(algorithm:, verification_data:, signature:, verified:)
110
+ @algorithm = algorithm
111
+ @verification_data = verification_data
112
+ @signature = signature
113
+ @verified = verified
114
+ end
115
+
84
116
  # Converts the ServerSignaturePayload object to a JSON string.
85
117
  # @param options [Hash] options to customize JSON encoding.
86
118
  # @return [String] JSON representation of the ServerSignaturePayload object.
@@ -96,9 +128,14 @@ module Altcha
96
128
  # Creates a ServerSignaturePayload object from a JSON string.
97
129
  # @param string [String] JSON string to parse.
98
130
  # @return [ServerSignaturePayload] Parsed ServerSignaturePayload object.
99
- def from_json(string)
131
+ def self.from_json(string)
100
132
  data = JSON.parse(string)
101
- new data['algorithm'], data['verificationData'], data['signature'], data['verified']
133
+ new(
134
+ algorithm: data['algorithm'],
135
+ verification_data: data['verificationData'],
136
+ signature: data['signature'],
137
+ verified: data['verified']
138
+ )
102
139
  end
103
140
  end
104
141
 
@@ -106,6 +143,26 @@ module Altcha
106
143
  class ServerSignatureVerificationData
107
144
  attr_accessor :classification, :country, :detected_language, :email, :expire, :fields, :fields_hash,
108
145
  :ip_address, :reasons, :score, :time, :verified
146
+
147
+ # Converts the ServerSignatureVerificationData object to a JSON string.
148
+ # @param options [Hash] options to customize JSON encoding.
149
+ # @return [String] JSON representation of the ServerSignatureVerificationData object.
150
+ def to_json(options = {})
151
+ {
152
+ classification: @classification,
153
+ country: @country,
154
+ detectedLanguage: @detected_language,
155
+ email: @email,
156
+ expire: @expire,
157
+ fields: @fields,
158
+ fieldsHash: @fields_hash,
159
+ ipAddress: @ip_address,
160
+ reasons: @reasons,
161
+ score: @score,
162
+ time: @time,
163
+ verified: @verified
164
+ }.to_json(options)
165
+ end
109
166
  end
110
167
 
111
168
  # Class representing the solution to a challenge.
@@ -204,13 +261,13 @@ module Altcha
204
261
  challenge = hash_hex(algorithm, challenge_str)
205
262
  signature = hmac_hex(algorithm, challenge, options.hmac_key)
206
263
 
207
- Challenge.new.tap do |c|
208
- c.algorithm = algorithm
209
- c.challenge = challenge
210
- c.maxnumber = max_number
211
- c.salt = salt
212
- c.signature = signature
213
- end
264
+ Challenge.new(
265
+ algorithm: algorithm,
266
+ challenge: challenge,
267
+ maxnumber: max_number,
268
+ salt: salt,
269
+ signature: signature,
270
+ )
214
271
  end
215
272
 
216
273
  # Verifies the solution provided by the client.
@@ -224,7 +281,17 @@ module Altcha
224
281
  # Decode and parse base64 JSON string if it's a String
225
282
  if payload.is_a?(String)
226
283
  decoded_payload = Base64.decode64(payload)
227
- payload = JSON.parse(decoded_payload, object_class: Payload)
284
+ payload = Payload.from_json(decoded_payload)
285
+
286
+ # Convert payload from hash to Payload if it's a plain object
287
+ elsif payload.is_a?(Hash)
288
+ payload = Payload.new(
289
+ algorithm: payload[:algorithm],
290
+ challenge: payload[:challenge],
291
+ number: payload[:number],
292
+ salt: payload[:salt],
293
+ signature: payload[:signature]
294
+ )
228
295
  end
229
296
 
230
297
  # Ensure payload is an instance of Payload
@@ -243,12 +310,12 @@ module Altcha
243
310
  end
244
311
 
245
312
  # Convert payload to ChallengeOptions
246
- challenge_options = ChallengeOptions.new.tap do |co|
247
- co.algorithm = payload.algorithm
248
- co.hmac_key = hmac_key
249
- co.number = payload.number
250
- co.salt = payload.salt
251
- end
313
+ challenge_options = ChallengeOptions.new(
314
+ algorithm: payload.algorithm,
315
+ hmac_key: hmac_key,
316
+ number: payload.number,
317
+ salt: payload.salt
318
+ )
252
319
 
253
320
  # Create expected challenge and compare with the provided payload
254
321
  expected_challenge = create_challenge(challenge_options)
@@ -272,7 +339,7 @@ module Altcha
272
339
  # @param algorithm [String] The hashing algorithm to use.
273
340
  # @return [Boolean] True if the fields hash matches, false otherwise.
274
341
  def self.verify_fields_hash(form_data, fields, fields_hash, algorithm)
275
- lines = fields.map { |field| form_data[field].to_a.first.to_s }
342
+ lines = fields.map { |field| form_data[field].to_s }
276
343
  joined_data = lines.join("\n")
277
344
  computed_hash = hash_hex(algorithm, joined_data)
278
345
  computed_hash == fields_hash
@@ -286,7 +353,16 @@ module Altcha
286
353
  # Decode and parse base64 JSON string if it's a String
287
354
  if payload.is_a?(String)
288
355
  decoded_payload = Base64.decode64(payload)
289
- payload = JSON.parse(decoded_payload, object_class: ServerSignaturePayload)
356
+ payload = ServerSignaturePayload.from_json(decoded_payload)
357
+
358
+ # Convert payload from hash to ServerSignaturePayload if it's a plain object
359
+ elsif payload.is_a?(Hash)
360
+ payload = ServerSignaturePayload.new(
361
+ algorithm: payload[:algorithm],
362
+ verification_data: payload[:verification_data],
363
+ signature: payload[:signature],
364
+ verified: payload[:verified]
365
+ )
290
366
  end
291
367
 
292
368
  # Ensure payload is an instance of ServerSignaturePayload
@@ -300,7 +376,7 @@ module Altcha
300
376
 
301
377
  hash_data = hash(payload.algorithm, payload.verification_data)
302
378
  expected_signature = hmac_hex(payload.algorithm, hash_data, hmac_key)
303
-
379
+
304
380
  params = URI.decode_www_form(payload.verification_data).to_h
305
381
  verification_data = ServerSignatureVerificationData.new.tap do |v|
306
382
  v.classification = params['classification'] || nil
@@ -309,6 +385,8 @@ module Altcha
309
385
  v.email = params['email'] || nil
310
386
  v.expire = params['expire'] ? params['expire'].to_i : nil
311
387
  v.fields = params['fields'] ? params['fields'].split(',') : nil
388
+ v.fields_hash = params['fieldsHash'] || nil
389
+ v.ip_address = params['ipAddress'] || nil
312
390
  v.reasons = params['reasons'] ? params['reasons'].split(',') : nil
313
391
  v.score = params['score'] ? params['score'].to_f : nil
314
392
  v.time = params['time'] ? params['time'].to_i : nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: altcha
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Regeci