altcha 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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