argon2id 0.4.1-x64-mingw32 → 0.6.0-x64-mingw32
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 +15 -0
- data/README.md +12 -9
- data/Rakefile +11 -16
- data/argon2id.gemspec +2 -3
- data/ext/argon2id/argon2id.c +13 -24
- data/ext/argon2id/extconf.rb +1 -1
- data/lib/argon2id/2.6/argon2id.so +0 -0
- data/lib/argon2id/2.7/argon2id.so +0 -0
- data/lib/argon2id/3.0/argon2id.so +0 -0
- data/lib/argon2id/extension.rb +69 -0
- data/lib/argon2id/password.rb +9 -14
- data/lib/argon2id/version.rb +1 -1
- data/lib/argon2id.rb +2 -65
- data/test/test_password.rb +66 -12
- metadata +6 -7
- data/lib/2.6/argon2id.so +0 -0
- data/lib/2.7/argon2id.so +0 -0
- data/lib/3.0/argon2id.so +0 -0
- data/test/test_hash_encoded.rb +0 -54
- data/test/test_verify.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9830d34e6ade0521646b04b6ac5bb6636880959d2fb28e03d30e6302027a016f
|
4
|
+
data.tar.gz: bfa8e53f5b9dffe5f5b7a264400a7aaaa3cecbf4ee9066181272db1c00e47571
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25d3e39fe9ddd17b9795905fe1c16d20a39b3795e2447c6cf9a9dadad1e09c52be3048dc73783bd0410ce4b279c3cf84c8e37691a9ce0af34b2bed6c3a60db9d
|
7
|
+
data.tar.gz: 25c021ef3950a43fd06441730dd74c9bfa8f86bafde3c098b52020ba48e32b2b8c624dd0f9bfe2a90c02959c4753ab747f4f89cecaf5872e5d22cd16e2381bb4
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,19 @@ 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.6.0] - 2024-11-05
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
|
12
|
+
- Move the internal API to `Argon2id::Password` and make it explicitly private
|
13
|
+
|
14
|
+
## [0.5.0] - 2024-11-02
|
15
|
+
|
16
|
+
### Removed
|
17
|
+
|
18
|
+
- No longer expose the `type` of an encoded hash as it must always be an
|
19
|
+
Argon2id hash
|
20
|
+
|
8
21
|
## [0.4.1] - 2024-11-02
|
9
22
|
|
10
23
|
### Changed
|
@@ -86,6 +99,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
86
99
|
reference C implementation of Argon2, the password-hashing function that won
|
87
100
|
the Password Hashing Competition.
|
88
101
|
|
102
|
+
[0.6.0]: https://github.com/mudge/argon2id/releases/tag/v0.6.0
|
103
|
+
[0.5.0]: https://github.com/mudge/argon2id/releases/tag/v0.5.0
|
89
104
|
[0.4.1]: https://github.com/mudge/argon2id/releases/tag/v0.4.1
|
90
105
|
[0.4.0]: https://github.com/mudge/argon2id/releases/tag/v0.4.0
|
91
106
|
[0.3.0]: https://github.com/mudge/argon2id/releases/tag/v0.3.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.6.0
|
9
9
|
**Bundled Argon2 version:** libargon2.1 (20190702)
|
10
10
|
|
11
11
|
```ruby
|
@@ -135,6 +135,10 @@ password == "opensesame" #=> true
|
|
135
135
|
password == "notopensesame" #=> false
|
136
136
|
```
|
137
137
|
|
138
|
+
> [!WARNING]
|
139
|
+
> `Argon2id::Password.new` does not support hashes generated from other Argon2
|
140
|
+
> variants such as Argon2i and Argon2d.
|
141
|
+
|
138
142
|
For compatibility with [bcrypt-ruby][], `Argon2id::Password#==` is aliased to `Argon2id::Password.is_password?`:
|
139
143
|
|
140
144
|
```ruby
|
@@ -147,7 +151,6 @@ The various parts of the encoded hash can be retrieved:
|
|
147
151
|
|
148
152
|
```ruby
|
149
153
|
password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
|
150
|
-
password.type #=> "argon2id"
|
151
154
|
password.version #=> 19
|
152
155
|
password.m_cost #=> 256
|
153
156
|
password.t_cost #=> 2
|
@@ -198,11 +201,11 @@ notes](https://github.com/mudge/argon2id/releases) for each version and can be
|
|
198
201
|
checked with `sha256sum`, e.g.
|
199
202
|
|
200
203
|
```console
|
201
|
-
$ gem fetch argon2id -v 0.
|
202
|
-
Fetching argon2id-0.
|
203
|
-
Downloaded argon2id-0.
|
204
|
-
$ sha256sum argon2id-0.
|
205
|
-
|
204
|
+
$ gem fetch argon2id -v 0.5.0
|
205
|
+
Fetching argon2id-0.5.0-arm64-darwin.gem
|
206
|
+
Downloaded argon2id-0.5.0-arm64-darwin
|
207
|
+
$ sha256sum argon2id-0.5.0-arm64-darwin.gem
|
208
|
+
871e9d9bcad09e75620ce9ddd32cd99a4ebc3a6db1516e487680787faa7368a3 argon2id-0.5.0-arm64-darwin.gem
|
206
209
|
```
|
207
210
|
|
208
211
|
[GPG](https://www.gnupg.org/) signatures are attached to each release (the
|
@@ -212,8 +215,8 @@ from a public keyserver, e.g. `gpg --keyserver keyserver.ubuntu.com --recv-key
|
|
212
215
|
0x39AC3530070E0F75`):
|
213
216
|
|
214
217
|
```console
|
215
|
-
$ gpg --verify argon2id-0.
|
216
|
-
gpg: Signature made Sat 2 Nov
|
218
|
+
$ gpg --verify argon2id-0.5.0-arm64-darwin.gem.sig argon2id-0.5.0-arm64-darwin.gem
|
219
|
+
gpg: Signature made Sat 2 Nov 21:09:51 2024 GMT
|
217
220
|
gpg: using RSA key 702609D9C790F45B577D7BEC39AC3530070E0F75
|
218
221
|
gpg: Good signature from "Paul Mucur <mudge@mudge.name>" [unknown]
|
219
222
|
gpg: aka "Paul Mucur <paul@ghostcassette.com>" [unknown]
|
data/Rakefile
CHANGED
@@ -20,16 +20,20 @@ ENV["RUBY_CC_VERSION"] = %w[3.3.0 3.2.0 3.1.0 3.0.0 2.7.0 2.6.0].join(":")
|
|
20
20
|
|
21
21
|
gemspec = Gem::Specification.load("argon2id.gemspec")
|
22
22
|
|
23
|
-
if RUBY_PLATFORM == "java"
|
24
|
-
gemspec.files.reject! { |path| File.fnmatch?("ext/*", path) }
|
25
|
-
gemspec.extensions.clear
|
26
|
-
gemspec.platform = Gem::Platform.new("java")
|
27
|
-
gemspec.required_ruby_version = ">= 3.1.0"
|
28
|
-
end
|
29
|
-
|
30
23
|
Gem::PackageTask.new(gemspec).define
|
31
24
|
|
25
|
+
namespace :java do
|
26
|
+
java_gemspec = gemspec.dup
|
27
|
+
java_gemspec.files.reject! { |path| File.fnmatch?("ext/*", path) }
|
28
|
+
java_gemspec.extensions.clear
|
29
|
+
java_gemspec.platform = Gem::Platform.new("java")
|
30
|
+
java_gemspec.required_ruby_version = ">= 3.1.0"
|
31
|
+
|
32
|
+
Gem::PackageTask.new(java_gemspec).define
|
33
|
+
end
|
34
|
+
|
32
35
|
Rake::ExtensionTask.new("argon2id", gemspec) do |e|
|
36
|
+
e.lib_dir = "lib/argon2id"
|
33
37
|
e.cross_compile = true
|
34
38
|
e.cross_platform = cross_platforms
|
35
39
|
end
|
@@ -57,15 +61,6 @@ namespace :gem do
|
|
57
61
|
SCRIPT
|
58
62
|
end
|
59
63
|
end
|
60
|
-
|
61
|
-
desc "Compile gem for JRuby"
|
62
|
-
task :jruby do
|
63
|
-
RakeCompilerDock.sh <<~SCRIPT, rubyvm: "jruby", platform: "jruby", verbose: true
|
64
|
-
gem install bundler --no-document &&
|
65
|
-
bundle &&
|
66
|
-
bundle exec rake gem
|
67
|
-
SCRIPT
|
68
|
-
end
|
69
64
|
end
|
70
65
|
|
71
66
|
task default: [:compile, :test]
|
data/argon2id.gemspec
CHANGED
@@ -45,11 +45,10 @@ Gem::Specification.new do |s|
|
|
45
45
|
"ext/argon2id/libargon2/thread.c",
|
46
46
|
"ext/argon2id/libargon2/thread.h",
|
47
47
|
"lib/argon2id.rb",
|
48
|
+
"lib/argon2id/extension.rb",
|
48
49
|
"lib/argon2id/password.rb",
|
49
50
|
"lib/argon2id/version.rb",
|
50
|
-
"test/
|
51
|
-
"test/test_password.rb",
|
52
|
-
"test/test_verify.rb"
|
51
|
+
"test/test_password.rb"
|
53
52
|
]
|
54
53
|
s.rdoc_options = ["--main", "README.md"]
|
55
54
|
|
data/ext/argon2id/argon2id.c
CHANGED
@@ -5,21 +5,11 @@
|
|
5
5
|
|
6
6
|
#define UNUSED(x) (void)(x)
|
7
7
|
|
8
|
-
VALUE mArgon2id, cArgon2idError;
|
9
|
-
|
10
|
-
|
11
|
-
*
|
12
|
-
* Hashes a password with Argon2id, producing an encoded hash.
|
13
|
-
*
|
14
|
-
* - +t_cost+: number of iterations
|
15
|
-
* - +m_cost+: sets memory usage to +m_cost+ kibibytes
|
16
|
-
* - +parallelism+: number of threads and compute lanes
|
17
|
-
* - +pwd+: the password
|
18
|
-
* - +salt+: the salt
|
19
|
-
* - +output_len+: desired length of the hash in bytes
|
20
|
-
*/
|
8
|
+
VALUE mArgon2id, cArgon2idError, cArgon2idPassword;
|
9
|
+
ID id_encoded;
|
10
|
+
|
21
11
|
static VALUE
|
22
|
-
rb_argon2id_hash_encoded(VALUE
|
12
|
+
rb_argon2id_hash_encoded(VALUE klass, VALUE iterations, VALUE memory, VALUE threads, VALUE pwd, VALUE salt, VALUE hashlen)
|
23
13
|
{
|
24
14
|
uint32_t t_cost, m_cost, parallelism;
|
25
15
|
size_t encodedlen, outlen;
|
@@ -27,7 +17,7 @@ rb_argon2id_hash_encoded(VALUE module, VALUE iterations, VALUE memory, VALUE thr
|
|
27
17
|
int result;
|
28
18
|
VALUE hash;
|
29
19
|
|
30
|
-
UNUSED(
|
20
|
+
UNUSED(klass);
|
31
21
|
|
32
22
|
t_cost = FIX2INT(iterations);
|
33
23
|
m_cost = FIX2INT(memory);
|
@@ -53,16 +43,12 @@ rb_argon2id_hash_encoded(VALUE module, VALUE iterations, VALUE memory, VALUE thr
|
|
53
43
|
return hash;
|
54
44
|
}
|
55
45
|
|
56
|
-
/* call-seq: verify(encoded, pwd)
|
57
|
-
*
|
58
|
-
* Verifies a password against an encoded string.
|
59
|
-
*/
|
60
46
|
static VALUE
|
61
|
-
rb_argon2id_verify(VALUE
|
47
|
+
rb_argon2id_verify(VALUE self, VALUE pwd) {
|
62
48
|
int result;
|
49
|
+
VALUE encoded;
|
63
50
|
|
64
|
-
|
65
|
-
|
51
|
+
encoded = rb_ivar_get(self, id_encoded);
|
66
52
|
result = argon2id_verify(StringValueCStr(encoded), StringValuePtr(pwd), RSTRING_LEN(pwd));
|
67
53
|
if (result == ARGON2_OK) {
|
68
54
|
return Qtrue;
|
@@ -80,8 +66,11 @@ rb_argon2id_verify(VALUE module, VALUE encoded, VALUE pwd) {
|
|
80
66
|
void
|
81
67
|
Init_argon2id(void)
|
82
68
|
{
|
69
|
+
id_encoded = rb_intern("@encoded");
|
70
|
+
|
83
71
|
mArgon2id = rb_define_module("Argon2id");
|
84
72
|
cArgon2idError = rb_define_class_under(mArgon2id, "Error", rb_eStandardError);
|
85
|
-
|
86
|
-
|
73
|
+
cArgon2idPassword = rb_define_class_under(mArgon2id, "Password", rb_cObject);
|
74
|
+
rb_define_private_method(rb_singleton_class(cArgon2idPassword), "hash_encoded", rb_argon2id_hash_encoded, 6);
|
75
|
+
rb_define_private_method(cArgon2idPassword, "verify", rb_argon2id_verify, 1);
|
87
76
|
}
|
data/ext/argon2id/extconf.rb
CHANGED
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if RUBY_PLATFORM == "java"
|
4
|
+
require "java"
|
5
|
+
require "openssl"
|
6
|
+
|
7
|
+
module Argon2id
|
8
|
+
Error = Class.new(StandardError)
|
9
|
+
|
10
|
+
class Password
|
11
|
+
def self.hash_encoded(t_cost, m_cost, parallelism, pwd, salt, hashlen)
|
12
|
+
raise Error, "Salt is too short" if salt.empty?
|
13
|
+
|
14
|
+
salt_bytes = salt.to_java_bytes
|
15
|
+
output = Java::byte[hashlen].new
|
16
|
+
params = Java::OrgBouncycastleCryptoParams::Argon2Parameters::Builder
|
17
|
+
.new(Java::OrgBouncycastleCryptoParams::Argon2Parameters::ARGON2_id)
|
18
|
+
.with_salt(salt_bytes)
|
19
|
+
.with_parallelism(parallelism)
|
20
|
+
.with_memory_as_kb(m_cost)
|
21
|
+
.with_iterations(t_cost)
|
22
|
+
.build
|
23
|
+
generator = Java::OrgBouncycastleCryptoGenerators::Argon2BytesGenerator.new
|
24
|
+
|
25
|
+
generator.init(params)
|
26
|
+
generator.generate_bytes(pwd.to_java_bytes, output)
|
27
|
+
|
28
|
+
encoder = Java::JavaUtil::Base64.get_encoder.without_padding
|
29
|
+
encoded_salt = encoder.encode_to_string(salt_bytes)
|
30
|
+
encoded_output = encoder.encode_to_string(output)
|
31
|
+
|
32
|
+
"$argon2id$v=19$m=#{m_cost},t=#{t_cost},p=#{parallelism}" \
|
33
|
+
"$#{encoded_salt}$#{encoded_output}"
|
34
|
+
rescue Java::JavaLang::IllegalStateException => e
|
35
|
+
raise Error, e.message
|
36
|
+
end
|
37
|
+
|
38
|
+
private_class_method :hash_encoded
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def verify(pwd)
|
43
|
+
other_output = Java::byte[output.bytesize].new
|
44
|
+
params = Java::OrgBouncycastleCryptoParams::Argon2Parameters::Builder
|
45
|
+
.new(Java::OrgBouncycastleCryptoParams::Argon2Parameters::ARGON2_id)
|
46
|
+
.with_salt(salt.to_java_bytes)
|
47
|
+
.with_parallelism(parallelism)
|
48
|
+
.with_memory_as_kb(m_cost)
|
49
|
+
.with_iterations(t_cost)
|
50
|
+
.build
|
51
|
+
generator = Java::OrgBouncycastleCryptoGenerators::Argon2BytesGenerator.new
|
52
|
+
generator.init(params)
|
53
|
+
generator.generate_bytes(pwd.to_java_bytes, other_output)
|
54
|
+
|
55
|
+
Java::OrgBouncycastleUtil::Arrays.constant_time_are_equal?(
|
56
|
+
output.to_java_bytes,
|
57
|
+
other_output
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
else
|
63
|
+
begin
|
64
|
+
::RUBY_VERSION =~ /(\d+\.\d+)/
|
65
|
+
require_relative "#{Regexp.last_match(1)}/argon2id"
|
66
|
+
rescue LoadError
|
67
|
+
require "argon2id/argon2id"
|
68
|
+
end
|
69
|
+
end
|
data/lib/argon2id/password.rb
CHANGED
@@ -25,7 +25,6 @@ module Argon2id
|
|
25
25
|
#
|
26
26
|
# You can read various parameters out of a password hash:
|
27
27
|
#
|
28
|
-
# password.type #=> "argon2id"
|
29
28
|
# password.version #=> 19
|
30
29
|
# password.m_cost #=> 19456
|
31
30
|
# password.t_cost #=> 2
|
@@ -36,7 +35,7 @@ module Argon2id
|
|
36
35
|
PATTERN = %r{
|
37
36
|
\A
|
38
37
|
\$
|
39
|
-
|
38
|
+
argon2id
|
40
39
|
(?:\$v=(\d+))?
|
41
40
|
\$m=(\d+)
|
42
41
|
,t=(\d+)
|
@@ -51,9 +50,6 @@ module Argon2id
|
|
51
50
|
# The encoded password hash.
|
52
51
|
attr_reader :encoded
|
53
52
|
|
54
|
-
# The type of the hashing function.
|
55
|
-
attr_reader :type
|
56
|
-
|
57
53
|
# The version number of the hashing function.
|
58
54
|
attr_reader :version
|
59
55
|
|
@@ -93,7 +89,7 @@ module Argon2id
|
|
93
89
|
# #=> "$argon2id$v=19$m=12288,t=3,p=1$JigW7fFn+N3NImt+aWpuzw$eM5F1cKeIBALNTU6LuWra75Zi2nymGvQLWzJzVFv0Nc"
|
94
90
|
def self.create(pwd, t_cost: Argon2id.t_cost, m_cost: Argon2id.m_cost, parallelism: Argon2id.parallelism, salt_len: Argon2id.salt_len, output_len: Argon2id.output_len)
|
95
91
|
new(
|
96
|
-
|
92
|
+
hash_encoded(
|
97
93
|
Integer(t_cost),
|
98
94
|
Integer(m_cost),
|
99
95
|
Integer(parallelism),
|
@@ -113,13 +109,12 @@ module Argon2id
|
|
113
109
|
raise ArgumentError, "invalid hash" unless PATTERN =~ String(encoded)
|
114
110
|
|
115
111
|
@encoded = $&
|
116
|
-
@
|
117
|
-
@
|
118
|
-
@
|
119
|
-
@
|
120
|
-
@
|
121
|
-
@
|
122
|
-
@output = $7.unpack1("m")
|
112
|
+
@version = Integer($1 || 0x10)
|
113
|
+
@m_cost = Integer($2)
|
114
|
+
@t_cost = Integer($3)
|
115
|
+
@parallelism = Integer($4)
|
116
|
+
@salt = $5.unpack1("m")
|
117
|
+
@output = $6.unpack1("m")
|
123
118
|
end
|
124
119
|
|
125
120
|
# Return the encoded password hash.
|
@@ -132,7 +127,7 @@ module Argon2id
|
|
132
127
|
# password == "password" #=> true
|
133
128
|
# password == "notpassword" #=> false
|
134
129
|
def ==(other)
|
135
|
-
|
130
|
+
verify(String(other))
|
136
131
|
end
|
137
132
|
|
138
133
|
alias_method :is_password?, :==
|
data/lib/argon2id/version.rb
CHANGED
data/lib/argon2id.rb
CHANGED
@@ -1,18 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require "openssl"
|
5
|
-
else
|
6
|
-
begin
|
7
|
-
::RUBY_VERSION =~ /(\d+\.\d+)/
|
8
|
-
require_relative "#{Regexp.last_match(1)}/argon2id.so"
|
9
|
-
rescue LoadError
|
10
|
-
require "argon2id.so"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
require "argon2id/version"
|
3
|
+
require "argon2id/extension"
|
15
4
|
require "argon2id/password"
|
5
|
+
require "argon2id/version"
|
16
6
|
|
17
7
|
module Argon2id
|
18
8
|
# The default "time cost" of 2 iterations recommended by OWASP.
|
@@ -52,57 +42,4 @@ module Argon2id
|
|
52
42
|
# The default desired length of the hash in bytes used by Argon2id::Password.create
|
53
43
|
attr_accessor :output_len
|
54
44
|
end
|
55
|
-
|
56
|
-
if RUBY_PLATFORM == "java"
|
57
|
-
Error = Class.new(StandardError)
|
58
|
-
|
59
|
-
def self.hash_encoded(t_cost, m_cost, parallelism, pwd, salt, hashlen)
|
60
|
-
output = hash_raw(t_cost, m_cost, parallelism, pwd, salt, hashlen)
|
61
|
-
|
62
|
-
encoder = Java::JavaUtil::Base64.get_encoder.without_padding
|
63
|
-
encoded_salt = encoder.encode_to_string(salt.to_java_bytes)
|
64
|
-
encoded_output = encoder.encode_to_string(output)
|
65
|
-
|
66
|
-
"$argon2id$v=19$m=#{Integer(m_cost)},t=#{Integer(t_cost)}," \
|
67
|
-
"p=#{Integer(parallelism)}$#{encoded_salt}$#{encoded_output}"
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.verify(encoded, pwd)
|
71
|
-
password = Password.new(encoded)
|
72
|
-
other_raw = hash_raw(
|
73
|
-
password.t_cost,
|
74
|
-
password.m_cost,
|
75
|
-
password.parallelism,
|
76
|
-
String(pwd),
|
77
|
-
password.salt,
|
78
|
-
password.output.bytesize
|
79
|
-
)
|
80
|
-
|
81
|
-
Java::OrgBouncycastleUtil::Arrays.constant_time_are_equal(
|
82
|
-
password.output.to_java_bytes,
|
83
|
-
other_raw
|
84
|
-
)
|
85
|
-
end
|
86
|
-
|
87
|
-
def self.hash_raw(t_cost, m_cost, parallelism, pwd, salt, hashlen)
|
88
|
-
raise Error, "Salt is too short" if String(salt).empty?
|
89
|
-
|
90
|
-
hash = Java::byte[Integer(hashlen)].new
|
91
|
-
params = Java::OrgBouncycastleCryptoParams::Argon2Parameters::Builder
|
92
|
-
.new(Java::OrgBouncycastleCryptoParams::Argon2Parameters::ARGON2_id)
|
93
|
-
.with_salt(String(salt).to_java_bytes)
|
94
|
-
.with_parallelism(Integer(parallelism))
|
95
|
-
.with_memory_as_kb(Integer(m_cost))
|
96
|
-
.with_iterations(Integer(t_cost))
|
97
|
-
.build
|
98
|
-
generator = Java::OrgBouncycastleCryptoGenerators::Argon2BytesGenerator.new
|
99
|
-
|
100
|
-
generator.init(params)
|
101
|
-
generator.generate_bytes(String(pwd).to_java_bytes, hash)
|
102
|
-
|
103
|
-
hash
|
104
|
-
rescue Java::JavaLang::IllegalStateException => e
|
105
|
-
raise Error, e.message
|
106
|
-
end
|
107
|
-
end
|
108
45
|
end
|
data/test/test_password.rb
CHANGED
@@ -98,6 +98,18 @@ class TestPassword < Minitest::Test
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
+
def test_raises_for_hashes_with_null_bytes
|
102
|
+
assert_raises(ArgumentError) do
|
103
|
+
Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4\x00foo")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_raises_for_non_argon2id_hashes
|
108
|
+
assert_raises(ArgumentError) do
|
109
|
+
Argon2id::Password.new("$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ$iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
101
113
|
def test_salt_supports_versionless_hashes
|
102
114
|
password = Argon2id::Password.new("$argon2id$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
|
103
115
|
|
@@ -110,18 +122,6 @@ class TestPassword < Minitest::Test
|
|
110
122
|
assert Argon2id::Password.new(password) == "password"
|
111
123
|
end
|
112
124
|
|
113
|
-
def test_extracting_type_from_hash
|
114
|
-
password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
|
115
|
-
|
116
|
-
assert_equal "argon2id", password.type
|
117
|
-
end
|
118
|
-
|
119
|
-
def test_extracting_type_from_argoni_hash
|
120
|
-
password = Argon2id::Password.new("$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
|
121
|
-
|
122
|
-
assert_equal "argon2i", password.type
|
123
|
-
end
|
124
|
-
|
125
125
|
def test_extracting_version_from_hash
|
126
126
|
password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
|
127
127
|
|
@@ -175,4 +175,58 @@ class TestPassword < Minitest::Test
|
|
175
175
|
|
176
176
|
assert_equal "\x9D\xFE\xB9\x10\xE8\v\xAD\x03\x11\xFE\xE2\x0F\x9C\x0E+\x12\xC1y\x87\xB4\xCA\xC9\f.\xF5M[0!\xC6\x8B\xFE".b, password.output
|
177
177
|
end
|
178
|
+
|
179
|
+
def test_libargon2_test_case_1
|
180
|
+
password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
|
181
|
+
|
182
|
+
assert password == "password"
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_libargon2_test_case_1_returns_false_with_incorrect_password
|
186
|
+
password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
|
187
|
+
|
188
|
+
refute password == "not password"
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_libargon2_test_case_2
|
192
|
+
password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=2$c29tZXNhbHQ$bQk8UB/VmZZF4Oo79iDXuL5/0ttZwg2f/5U52iv1cDc")
|
193
|
+
|
194
|
+
assert password == "password"
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_encoded_password_does_not_include_trailing_null_byte
|
198
|
+
password = Argon2id::Password.create("password", t_cost: 2, m_cost: 256, salt_len: 8)
|
199
|
+
|
200
|
+
refute password.to_s.end_with?("\x00")
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_raises_with_too_short_output
|
204
|
+
assert_raises(Argon2id::Error) do
|
205
|
+
Argon2id::Password.create("password", t_cost: 2, m_cost: 256, salt_len: 8, output_len: 1)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_raises_with_too_few_threads_and_compute_lanes
|
210
|
+
assert_raises(Argon2id::Error) do
|
211
|
+
Argon2id::Password.create("password", t_cost: 2, m_cost: 256, parallelism: 0, salt_len: 8)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_raises_with_too_small_memory_cost
|
216
|
+
assert_raises(Argon2id::Error) do
|
217
|
+
Argon2id::Password.create("password", t_cost: 2, m_cost: 0, salt_len: 8)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_raises_with_too_small_time_cost
|
222
|
+
assert_raises(Argon2id::Error) do
|
223
|
+
Argon2id::Password.create("password", t_cost: 0, m_cost: 256, salt_len: 8)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_raises_with_too_short_salt
|
228
|
+
assert_raises(Argon2id::Error) do
|
229
|
+
Argon2id::Password.create("password", t_cost: 2, m_cost: 256, salt_len: 0)
|
230
|
+
end
|
231
|
+
end
|
178
232
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: argon2id
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: x64-mingw32
|
6
6
|
authors:
|
7
7
|
- Paul Mucur
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -82,15 +82,14 @@ files:
|
|
82
82
|
- ext/argon2id/libargon2/ref.c
|
83
83
|
- ext/argon2id/libargon2/thread.c
|
84
84
|
- ext/argon2id/libargon2/thread.h
|
85
|
-
- lib/2.6/argon2id.so
|
86
|
-
- lib/2.7/argon2id.so
|
87
|
-
- lib/3.0/argon2id.so
|
88
85
|
- lib/argon2id.rb
|
86
|
+
- lib/argon2id/2.6/argon2id.so
|
87
|
+
- lib/argon2id/2.7/argon2id.so
|
88
|
+
- lib/argon2id/3.0/argon2id.so
|
89
|
+
- lib/argon2id/extension.rb
|
89
90
|
- lib/argon2id/password.rb
|
90
91
|
- lib/argon2id/version.rb
|
91
|
-
- test/test_hash_encoded.rb
|
92
92
|
- test/test_password.rb
|
93
|
-
- test/test_verify.rb
|
94
93
|
homepage: https://github.com/mudge/argon2id
|
95
94
|
licenses:
|
96
95
|
- BSD-3-Clause
|
data/lib/2.6/argon2id.so
DELETED
Binary file
|
data/lib/2.7/argon2id.so
DELETED
Binary file
|
data/lib/3.0/argon2id.so
DELETED
Binary file
|
data/test/test_hash_encoded.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "minitest/autorun"
|
4
|
-
require "argon2id"
|
5
|
-
|
6
|
-
class TestHashEncoded < Minitest::Test
|
7
|
-
def test_valid_password_and_salt_encodes_successfully
|
8
|
-
encoded = Argon2id.hash_encoded(2, 256, 1, "password", "somesalt", 32)
|
9
|
-
|
10
|
-
assert_equal "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4", encoded
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_password_with_parallelism_of_two
|
14
|
-
encoded = Argon2id.hash_encoded(2, 256, 2, "password", "somesalt", 32)
|
15
|
-
|
16
|
-
assert_equal "$argon2id$v=19$m=256,t=2,p=2$c29tZXNhbHQ$bQk8UB/VmZZF4Oo79iDXuL5/0ttZwg2f/5U52iv1cDc", encoded
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_valid_password_does_not_include_trailing_null_byte
|
20
|
-
encoded = Argon2id.hash_encoded(2, 256, 1, "password", "somesalt", 32)
|
21
|
-
|
22
|
-
refute encoded.end_with?("\x00")
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_raises_with_too_short_output
|
26
|
-
assert_raises(Argon2id::Error) do
|
27
|
-
Argon2id.hash_encoded(2, 256, 1, "password", "somesalt", 1)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_raises_with_too_few_lanes
|
32
|
-
assert_raises(Argon2id::Error) do
|
33
|
-
Argon2id.hash_encoded(2, 256, 0, "password", "somesalt", 32)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_raises_with_too_small_memory_cost
|
38
|
-
assert_raises(Argon2id::Error) do
|
39
|
-
Argon2id.hash_encoded(2, 0, 1, "password", "somesalt", 32)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def test_raises_with_too_small_time_cost
|
44
|
-
assert_raises(Argon2id::Error) do
|
45
|
-
Argon2id.hash_encoded(0, 256, 1, "password", "somesalt", 32)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_raises_with_too_short_salt
|
50
|
-
assert_raises(Argon2id::Error) do
|
51
|
-
Argon2id.hash_encoded(2, 256, 1, "password", "", 32)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
data/test/test_verify.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "minitest/autorun"
|
4
|
-
require "argon2id"
|
5
|
-
|
6
|
-
class TestVerify < Minitest::Test
|
7
|
-
def test_returns_true_with_correct_password
|
8
|
-
assert Argon2id.verify(
|
9
|
-
"$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4",
|
10
|
-
"password"
|
11
|
-
)
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_returns_false_with_incorrect_password
|
15
|
-
refute Argon2id.verify(
|
16
|
-
"$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4",
|
17
|
-
"not password"
|
18
|
-
)
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_raises_if_given_invalid_encoded
|
22
|
-
assert_raises(ArgumentError) do
|
23
|
-
Argon2id.verify("", "opensesame")
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_raises_if_given_encoded_with_null_byte
|
28
|
-
assert_raises(ArgumentError) do
|
29
|
-
Argon2id.verify(
|
30
|
-
"$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4\x00foo",
|
31
|
-
"password"
|
32
|
-
)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|