argon2id 0.8.0.rc1-aarch64-linux-gnu → 0.10.0-aarch64-linux-gnu
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 +4 -4
- data/CHANGELOG.md +39 -0
- data/README.md +5 -5
- data/Rakefile +2 -7
- data/argon2id.gemspec +2 -2
- data/ext/argon2id/argon2id.c +141 -28
- data/lib/argon2id/3.1/argon2id.so +0 -0
- data/lib/argon2id/3.2/argon2id.so +0 -0
- data/lib/argon2id/3.3/argon2id.so +0 -0
- data/lib/argon2id/3.4/argon2id.so +0 -0
- data/lib/argon2id/4.0/argon2id.so +0 -0
- data/lib/argon2id/extension.rb +1 -0
- data/lib/argon2id/password.rb +4 -3
- data/lib/argon2id/version.rb +1 -1
- data/test/argon2id/test_password.rb +67 -0
- metadata +9 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 73e28c9dee86c37e3701604ccda5ea8d7d5152c656e7147c058d6b275d36532e
|
|
4
|
+
data.tar.gz: 01514af73f357ea3ccd9696572c8ee1d20ba64ca1d4d2a4eb40693c51a2dea41
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f9e2423f7069bc72f2344aa412be78db1ebada03ccb32f906c1bc577df32938378bd5c703c11ac655eff55a2cd145413b30e62fc4c4c049c8d9bf3cf9480955
|
|
7
|
+
data.tar.gz: 77e3b6316592a4ab01dabd599369632da74f55fffaecdc3e7a98f5d19dd88838b6c775a8d73f31d47cb0cf8506b9da4d0db0d855fb737927f43465fdabc8583f
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,42 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.10.0] - 2026-04-06
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Hashing and verifying passwords no longer holds the Ruby Global VM Lock
|
|
13
|
+
during the intentionally expensive computation of the Argon2id hash, allowing
|
|
14
|
+
other threads to do work at the same time.
|
|
15
|
+
- Argon2id::Password objects, their encoded password hash, salt, and hash
|
|
16
|
+
output strings are now all frozen to prevent mutation. Inputs are also now
|
|
17
|
+
frozen ASAP during hashing and verification to prevent mutation before
|
|
18
|
+
passing to the internal C/Java implementation of Argon2.
|
|
19
|
+
- The extension is now flagged as safe to use with Ractors.
|
|
20
|
+
|
|
21
|
+
## [0.9.0] - 2025-12-30
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- Add support for Ruby 4.0 in precompiled, native gems.
|
|
25
|
+
|
|
26
|
+
### Removed
|
|
27
|
+
- Remove support and native gems for Ruby 2.6, 2.7, and 3.0.
|
|
28
|
+
- Remove native gems for 32-bit platforms, specifically x86-linux-gnu,
|
|
29
|
+
x86-linux-musl, and x86-mingw32
|
|
30
|
+
|
|
31
|
+
## [0.8.0] - 2024-12-29
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- Add Ruby 3.4 support to the precompiled, native gems
|
|
36
|
+
- Restored support for Ruby 2.6, 2.7, and 3.0 after dropping them in 0.8.0.rc1
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- Provide separate precompiled, native gems for GNU and Musl
|
|
41
|
+
- Require glibc 2.29+ for x86-linux-gnu and x86_64-linux-gnu (and recommend
|
|
42
|
+
RubyGems 3.3.22+ and Bundler 2.3.21+)
|
|
43
|
+
|
|
8
44
|
## [0.8.0.rc1] - 2024-12-16
|
|
9
45
|
|
|
10
46
|
### Added
|
|
@@ -128,6 +164,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
128
164
|
reference C implementation of Argon2, the password-hashing function that won
|
|
129
165
|
the Password Hashing Competition.
|
|
130
166
|
|
|
167
|
+
[0.10.0]: https://github.com/mudge/argon2id/releases/tag/v0.10.0
|
|
168
|
+
[0.9.0]: https://github.com/mudge/argon2id/releases/tag/v0.9.0
|
|
169
|
+
[0.8.0]: https://github.com/mudge/argon2id/releases/tag/v0.8.0
|
|
131
170
|
[0.8.0.rc1]: https://github.com/mudge/argon2id/releases/tag/v0.8.0.rc1
|
|
132
171
|
[0.7.0]: https://github.com/mudge/argon2id/releases/tag/v0.7.0
|
|
133
172
|
[0.6.0]: https://github.com/mudge/argon2id/releases/tag/v0.6.0
|
data/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Ruby bindings to [Argon2][], the password-hashing function that won the 2015
|
|
|
5
5
|
|
|
6
6
|
[](https://github.com/mudge/argon2id/actions)
|
|
7
7
|
|
|
8
|
-
**Current version:** 0.
|
|
8
|
+
**Current version:** 0.10.0
|
|
9
9
|
**Bundled Argon2 version:** libargon2.1 (20190702)
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
@@ -257,8 +257,8 @@ User.find_by(name: "alice")&.authenticate("password") #=> user
|
|
|
257
257
|
|
|
258
258
|
This gem requires any of the following to run:
|
|
259
259
|
|
|
260
|
-
* [Ruby](https://www.ruby-lang.org/en/) 3.1 to
|
|
261
|
-
* [JRuby](https://www.jruby.org) 9.4
|
|
260
|
+
* [Ruby](https://www.ruby-lang.org/en/) 3.1 to 4.0
|
|
261
|
+
* [JRuby](https://www.jruby.org) 9.4 to 10.0
|
|
262
262
|
* [TruffleRuby](https://www.graalvm.org/ruby/) 24.1
|
|
263
263
|
|
|
264
264
|
> [!NOTE]
|
|
@@ -271,10 +271,10 @@ This gem requires any of the following to run:
|
|
|
271
271
|
Where possible, a pre-compiled native gem will be provided for the following platforms:
|
|
272
272
|
|
|
273
273
|
* Linux
|
|
274
|
-
* `aarch64-linux`, `arm-linux`, `
|
|
274
|
+
* `aarch64-linux`, `arm-linux`, `x86_64-linux` (requires [glibc](https://www.gnu.org/software/libc/) 2.29+, RubyGems 3.3.22+ and Bundler 2.3.21+)
|
|
275
275
|
* [musl](https://musl.libc.org/)-based systems such as [Alpine](https://alpinelinux.org) are supported with Bundler 2.5.6+
|
|
276
276
|
* macOS `x86_64-darwin` and `arm64-darwin`
|
|
277
|
-
* Windows `x64-mingw-ucrt`
|
|
277
|
+
* Windows 2022+ `x64-mingw-ucrt`
|
|
278
278
|
* Java: any platform running JRuby 9.4 or higher
|
|
279
279
|
|
|
280
280
|
### Verifying the gems
|
data/Rakefile
CHANGED
|
@@ -11,16 +11,12 @@ cross_platforms = %w[
|
|
|
11
11
|
arm-linux-musl
|
|
12
12
|
arm64-darwin
|
|
13
13
|
x64-mingw-ucrt
|
|
14
|
-
x64-mingw32
|
|
15
|
-
x86-linux-gnu
|
|
16
|
-
x86-linux-musl
|
|
17
|
-
x86-mingw32
|
|
18
14
|
x86_64-darwin
|
|
19
15
|
x86_64-linux-gnu
|
|
20
16
|
x86_64-linux-musl
|
|
21
17
|
].freeze
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
RakeCompilerDock.set_ruby_cc_version("~> 3.1", "~> 4.0")
|
|
24
20
|
|
|
25
21
|
gemspec = Gem::Specification.load("argon2id.gemspec")
|
|
26
22
|
|
|
@@ -31,7 +27,6 @@ namespace :java do
|
|
|
31
27
|
java_gemspec.files.reject! { |path| File.fnmatch?("ext/*", path) }
|
|
32
28
|
java_gemspec.extensions.clear
|
|
33
29
|
java_gemspec.platform = Gem::Platform.new("java")
|
|
34
|
-
java_gemspec.required_ruby_version = ">= 3.1.0"
|
|
35
30
|
|
|
36
31
|
Gem::PackageTask.new(java_gemspec).define
|
|
37
32
|
end
|
|
@@ -60,7 +55,7 @@ namespace :gem do
|
|
|
60
55
|
task platform do
|
|
61
56
|
RakeCompilerDock.sh <<~SCRIPT, platform: platform, verbose: true
|
|
62
57
|
gem install bundler --no-document &&
|
|
63
|
-
bundle &&
|
|
58
|
+
bundle install &&
|
|
64
59
|
bundle exec rake native:#{platform} pkg/#{gemspec.full_name}-#{Gem::Platform.new(platform)}.gem PATH="/usr/local/bin:$PATH"
|
|
65
60
|
SCRIPT
|
|
66
61
|
end
|
data/argon2id.gemspec
CHANGED
|
@@ -53,7 +53,7 @@ Gem::Specification.new do |s|
|
|
|
53
53
|
]
|
|
54
54
|
s.rdoc_options = ["--main", "README.md"]
|
|
55
55
|
|
|
56
|
-
s.add_development_dependency("rake-compiler", "~> 1.
|
|
57
|
-
s.add_development_dependency("rake-compiler-dock", "~> 1.
|
|
56
|
+
s.add_development_dependency("rake-compiler", "~> 1.3")
|
|
57
|
+
s.add_development_dependency("rake-compiler-dock", "~> 1.11")
|
|
58
58
|
s.add_development_dependency("minitest", "~> 5.25")
|
|
59
59
|
end
|
data/ext/argon2id/argon2id.c
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include <ruby.h>
|
|
2
|
+
#include <ruby/thread.h>
|
|
2
3
|
#include <stdint.h>
|
|
3
4
|
|
|
4
5
|
#include "argon2.h"
|
|
@@ -8,64 +9,176 @@
|
|
|
8
9
|
VALUE mArgon2id, cArgon2idError, cArgon2idPassword;
|
|
9
10
|
ID id_encoded;
|
|
10
11
|
|
|
12
|
+
struct hash_encoded_args {
|
|
13
|
+
uint32_t t_cost;
|
|
14
|
+
uint32_t m_cost;
|
|
15
|
+
uint32_t parallelism;
|
|
16
|
+
const char *pwd;
|
|
17
|
+
size_t pwdlen;
|
|
18
|
+
const char *salt;
|
|
19
|
+
size_t saltlen;
|
|
20
|
+
uint32_t outlen;
|
|
21
|
+
char *encoded;
|
|
22
|
+
size_t encodedlen;
|
|
23
|
+
int result;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
static void *
|
|
27
|
+
nogvl_hash_encoded(void *data)
|
|
28
|
+
{
|
|
29
|
+
struct hash_encoded_args *args = data;
|
|
30
|
+
args->result = argon2id_hash_encoded(args->t_cost, args->m_cost,
|
|
31
|
+
args->parallelism, args->pwd, args->pwdlen, args->salt, args->saltlen,
|
|
32
|
+
args->outlen, args->encoded, args->encodedlen);
|
|
33
|
+
|
|
34
|
+
return NULL;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
struct verify_args {
|
|
38
|
+
const char *encoded;
|
|
39
|
+
const char *pwd;
|
|
40
|
+
size_t pwdlen;
|
|
41
|
+
int result;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
static void *
|
|
45
|
+
nogvl_verify(void *data)
|
|
46
|
+
{
|
|
47
|
+
struct verify_args *args = data;
|
|
48
|
+
args->result = argon2id_verify(args->encoded, args->pwd, args->pwdlen);
|
|
49
|
+
|
|
50
|
+
return NULL;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
struct hash_encoded_data {
|
|
54
|
+
char *encoded;
|
|
55
|
+
VALUE pwd;
|
|
56
|
+
VALUE salt;
|
|
57
|
+
struct hash_encoded_args args;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
static VALUE
|
|
61
|
+
hash_encoded_body(VALUE arg)
|
|
62
|
+
{
|
|
63
|
+
struct hash_encoded_data *data = (struct hash_encoded_data *)arg;
|
|
64
|
+
|
|
65
|
+
rb_thread_call_without_gvl(nogvl_hash_encoded, &data->args, NULL, NULL);
|
|
66
|
+
|
|
67
|
+
if (data->args.result != ARGON2_OK) {
|
|
68
|
+
rb_raise(cArgon2idError, "%s", argon2_error_message(data->args.result));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return rb_str_new_cstr(data->encoded);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static VALUE
|
|
75
|
+
hash_encoded_finalize(VALUE arg)
|
|
76
|
+
{
|
|
77
|
+
struct hash_encoded_data *data = (struct hash_encoded_data *)arg;
|
|
78
|
+
|
|
79
|
+
RB_GC_GUARD(data->pwd);
|
|
80
|
+
RB_GC_GUARD(data->salt);
|
|
81
|
+
free(data->encoded);
|
|
82
|
+
|
|
83
|
+
return Qnil;
|
|
84
|
+
}
|
|
85
|
+
|
|
11
86
|
static VALUE
|
|
12
87
|
rb_argon2id_hash_encoded(VALUE klass, VALUE iterations, VALUE memory, VALUE threads, VALUE pwd, VALUE salt, VALUE hashlen)
|
|
13
88
|
{
|
|
14
|
-
uint32_t t_cost, m_cost, parallelism;
|
|
15
|
-
size_t encodedlen
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
VALUE hash;
|
|
89
|
+
uint32_t t_cost, m_cost, parallelism, outlen;
|
|
90
|
+
size_t encodedlen;
|
|
91
|
+
long saltlen;
|
|
92
|
+
struct hash_encoded_data data;
|
|
19
93
|
|
|
20
94
|
UNUSED(klass);
|
|
21
95
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
96
|
+
/* Coerce pwd and salt to strings, then freeze to protect against mutation. */
|
|
97
|
+
StringValue(pwd);
|
|
98
|
+
pwd = rb_str_new_frozen(pwd);
|
|
99
|
+
StringValue(salt);
|
|
100
|
+
salt = rb_str_new_frozen(salt);
|
|
26
101
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
102
|
+
t_cost = NUM2UINT(iterations);
|
|
103
|
+
m_cost = NUM2UINT(memory);
|
|
104
|
+
parallelism = NUM2UINT(threads);
|
|
105
|
+
outlen = NUM2UINT(hashlen);
|
|
32
106
|
|
|
33
|
-
|
|
107
|
+
if (RSTRING_LEN(pwd) > UINT32_MAX) {
|
|
108
|
+
rb_raise(rb_eRangeError, "password too long");
|
|
109
|
+
}
|
|
34
110
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
rb_raise(
|
|
111
|
+
saltlen = RSTRING_LEN(salt);
|
|
112
|
+
if (saltlen > UINT32_MAX) {
|
|
113
|
+
rb_raise(rb_eRangeError, "salt too long");
|
|
38
114
|
}
|
|
39
115
|
|
|
40
|
-
|
|
41
|
-
|
|
116
|
+
encodedlen = argon2_encodedlen(t_cost, m_cost, parallelism, (uint32_t)saltlen, outlen, Argon2_id);
|
|
117
|
+
data.encoded = malloc(encodedlen);
|
|
118
|
+
if (!data.encoded) {
|
|
119
|
+
rb_raise(rb_eNoMemError, "not enough memory to allocate for encoded password");
|
|
120
|
+
}
|
|
42
121
|
|
|
43
|
-
|
|
122
|
+
data.pwd = pwd;
|
|
123
|
+
data.salt = salt;
|
|
124
|
+
data.args.result = ARGON2_MISSING_ARGS;
|
|
125
|
+
data.args.t_cost = t_cost;
|
|
126
|
+
data.args.m_cost = m_cost;
|
|
127
|
+
data.args.parallelism = parallelism;
|
|
128
|
+
data.args.pwd = RSTRING_PTR(pwd);
|
|
129
|
+
data.args.pwdlen = RSTRING_LEN(pwd);
|
|
130
|
+
data.args.salt = RSTRING_PTR(salt);
|
|
131
|
+
data.args.saltlen = RSTRING_LEN(salt);
|
|
132
|
+
data.args.outlen = outlen;
|
|
133
|
+
data.args.encoded = data.encoded;
|
|
134
|
+
data.args.encodedlen = encodedlen;
|
|
135
|
+
|
|
136
|
+
return rb_ensure(hash_encoded_body, (VALUE)&data, hash_encoded_finalize, (VALUE)&data);
|
|
44
137
|
}
|
|
45
138
|
|
|
46
139
|
static VALUE
|
|
47
140
|
rb_argon2id_verify(VALUE self, VALUE pwd) {
|
|
48
|
-
int result;
|
|
49
141
|
VALUE encoded;
|
|
142
|
+
struct verify_args args;
|
|
50
143
|
|
|
51
144
|
encoded = rb_ivar_get(self, id_encoded);
|
|
52
|
-
|
|
53
|
-
|
|
145
|
+
|
|
146
|
+
/* Coerce encoded and freeze it before doing the same to pwd. The order here
|
|
147
|
+
* is important to prevent pwd#to_str mutating encoded.
|
|
148
|
+
*/
|
|
149
|
+
StringValueCStr(encoded);
|
|
150
|
+
encoded = rb_str_new_frozen(encoded);
|
|
151
|
+
StringValue(pwd);
|
|
152
|
+
pwd = rb_str_new_frozen(pwd);
|
|
153
|
+
|
|
154
|
+
args.result = ARGON2_MISSING_ARGS;
|
|
155
|
+
args.encoded = RSTRING_PTR(encoded);
|
|
156
|
+
args.pwd = RSTRING_PTR(pwd);
|
|
157
|
+
args.pwdlen = RSTRING_LEN(pwd);
|
|
158
|
+
|
|
159
|
+
rb_thread_call_without_gvl(nogvl_verify, &args, NULL, NULL);
|
|
160
|
+
|
|
161
|
+
RB_GC_GUARD(encoded);
|
|
162
|
+
RB_GC_GUARD(pwd);
|
|
163
|
+
|
|
164
|
+
if (args.result == ARGON2_OK) {
|
|
54
165
|
return Qtrue;
|
|
55
166
|
}
|
|
56
|
-
if (result == ARGON2_VERIFY_MISMATCH) {
|
|
167
|
+
if (args.result == ARGON2_VERIFY_MISMATCH) {
|
|
57
168
|
return Qfalse;
|
|
58
169
|
}
|
|
59
|
-
if (result == ARGON2_DECODING_FAIL || result == ARGON2_DECODING_LENGTH_FAIL) {
|
|
60
|
-
rb_raise(rb_eArgError, "%s", argon2_error_message(result));
|
|
170
|
+
if (args.result == ARGON2_DECODING_FAIL || args.result == ARGON2_DECODING_LENGTH_FAIL) {
|
|
171
|
+
rb_raise(rb_eArgError, "%s", argon2_error_message(args.result));
|
|
61
172
|
}
|
|
62
173
|
|
|
63
|
-
rb_raise(cArgon2idError, "%s", argon2_error_message(result));
|
|
174
|
+
rb_raise(cArgon2idError, "%s", argon2_error_message(args.result));
|
|
64
175
|
}
|
|
65
176
|
|
|
66
177
|
void
|
|
67
178
|
Init_argon2id(void)
|
|
68
179
|
{
|
|
180
|
+
rb_ext_ractor_safe(true);
|
|
181
|
+
|
|
69
182
|
id_encoded = rb_intern("@encoded");
|
|
70
183
|
|
|
71
184
|
mArgon2id = rb_define_module("Argon2id");
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/lib/argon2id/extension.rb
CHANGED
|
@@ -10,6 +10,7 @@ if RUBY_PLATFORM == "java"
|
|
|
10
10
|
class Password
|
|
11
11
|
def self.hash_encoded(t_cost, m_cost, parallelism, pwd, salt, hashlen)
|
|
12
12
|
raise Error, "Salt is too short" if salt.empty?
|
|
13
|
+
raise Error, "Memory cost is too small" if m_cost < 8
|
|
13
14
|
|
|
14
15
|
salt_bytes = salt.to_java_bytes
|
|
15
16
|
output = Java::byte[hashlen].new
|
data/lib/argon2id/password.rb
CHANGED
|
@@ -115,13 +115,14 @@ module Argon2id
|
|
|
115
115
|
def initialize(encoded)
|
|
116
116
|
raise ArgumentError, "invalid hash" unless PATTERN =~ String(encoded)
|
|
117
117
|
|
|
118
|
-
@encoded =
|
|
118
|
+
@encoded = $&.freeze
|
|
119
119
|
@version = Integer($1 || 0x10)
|
|
120
120
|
@m_cost = Integer($2)
|
|
121
121
|
@t_cost = Integer($3)
|
|
122
122
|
@parallelism = Integer($4)
|
|
123
|
-
@salt = $5.unpack1("m")
|
|
124
|
-
@output = $6.unpack1("m")
|
|
123
|
+
@salt = $5.unpack1("m").freeze
|
|
124
|
+
@output = $6.unpack1("m").freeze
|
|
125
|
+
freeze
|
|
125
126
|
end
|
|
126
127
|
|
|
127
128
|
# Return the encoded password hash.
|
data/lib/argon2id/version.rb
CHANGED
|
@@ -188,6 +188,42 @@ class TestPassword < Minitest::Test
|
|
|
188
188
|
assert password == "password"
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
+
def test_new_password_is_frozen
|
|
192
|
+
password = Argon2id::Password.new(
|
|
193
|
+
"$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ" \
|
|
194
|
+
"$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4"
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
assert password.frozen?
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def test_encoded_is_frozen
|
|
201
|
+
password = Argon2id::Password.new(
|
|
202
|
+
"$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ" \
|
|
203
|
+
"$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4"
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
assert password.encoded.frozen?
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def test_salt_is_frozen
|
|
210
|
+
password = Argon2id::Password.new(
|
|
211
|
+
"$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ" \
|
|
212
|
+
"$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4"
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
assert password.salt.frozen?
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def test_output_is_frozen
|
|
219
|
+
password = Argon2id::Password.new(
|
|
220
|
+
"$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ" \
|
|
221
|
+
"$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4"
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
assert password.output.frozen?
|
|
225
|
+
end
|
|
226
|
+
|
|
191
227
|
def test_encoded_returns_the_full_encoded_hash
|
|
192
228
|
password = Argon2id::Password.new(
|
|
193
229
|
"$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ" \
|
|
@@ -526,6 +562,12 @@ class TestPassword < Minitest::Test
|
|
|
526
562
|
Argon2id.output_len = Argon2id::DEFAULT_OUTPUT_LEN
|
|
527
563
|
end
|
|
528
564
|
|
|
565
|
+
def test_create_password_is_frozen
|
|
566
|
+
password = Argon2id::Password.create("password")
|
|
567
|
+
|
|
568
|
+
assert password.frozen?
|
|
569
|
+
end
|
|
570
|
+
|
|
529
571
|
def test_create_password_equals_correct_password
|
|
530
572
|
password = Argon2id::Password.create("password")
|
|
531
573
|
|
|
@@ -538,6 +580,31 @@ class TestPassword < Minitest::Test
|
|
|
538
580
|
refute password == "differentpassword"
|
|
539
581
|
end
|
|
540
582
|
|
|
583
|
+
def test_create_is_thread_safe
|
|
584
|
+
threads = 10.times.map do |i|
|
|
585
|
+
Thread.new(i) do |n|
|
|
586
|
+
password = Argon2id::Password.create("password-#{n}", t_cost: 2, m_cost: 256, parallelism: 1)
|
|
587
|
+
assert password == "password-#{n}"
|
|
588
|
+
end
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
threads.each(&:value)
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
def test_verify_is_thread_safe
|
|
595
|
+
hash = Argon2id::Password.create("password", t_cost: 2, m_cost: 256, parallelism: 1).to_s
|
|
596
|
+
|
|
597
|
+
threads = 10.times.map do |i|
|
|
598
|
+
Thread.new do
|
|
599
|
+
password = Argon2id::Password.new(hash)
|
|
600
|
+
assert password == "password"
|
|
601
|
+
refute password == "wrong"
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
threads.each(&:value)
|
|
606
|
+
end
|
|
607
|
+
|
|
541
608
|
def test_hashing_password_verifies_correct_password
|
|
542
609
|
hash = Argon2id::Password.create("password").to_s
|
|
543
610
|
password = Argon2id::Password.new(hash)
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: argon2id
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.0
|
|
5
5
|
platform: aarch64-linux-gnu
|
|
6
6
|
authors:
|
|
7
7
|
- Paul Mucur
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rake-compiler
|
|
@@ -16,28 +15,28 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '1.
|
|
18
|
+
version: '1.3'
|
|
20
19
|
type: :development
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - "~>"
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '1.
|
|
25
|
+
version: '1.3'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: rake-compiler-dock
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
30
|
- - "~>"
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 1.
|
|
32
|
+
version: '1.11'
|
|
34
33
|
type: :development
|
|
35
34
|
prerelease: false
|
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
36
|
requirements:
|
|
38
37
|
- - "~>"
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 1.
|
|
39
|
+
version: '1.11'
|
|
41
40
|
- !ruby/object:Gem::Dependency
|
|
42
41
|
name: minitest
|
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -54,7 +53,6 @@ dependencies:
|
|
|
54
53
|
version: '5.25'
|
|
55
54
|
description: Ruby bindings to Argon2, the password-hashing function that won the 2015
|
|
56
55
|
Password Hashing Competition.
|
|
57
|
-
email:
|
|
58
56
|
executables: []
|
|
59
57
|
extensions: []
|
|
60
58
|
extra_rdoc_files: []
|
|
@@ -87,6 +85,7 @@ files:
|
|
|
87
85
|
- lib/argon2id/3.2/argon2id.so
|
|
88
86
|
- lib/argon2id/3.3/argon2id.so
|
|
89
87
|
- lib/argon2id/3.4/argon2id.so
|
|
88
|
+
- lib/argon2id/4.0/argon2id.so
|
|
90
89
|
- lib/argon2id/extension.rb
|
|
91
90
|
- lib/argon2id/password.rb
|
|
92
91
|
- lib/argon2id/version.rb
|
|
@@ -102,7 +101,6 @@ metadata:
|
|
|
102
101
|
homepage_uri: https://github.com/mudge/argon2id
|
|
103
102
|
source_code_uri: https://github.com/mudge/argon2id
|
|
104
103
|
rubygems_mfa_required: 'true'
|
|
105
|
-
post_install_message:
|
|
106
104
|
rdoc_options:
|
|
107
105
|
- "--main"
|
|
108
106
|
- README.md
|
|
@@ -115,18 +113,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
115
113
|
version: '3.1'
|
|
116
114
|
- - "<"
|
|
117
115
|
- !ruby/object:Gem::Version
|
|
118
|
-
version:
|
|
116
|
+
version: 4.1.dev
|
|
119
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
118
|
requirements:
|
|
121
|
-
- - ">"
|
|
122
|
-
- !ruby/object:Gem::Version
|
|
123
|
-
version: 1.3.1
|
|
124
119
|
- - ">="
|
|
125
120
|
- !ruby/object:Gem::Version
|
|
126
121
|
version: 3.3.22
|
|
127
122
|
requirements: []
|
|
128
|
-
rubygems_version:
|
|
129
|
-
signing_key:
|
|
123
|
+
rubygems_version: 4.0.3
|
|
130
124
|
specification_version: 4
|
|
131
125
|
summary: Ruby bindings to Argon2
|
|
132
126
|
test_files: []
|