altcha 0.2.1 → 2.0.0.beta1

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: 26bd90d5f8f25ec3b565a8686fe424421326163149ce34e2fe94d9b335815394
4
- data.tar.gz: d8a48c54a34721b77847b765c428b1068c1c6f611c4a133c5da6e77074c6e6c2
3
+ metadata.gz: 86a8015b761012e385bf6b5756e3cc06ab6e0918efebcdc7fc244e029c200e69
4
+ data.tar.gz: 187c01c7e93e15676c755ec9105955447c048c2e2c0249a270a44e735ea41666
5
5
  SHA512:
6
- metadata.gz: 646c34c483cfbb68003e149b0ccf297d0b57072f6a1df6df3fbae555fd714a1a37dd3c8333e5dec61c024ef92655ba1983333b79984372775559291c2b635db0
7
- data.tar.gz: 8670ab596f21009624bc1808fc7f952de9431df58a2752b5c2170d34fb8970d953550e35566bdfba7d383a27be09b17fbdecd6b4946becf7fd1b2eac49be98bf
6
+ metadata.gz: 98e5fd75d6640ac91149c917bbc45e6bebe02fa03f1b0d0a201382675579ec8d6e2d8dcc85d17ef608833972b44dfc81df07e7f6f7964ce9da25cb1c47ef1530
7
+ data.tar.gz: 6daf6a061f5340a93c920ab6e2973b49979b77031c548845ad9a78fc363aed96e1f43e7de561b2f924b4401f5949c4356c1af1cda66a3e44d9ce693d23d1dc18
@@ -0,0 +1,24 @@
1
+ name: Publish gem
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+ environment: rubygems
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: '3.3'
22
+ bundler-cache: true
23
+
24
+ - uses: rubygems/release-gem@v1
@@ -0,0 +1,128 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity
10
+ and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the
26
+ overall community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or
31
+ advances of any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email
35
+ address, without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ GitHub Issues.
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series
86
+ of actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or
93
+ permanent ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within
113
+ the community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.0, available at
119
+ https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120
+
121
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct
122
+ enforcement ladder](https://github.com/mozilla/diversity).
123
+
124
+ [homepage]: https://www.contributor-covenant.org
125
+
126
+ For answers to common questions about this code of conduct, see the FAQ at
127
+ https://www.contributor-covenant.org/faq. Translations are available at
128
+ https://www.contributor-covenant.org/translations.
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,36 @@
1
+ # Contributing to ALTCHA
2
+
3
+ We appreciate your contributions! To ensure a smooth and transparent collaboration, we've outlined the various ways you can contribute to ALTCHA:
4
+
5
+ - **Reporting a Bug**
6
+ - **Discussing the Current State of the Code**
7
+ - **Submitting a Fix**
8
+ - **Proposing New Features**
9
+ - **Becoming a Maintainer**
10
+
11
+ ## Development with GitHub
12
+
13
+ ALTCHA is hosted on GitHub, where you can find the codebase, track issues, and submit pull requests. Please familiarize yourself with GitHub for effective collaboration.
14
+
15
+ ## Licensing Information
16
+
17
+ Any contributions you make will be subjected to the project's MIT software license. By submitting code changes, you agree to license your contributions under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the entire project. If you have any concerns regarding licensing, feel free to reach out to the maintainers.
18
+
19
+ ## Reporting Bugs Using GitHub's [Issues](https://github.com/altcha-org/altcha-lib-rb/issues)
20
+
21
+ We track public bugs using GitHub issues. Reporting a bug is easy: simply [open a new issue](https://github.com/altcha-org/altcha-lib-rb/issues). Provide detailed information for effective bug resolution.
22
+
23
+ ## Writing Effective Bug Reports
24
+
25
+ Good bug reports include:
26
+
27
+ - A quick summary and background of the issue
28
+ - Steps to reproduce the problem
29
+ - Be specific!
30
+ - Include sample code if possible
31
+ - Expected vs. actual outcomes
32
+ - Additional notes, such as your hypotheses or unsuccessful attempts to resolve the issue
33
+
34
+ ## License Agreement
35
+
36
+ By contributing to ALTCHA, you agree that your contributions will be licensed under the project's MIT License. If you have any questions or concerns, please reach out to the maintainers.
data/Gemfile.lock CHANGED
@@ -1,26 +1,28 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- altcha (0.2.1)
4
+ altcha (2.0.0.beta1)
5
+ base64
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
9
- diff-lcs (1.5.1)
10
- rake (10.5.0)
11
- rspec (3.13.0)
10
+ base64 (0.3.0)
11
+ diff-lcs (1.6.2)
12
+ rake (13.3.1)
13
+ rspec (3.13.2)
12
14
  rspec-core (~> 3.13.0)
13
15
  rspec-expectations (~> 3.13.0)
14
16
  rspec-mocks (~> 3.13.0)
15
- rspec-core (3.13.0)
17
+ rspec-core (3.13.6)
16
18
  rspec-support (~> 3.13.0)
17
- rspec-expectations (3.13.1)
19
+ rspec-expectations (3.13.5)
18
20
  diff-lcs (>= 1.2.0, < 2.0)
19
21
  rspec-support (~> 3.13.0)
20
- rspec-mocks (3.13.1)
22
+ rspec-mocks (3.13.8)
21
23
  diff-lcs (>= 1.2.0, < 2.0)
22
24
  rspec-support (~> 3.13.0)
23
- rspec-support (3.13.1)
25
+ rspec-support (3.13.7)
24
26
 
25
27
  PLATFORMS
26
28
  arm64-darwin-23
@@ -28,9 +30,9 @@ PLATFORMS
28
30
 
29
31
  DEPENDENCIES
30
32
  altcha!
31
- bundler (~> 2.5)
32
- rake (~> 10.0)
33
- rspec (~> 3.0)
33
+ bundler (~> 4.0)
34
+ rake (~> 13.3)
35
+ rspec (~> 3.13)
34
36
 
35
37
  BUNDLED WITH
36
- 2.5.11
38
+ 4.0.9
data/README.md CHANGED
@@ -1,20 +1,18 @@
1
1
  # ALTCHA Ruby Library
2
2
 
3
- The ALTCHA Ruby Library is a lightweight, zero-dependency library designed for creating and verifying [ALTCHA](https://altcha.org) challenges.
3
+ The ALTCHA Ruby Library is a lightweight, zero-dependency library designed for creating and verifying [ALTCHA](https://altcha.org) challenges. It supports both the current **PoW v2** protocol and the legacy **PoW v1** protocol.
4
4
 
5
5
  ## Compatibility
6
6
 
7
- This library is compatible with:
8
-
9
7
  - Ruby 2.7+
10
8
 
11
- ## Example
9
+ ## Examples
12
10
 
13
- - [Demo server](https://github.com/altcha-org/altcha-starter-rb)
11
+ - [`examples/server.rb`](/examples/server.rb)
14
12
 
15
13
  ## Installation
16
14
 
17
- To install the ALTCHA Ruby Library, add it to your Gemfile:
15
+ Add to your Gemfile:
18
16
 
19
17
  ```ruby
20
18
  gem 'altcha'
@@ -26,123 +24,241 @@ Then run:
26
24
  bundle install
27
25
  ```
28
26
 
29
- Alternatively, install it directly using:
27
+ Or install directly:
30
28
 
31
29
  ```sh
32
30
  gem install altcha
33
31
  ```
34
32
 
33
+ ## Optional dependencies
34
+
35
+ | Algorithm | Gem | System library |
36
+ |---|---|---|
37
+ | `ARGON2ID` | [`argon2-kdf`](https://github.com/ankane/argon2-kdf) | `libargon2` |
38
+
39
+ The `argon2-kdf` gem is only required if you use the `ARGON2ID` algorithm. Add it to your Gemfile when needed:
40
+
41
+ ```ruby
42
+ gem 'argon2-kdf'
43
+ ```
44
+
45
+ A `LoadError` with an actionable message is raised at runtime if the gem is missing and `ARGON2ID` is requested.
46
+
35
47
  ## Usage
36
48
 
37
- Here’s a basic example of how to use the ALTCHA Ruby Library:
49
+ ### PoW v2 (current)
50
+
51
+ ```ruby
52
+ require 'altcha'
53
+ require 'securerandom'
54
+
55
+ hmac_secret = 'secret hmac key'
56
+
57
+ # Create a challenge
58
+ options = Altcha::V2::CreateChallengeOptions.new(
59
+ algorithm: 'PBKDF2/SHA-256',
60
+ cost: 5_000,
61
+ counter: SecureRandom.random_number(5_000..10_000),
62
+ hmac_signature_secret: hmac_secret
63
+ )
64
+
65
+ challenge = Altcha::V2.create_challenge(options)
66
+ # => #<Altcha::V2::Challenge ...>
67
+
68
+ # Solve (client-side)
69
+ solution = Altcha::V2.solve_challenge(challenge)
70
+ # => #<Altcha::V2::Solution counter=..., derived_key="...">
71
+
72
+ # Verify (server-side)
73
+ result = Altcha::V2.verify_solution(challenge, solution, hmac_signature_secret: hmac_secret)
74
+ puts result.verified ? "Verified!" : "Invalid solution."
75
+ ```
76
+
77
+ The payload sent from the client to the server is a JSON object:
78
+
79
+ ```ruby
80
+ payload = Altcha::V2::Payload.new(challenge: challenge, solution: solution)
81
+ json = payload.to_json # send this to the server
82
+
83
+ # Server-side: restore and verify
84
+ restored = Altcha::V2::Payload.from_json(json)
85
+ result = Altcha::V2.verify_solution(
86
+ restored.challenge,
87
+ restored.solution,
88
+ hmac_signature_secret: hmac_secret
89
+ )
90
+ ```
91
+
92
+ ### PoW v1 (legacy)
38
93
 
39
94
  ```ruby
40
95
  require 'altcha'
41
96
 
42
97
  hmac_key = 'secret hmac key'
43
98
 
44
- # Create a new challenge
45
- options = Altcha::ChallengeOptions.new(
99
+ # Create a challenge
100
+ options = Altcha::V1::ChallengeOptions.new(
46
101
  hmac_key: hmac_key,
47
- max_number: 100000 # the maximum random number
102
+ max_number: 100_000
48
103
  )
49
104
 
50
- challenge = Altcha.create_challenge(options)
51
-
52
- # Example payload to verify
53
- payload = {
54
- algorithm: challenge.algorithm,
55
- challenge: challenge.challenge,
56
- number: 12345, # Example number
57
- salt: challenge.salt,
58
- signature: challenge.signature
59
- }
105
+ challenge = Altcha::V1.create_challenge(options)
60
106
 
61
- # Verify the solution
62
- valid = Altcha.verify_solution(payload, hmac_key, true)
63
- puts valid ? "Solution verified!" : "Invalid solution."
107
+ # Verify a solution submitted by the client
108
+ valid = Altcha::V1.verify_solution(payload, hmac_key, true)
109
+ puts valid ? "Verified!" : "Invalid solution."
64
110
  ```
65
111
 
66
- ## API
112
+ ## V2 API
113
+
114
+ ### `Altcha::V2.create_challenge(options)` → `Challenge`
115
+
116
+ Creates a new v2 challenge.
117
+
118
+ **`CreateChallengeOptions`**
119
+
120
+ | Option | Type | Default | Description |
121
+ |---|---|---|---|
122
+ | `algorithm` | `String` | — | Key derivation algorithm: `SHA-256`, `SHA-384`, `SHA-512`, `PBKDF2/SHA-256`, `PBKDF2/SHA-384`, `PBKDF2/SHA-512`, `SCRYPT`, `ARGON2ID`. |
123
+ | `cost` | `Integer` | — | Algorithm cost (iterations for PBKDF2/SHA, N for SCRYPT). |
124
+ | `counter` | `Integer` | `nil` | Pre-compute a deterministic key prefix from this counter value. |
125
+ | `data` | `Hash` | `nil` | Arbitrary metadata to embed in the challenge. |
126
+ | `expires_at` | `Integer, Time` | `nil` | Expiration timestamp (Unix seconds or `Time`). |
127
+ | `hmac_signature_secret` | `String` | `nil` | Signs the challenge parameters. Required for `verify_solution`. |
128
+ | `hmac_key_signature_secret` | `String` | `nil` | Signs the derived key (fast-path verification). Requires `counter`. |
129
+ | `key_length` | `Integer` | `32` | Derived key length in bytes. |
130
+ | `key_prefix` | `String` | `'00'` | Hex prefix the derived key must start with. |
131
+ | `key_prefix_length` | `Integer` | `key_length / 2` | Bytes of the derived key used as prefix in deterministic mode. |
132
+ | `memory_cost` | `Integer` | `nil` | Memory cost in KiB (`ARGON2ID`), or block size `r` (`SCRYPT`). |
133
+ | `parallelism` | `Integer` | `nil` | Parallelism factor (`ARGON2ID`, `SCRYPT`). |
134
+
135
+ ---
136
+
137
+ ### `Altcha::V2.solve_challenge(challenge, ...)` → `Solution, nil`
138
+
139
+ Solves a challenge by iterating counter values until the derived key starts with `key_prefix`.
140
+
141
+ | Parameter | Type | Default | Description |
142
+ |---|---|---|---|
143
+ | `challenge` | `Challenge` | — | Challenge to solve. |
144
+ | `max_counter` | `Integer, nil` | `nil` | Safety cap on the counter. Returns `nil` if exceeded. |
145
+ | `counter_start` | `Integer` | `0` | Starting counter value. |
146
+ | `counter_step` | `Integer` | `1` | Counter increment per iteration. |
147
+
148
+ ---
149
+
150
+ ### `Altcha::V2.verify_solution(challenge, solution, ...)` → `VerifySolutionResult`
151
+
152
+ Verifies a submitted solution.
153
+
154
+ | Parameter | Type | Description |
155
+ |---|---|---|
156
+ | `challenge` | `Challenge` | The original challenge. |
157
+ | `solution` | `Solution` | The submitted solution. |
158
+ | `hmac_signature_secret:` | `String` | Must match the secret used in `create_challenge`. |
159
+ | `hmac_key_signature_secret:` | `String, nil` | Required when `key_signature` is present. |
160
+ | `hmac_algorithm:` | `String` | HMAC digest algorithm (`SHA-256`, `SHA-384`, `SHA-512`). Default: `SHA-256`. |
161
+
162
+ **`VerifySolutionResult`**
163
+
164
+ | Field | Type | Description |
165
+ |---|---|---|
166
+ | `verified` | `Boolean` | `true` if the solution is valid. |
167
+ | `expired` | `Boolean` | `true` if the challenge has expired. |
168
+ | `invalid_signature` | `Boolean, nil` | `true` if the challenge signature is missing or wrong. |
169
+ | `invalid_solution` | `Boolean, nil` | `true` if the derived key does not match. |
170
+ | `time` | `Integer` | Verification time in milliseconds. |
171
+
172
+ ---
67
173
 
68
- ### `Altcha.create_challenge(options)`
174
+ ### `Altcha::V2.verify_server_signature(payload:, hmac_secret:)` → `VerifyServerSignatureResult`
69
175
 
70
- Creates a new challenge for ALTCHA.
176
+ Verifies a server signature payload issued by the ALTCHA backend.
71
177
 
72
- **Parameters:**
178
+ | Parameter | Type | Description |
179
+ |---|---|---|
180
+ | `payload:` | `ServerSignaturePayload` | Decoded payload from the ALTCHA backend. |
181
+ | `hmac_secret:` | `String` | Shared secret used to sign the payload. |
73
182
 
74
- - `options [ChallengeOptions]`:
75
- - `algorithm [String]`: Hashing algorithm to use (`SHA-1`, `SHA-256`, `SHA-512`, default: `SHA-256`).
76
- - `max_number [Integer]`: Maximum number for the random number generator (default: 1,000,000).
77
- - `salt_length [Integer]`: Length of the random salt (default: 12 bytes).
78
- - `hmac_key [String]`: Required HMAC key.
79
- - `salt [String]`: Optional salt string. If not provided, a random salt will be generated.
80
- - `number [Integer]`: Optional specific number to use. If not provided, a random number will be generated.
81
- - `expires [Time]`: Optional expiration time for the challenge.
82
- - `params [Hash]`: Optional URL-encoded query parameters.
183
+ **`VerifyServerSignatureResult`**
83
184
 
84
- **Returns:** `Challenge`
185
+ | Field | Type | Description |
186
+ |---|---|---|
187
+ | `verified` | `Boolean` | `true` if the payload is valid and unexpired. |
188
+ | `expired` | `Boolean` | `true` if `expire` is in the past. |
189
+ | `invalid_signature` | `Boolean` | `true` if the HMAC signature does not match. |
190
+ | `invalid_solution` | `Boolean` | `true` if `verified` is not `true` in the payload or verification data. |
191
+ | `verification_data` | `Hash, nil` | Parsed verification data with auto-typed values. |
192
+ | `time` | `Integer` | Verification time in milliseconds. |
85
193
 
86
- ### `Altcha.verify_solution(payload, hmac_key, check_expires = true)`
194
+ ---
87
195
 
88
- Verifies an ALTCHA solution.
196
+ ### `Altcha::V2.verify_fields_hash(form_data:, fields:, fields_hash:, algorithm: 'SHA-256')` → `Boolean`
89
197
 
90
- **Parameters:**
198
+ Verifies the SHA digest of selected form fields, matching the `fieldsHash` included in `verification_data`.
91
199
 
92
- - `payload [Hash]`: The solution payload to verify.
93
- - `hmac_key [String]`: The HMAC key used for verification.
94
- - `check_expires [Boolean]`: Whether to check if the challenge has expired.
200
+ ---
95
201
 
96
- **Returns:** `Boolean`
202
+ ### `Altcha::V2.parse_verification_data(data)` → `Hash, nil`
97
203
 
98
- ### `Altcha.extract_params(payload)`
204
+ Parses a URL-encoded `verificationData` string into a typed Hash. Booleans, integers, and floats are auto-detected; `fields` and `reasons` are converted to arrays.
99
205
 
100
- Extracts URL parameters from the payload's salt.
206
+ ---
101
207
 
102
- **Parameters:**
208
+ ### `Altcha::V2.canonical_json(obj)` → `String`
103
209
 
104
- - `payload [Hash]`: The payload containing the salt.
210
+ Produces a canonical (alphabetically sorted keys, compact) JSON string. Used internally for signing.
105
211
 
106
- **Returns:** `Hash`
212
+ ---
107
213
 
108
- ### `Altcha.verify_fields_hash(form_data, fields, fields_hash, algorithm)`
214
+ ### Data classes
109
215
 
110
- Verifies the hash of form fields.
216
+ **`Altcha::V2::Challenge`** challenge sent to the client.
217
+ - `parameters` — `ChallengeParameters`
218
+ - `signature` — `String, nil`
219
+ - `.from_json(string)` / `#to_json`
111
220
 
112
- **Parameters:**
221
+ **`Altcha::V2::ChallengeParameters`** — all parameters embedded in a challenge.
113
222
 
114
- - `form_data [Hash]`: The form data to hash.
115
- - `fields [Array<String>]`: The fields to include in the hash.
116
- - `fields_hash [String]`: The expected hash value.
117
- - `algorithm [String]`: Hashing algorithm (`SHA-1`, `SHA-256`, `SHA-512`).
223
+ **`Altcha::V2::Solution`** solution returned by `solve_challenge`.
224
+ - `counter` `Integer`
225
+ - `derived_key` — `String` (hex)
226
+ - `time` `Integer, nil` (milliseconds)
118
227
 
119
- **Returns:** `Boolean`
228
+ **`Altcha::V2::Payload`** — combined challenge + solution for client→server transport.
229
+ - `.from_json(string)` / `#to_json`
120
230
 
121
- ### `Altcha.verify_server_signature(payload, hmac_key)`
231
+ **`Altcha::V2::ServerSignaturePayload`** payload from the ALTCHA backend signature verification.
232
+ - `algorithm`, `verification_data`, `signature`, `verified`, `api_key`, `id`
233
+ - `.from_json(string)` / `.from_base64(string)` / `#to_json`
122
234
 
123
- Verifies the server's signature.
235
+ ---
124
236
 
125
- **Parameters:**
237
+ ## V1 API (legacy)
126
238
 
127
- - `payload [String, ServerSignaturePayload]`: The payload to verify (string or `ServerSignaturePayload`).
128
- - `hmac_key [String]`: The HMAC key used for verification.
239
+ ### `Altcha::V1.create_challenge(options)` `Challenge`
129
240
 
130
- **Returns:** `[Boolean, ServerSignatureVerificationData]`
241
+ | Option | Type | Default | Description |
242
+ |---|---|---|---|
243
+ | `hmac_key` | `String` | — | Required HMAC key. |
244
+ | `algorithm` | `String` | `SHA-256` | Hashing algorithm (`SHA-1`, `SHA-256`, `SHA-512`). |
245
+ | `max_number` | `Integer` | `1_000_000` | Upper bound for the random number. |
246
+ | `salt_length` | `Integer` | `12` | Random salt length in bytes. |
247
+ | `salt` | `String` | `nil` | Override generated salt. |
248
+ | `number` | `Integer` | `nil` | Override random number. |
249
+ | `expires` | `Time` | `nil` | Challenge expiration time. |
250
+ | `params` | `Hash` | `nil` | Extra URL-encoded parameters embedded in the salt. |
131
251
 
132
- ### `Altcha.solve_challenge(challenge, salt, algorithm, max, start)`
252
+ ### `Altcha::V1.verify_solution(payload, hmac_key, check_expires = true)` → `Boolean`
133
253
 
134
- Finds a solution to the given challenge.
254
+ ### `Altcha::V1.verify_fields_hash(form_data, fields, fields_hash, algorithm)` `Boolean`
135
255
 
136
- **Parameters:**
256
+ ### `Altcha::V1.verify_server_signature(payload, hmac_key)` → `[Boolean, ServerSignatureVerificationData]`
137
257
 
138
- - `challenge [String]`: The challenge hash.
139
- - `salt [String]`: The challenge salt.
140
- - `algorithm [String]`: Hashing algorithm (`SHA-1`, `SHA-256`, `SHA-512`).
141
- - `max [Integer]`: Maximum number to iterate to.
142
- - `start [Integer]`: Starting number.
258
+ ### `Altcha::V1.solve_challenge(challenge, salt, algorithm, max, start)` → `Solution, nil`
143
259
 
144
- **Returns:** `Solution, nil`
260
+ ### `Altcha::V1.extract_params(payload)` `Hash`
145
261
 
146
262
  ## License
147
263
 
148
- MIT
264
+ MIT
data/SECURITY.md ADDED
@@ -0,0 +1,57 @@
1
+ ## Security Vulnerability Disclosure Policy
2
+
3
+ We take security seriously and value the contributions of researchers who act in good faith to help protect our users. If you believe you have found a vulnerability in our services or software, we encourage you to report it responsibly so we can address it promptly.
4
+
5
+ ### Reporting a Vulnerability
6
+
7
+ Please email your findings to our [security contacts](https://altcha.org/contact#reporting-security-issues).
8
+ To ensure confidentiality, we recommend encrypting your report using our [PGP key](https://altcha.org/pgp/security-public-key.asc).
9
+
10
+ Your report should include:
11
+
12
+ - A clear description of the vulnerability.
13
+ - A working proof of concept or detailed steps to reproduce the issue.
14
+ - Relevant logs, screenshots, or code snippets.
15
+
16
+ We will acknowledge receipt of your report within 5 business days and keep you informed about our investigation.
17
+
18
+ ### In-Scope
19
+
20
+ We prioritize reports that demonstrate a real, actionable security risk to our software, services, or infrastructure, such as:
21
+
22
+ - Remote code execution (RCE)
23
+ - Authentication bypass or privilege escalation
24
+ - Server-side request forgery (SSRF)
25
+ - Cross-site scripting (XSS) or CSRF with significant impact
26
+
27
+ ### Out-of-Scope
28
+
29
+ To minimize automated noise, the following are generally excluded from our review process:
30
+
31
+ - Automated results: Reports generated by scanners that lack a manual, actionable proof of exploitability.
32
+ - Configuration & Hygiene: Missing HTTP headers, TLS/SSL configurations, DNS records, or server banners.
33
+ - Volume-based attacks: Denial of Service (DoS/DDoS) or rate-limiting issues.
34
+ - Low-impact: Clickjacking on non-sensitive pages, or bugs requiring jailbroken devices/unsupported browsers.
35
+ - Third-party: Issues in libraries or services not directly managed by us.
36
+
37
+ ### Responsible Disclosure Guidelines
38
+
39
+ To remain in good standing with our team, we ask that you:
40
+
41
+ - Do not publicly disclose vulnerabilities before we have confirmed a fix.
42
+ - Do not access, modify, or delete data that does not belong to you.
43
+ - Avoid any actions that could degrade or disrupt our services.
44
+
45
+ We appreciate the efforts of the security community in helping us maintain a safe environment.
46
+
47
+ ### Disclaimer
48
+
49
+ This is a voluntary disclosure program rooted in the spirit of open-source collaboration. We operate this program to benefit the broader community and ensure the collective safety of our users. We do not offer any form of compensation for submitted reports. By submitting a report, you acknowledge that you are doing so without expectation of payment and waive any future claims for compensation.
50
+
51
+ ### Related
52
+
53
+ - [Security Advisory](https://altcha.org/security-advisory)
54
+
55
+ ---
56
+
57
+ Updated: Feb 4, 2026
data/altcha.gemspec CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "A lightweight library for creating and verifying ALTCHA challenges."
13
13
  spec.homepage = "https://altcha.org"
14
14
  spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.7"
15
16
 
16
17
  # Specify which files should be added to the gem when it is released.
17
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -22,7 +23,9 @@ Gem::Specification.new do |spec|
22
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
24
  spec.require_paths = ["lib"]
24
25
 
25
- spec.add_development_dependency "bundler", "~> 2.5"
26
- spec.add_development_dependency "rake", "~> 10.0"
27
- spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_dependency "base64"
27
+
28
+ spec.add_development_dependency "bundler", "~> 4.0"
29
+ spec.add_development_dependency "rake", "~> 13.3"
30
+ spec.add_development_dependency "rspec", "~> 3.13"
28
31
  end