argon2 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +35 -8
- data/lib/argon2/profiles.rb +50 -0
- data/lib/argon2/version.rb +1 -1
- data/lib/argon2.rb +27 -7
- data/sig/argon2.rbs +29 -9
- data/sig/engine.rbs +9 -0
- data/sig/errors.rbs +6 -0
- data/sig/ffi.rbs +3 -3
- data/sig/hash_format.rbs +31 -0
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77cb6034627eab11765cd70555304c694e3f3f20febe4fed4fa986f7c77bc8b1
|
4
|
+
data.tar.gz: 80f8821f1a3f14f45947644f7e2c538ce3287c2c42a32f6d62f12b34c9e16d9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72fa1e22c23e7c7e47fd03270a90af60e95d7891493d877eb961c6b4087999557ca2accb9b5ed1a7bc94fd2e5f05d98688360f941069a946f37bf20f1b0c9506
|
7
|
+
data.tar.gz: dfff839d55b2f7ca06183d1cd6006aa45a79bf249081f039cdd486d53100dc2ea293f789d9a8ffa87aa69fb6d2d4413c35c296e214fb527ee172789d5f7b74cb
|
data/README.md
CHANGED
@@ -27,26 +27,50 @@ Require this in your Gemfile like a typical Ruby gem:
|
|
27
27
|
require 'argon2'
|
28
28
|
```
|
29
29
|
|
30
|
-
To
|
30
|
+
To utilise default costs ([RFC 9106](https://www.rfc-editor.org/rfc/rfc9106#name-parameter-choice)'s lower-memory, second recommended parameters):
|
31
31
|
|
32
32
|
```ruby
|
33
|
-
hasher = Argon2::Password.new
|
33
|
+
hasher = Argon2::Password.new
|
34
34
|
hasher.create("password")
|
35
|
-
=> "$argon2i$v=19$m=65536,t=2,p=1$jL7lLEAjDN+pY2cG1N8D2g$iwj1ueduCvm6B9YVjBSnAHu+6mKzqGmDW745ALR38Uo"
|
36
35
|
```
|
37
36
|
|
38
|
-
|
37
|
+
Alternatively, use this shortcut:
|
39
38
|
|
40
39
|
```ruby
|
41
|
-
|
40
|
+
Argon2::Password.create("password")
|
41
|
+
=> "$argon2i$v=19$m=65536,t=2,p=1$61qkSyYNbUgf3kZH3GtHRw$4CQff9AZ0lWd7uF24RKMzqEiGpzhte1Hp8SO7X8bAew"
|
42
|
+
```
|
43
|
+
|
44
|
+
If your use case can afford the higher memory consumption/cost, you can/should specify to use RFC 9106's first recommended parameters:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
hasher = Argon2::Password.new(profile: :rfc_9106_high_memory)
|
42
48
|
hasher.create("password")
|
49
|
+
=> "$argon2id$v=19$m=2097152,t=1,p=4$LvHa74Yax7uCWPN7P6/oQQ$V1dMt4dfuYSmLpwUTpKUzg+RrXjWzWHlE6NLowBzsAg"
|
43
50
|
```
|
44
51
|
|
45
|
-
|
52
|
+
To generate a hash using one of the other `Argon::Profiles` names:
|
46
53
|
|
47
54
|
```ruby
|
48
|
-
|
49
|
-
|
55
|
+
# Only use this profile in testing env, it's unsafe!
|
56
|
+
hasher = Argon2::Password.new(profile: :unsafe_cheapest)
|
57
|
+
hasher.create("password")
|
58
|
+
=> "$argon2id$v=19$m=8,t=1,p=1$HZZHG3oTqptqgrxWxFic5g$EUokHMU6m6w2AVIEk1MpZBhVwW9Nj+ESRjPwTBVtWpY"
|
59
|
+
```
|
60
|
+
|
61
|
+
The list of named cost profiles are:
|
62
|
+
|
63
|
+
* `:rfc_9106_high_memory`: the first recommended option but is expensive
|
64
|
+
* `:rfc_9106_low_memory`: the second recommended option (default)
|
65
|
+
* `:pre_rfc_9106`: the previous default costs for `ruby-argon2` <= v2.2.0, before offering RFC 9106 named profiles
|
66
|
+
* `:unsafe_cheapest`: Strictly for testing, the minimum costs allowed by Argon2 for the fastest hashing speed
|
67
|
+
|
68
|
+
To generate a hash using specific time and memory cost:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
hasher = Argon2::Password.new(t_cost: 2, m_cost: 16, p_cost: 1)
|
72
|
+
hasher.create("password")
|
73
|
+
=> "$argon2i$v=19$m=65536,t=2,p=1$jL7lLEAjDN+pY2cG1N8D2g$iwj1ueduCvm6B9YVjBSnAHu+6mKzqGmDW745ALR38Uo"
|
50
74
|
```
|
51
75
|
|
52
76
|
You can then use this function to verify a password against a given hash. Will return either true or false.
|
@@ -81,6 +105,9 @@ steep check
|
|
81
105
|
```
|
82
106
|
These tools will need to be installed manually at this time and will be added to Gemfiles after much further testing.
|
83
107
|
|
108
|
+
## Version 2.2.0
|
109
|
+
This version changed the way the build system works to deal with a new version of Rubygems. See https://github.com/technion/ruby-argon2/issues/56.
|
110
|
+
|
84
111
|
## Version 2.0 - Argon 2id
|
85
112
|
Version 2.x upwards will now default to the Argon2id hash format. This is consistent with current recommendations regarding Argon2 usage. It remains capable of verifying existing hashes.
|
86
113
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Argon2
|
4
|
+
# Contains named profiles of different common cost parameter sets
|
5
|
+
class Profiles
|
6
|
+
def self.[](name)
|
7
|
+
name = name.upcase.to_sym
|
8
|
+
raise NotImplementedError unless const_defined?(name)
|
9
|
+
|
10
|
+
const_get(name)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.to_a
|
14
|
+
constants.map(&:downcase)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.to_h
|
18
|
+
to_a.reduce({}) { |h, name| h.update(name => self[name]) }
|
19
|
+
end
|
20
|
+
|
21
|
+
# https://datatracker.ietf.org/doc/html/rfc9106#name-argon2-algorithm
|
22
|
+
# FIRST RECOMMENDED option per RFC 9106.
|
23
|
+
RFC_9106_HIGH_MEMORY = {
|
24
|
+
t_cost: 1,
|
25
|
+
m_cost: 21, # 2 GiB
|
26
|
+
p_cost: 4
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
# SECOND RECOMMENDED option per RFC 9106.
|
30
|
+
RFC_9106_LOW_MEMORY = {
|
31
|
+
t_cost: 3,
|
32
|
+
m_cost: 16, # 64 MiB
|
33
|
+
p_cost: 4
|
34
|
+
}.freeze
|
35
|
+
|
36
|
+
# The default values ruby-argon2 had before using RFC 9106 recommendations
|
37
|
+
PRE_RFC_9106 = {
|
38
|
+
t_cost: 2,
|
39
|
+
m_cost: 16, # 64 MiB
|
40
|
+
p_cost: 1
|
41
|
+
}.freeze
|
42
|
+
|
43
|
+
# Only use for fast testing. Insecure otherwise!
|
44
|
+
UNSAFE_CHEAPEST = {
|
45
|
+
t_cost: 1,
|
46
|
+
m_cost: 3, # 8 KiB
|
47
|
+
p_cost: 1
|
48
|
+
}.freeze
|
49
|
+
end
|
50
|
+
end
|
data/lib/argon2/version.rb
CHANGED
data/lib/argon2.rb
CHANGED
@@ -6,19 +6,26 @@ require 'argon2/version'
|
|
6
6
|
require 'argon2/errors'
|
7
7
|
require 'argon2/engine'
|
8
8
|
require 'argon2/hash_format'
|
9
|
+
require 'argon2/profiles'
|
9
10
|
|
10
11
|
module Argon2
|
11
12
|
# Front-end API for the Argon2 module.
|
12
13
|
class Password
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
# Expose constants for the options supported and default used for passwords.
|
15
|
+
DEFAULT_T_COST = Argon2::Profiles::RFC_9106_LOW_MEMORY[:t_cost]
|
16
|
+
DEFAULT_M_COST = Argon2::Profiles::RFC_9106_LOW_MEMORY[:m_cost]
|
17
|
+
DEFAULT_P_COST = Argon2::Profiles::RFC_9106_LOW_MEMORY[:p_cost]
|
18
|
+
MIN_T_COST = 1
|
19
|
+
MAX_T_COST = 750
|
20
|
+
MIN_M_COST = 3
|
21
|
+
MAX_M_COST = 31
|
22
|
+
MIN_P_COST = 1
|
23
|
+
MAX_P_COST = 8
|
16
24
|
|
17
|
-
|
18
|
-
|
25
|
+
def initialize(options = {})
|
26
|
+
options.update(Profiles[options[:profile]]) if options.key?(:profile)
|
19
27
|
|
20
|
-
|
21
|
-
raise ArgonHashFail, "Invalid p_cost" if @p_cost < 1 || @p_cost > 8
|
28
|
+
init_costs(options)
|
22
29
|
|
23
30
|
@salt_do_not_supply = options[:salt_do_not_supply]
|
24
31
|
@secret = options[:secret]
|
@@ -50,5 +57,18 @@ module Argon2
|
|
50
57
|
|
51
58
|
Argon2::Engine.argon2_verify(pass, hash, secret)
|
52
59
|
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def init_costs(options = {})
|
64
|
+
@t_cost = options[:t_cost] || DEFAULT_T_COST
|
65
|
+
raise ArgonHashFail, "Invalid t_cost" if @t_cost < MIN_T_COST || @t_cost > MAX_T_COST
|
66
|
+
|
67
|
+
@m_cost = options[:m_cost] || DEFAULT_M_COST
|
68
|
+
raise ArgonHashFail, "Invalid m_cost" if @m_cost < MIN_M_COST || @m_cost > MAX_M_COST
|
69
|
+
|
70
|
+
@p_cost = options[:p_cost] || DEFAULT_P_COST
|
71
|
+
raise ArgonHashFail, "Invalid p_cost" if @p_cost < MIN_P_COST || @p_cost > MAX_P_COST
|
72
|
+
end
|
53
73
|
end
|
54
74
|
end
|
data/sig/argon2.rbs
CHANGED
@@ -1,21 +1,41 @@
|
|
1
|
-
# Classes
|
2
1
|
module Argon2
|
2
|
+
# Front-end API for the Argon2 module.
|
3
3
|
class Password
|
4
4
|
@t_cost: Integer
|
5
5
|
@m_cost: Integer
|
6
6
|
@p_cost: Integer
|
7
7
|
@salt: nil | String
|
8
8
|
@secret: nil | String
|
9
|
+
@salt_do_not_supply: nil | String
|
10
|
+
|
11
|
+
# Expose constants for the options supported and default used for passwords.
|
12
|
+
DEFAULT_T_COST: 2
|
13
|
+
|
14
|
+
DEFAULT_M_COST: 16
|
15
|
+
|
16
|
+
DEFAULT_P_COST: 1
|
17
|
+
|
18
|
+
MIN_T_COST: 1
|
19
|
+
|
20
|
+
MAX_T_COST: 750
|
21
|
+
|
22
|
+
MIN_M_COST: 1
|
23
|
+
|
24
|
+
MAX_M_COST: 31
|
25
|
+
|
26
|
+
MIN_P_COST: 1
|
27
|
+
|
28
|
+
MAX_P_COST: 8
|
9
29
|
|
10
30
|
def initialize: (?::Hash[untyped, untyped] options) -> void
|
31
|
+
|
11
32
|
def create: (String pass) -> untyped
|
12
|
-
|
13
|
-
|
14
|
-
def self.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
class ArgonHashFail < StandardError
|
33
|
+
|
34
|
+
# Helper class, just creates defaults and calls hash()
|
35
|
+
def self.create: (String pass, ?::Hash[untyped, untyped] options) -> String
|
36
|
+
|
37
|
+
def self.valid_hash?: (String hash) -> bool
|
38
|
+
|
39
|
+
def self.verify_password: (String pass, String hash, ?String|nil secret) -> bool
|
20
40
|
end
|
21
41
|
end
|
data/sig/engine.rbs
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
module Argon2
|
2
|
+
# SecureRandom is a Ruby module. I have no idea why steep now thinks it's an unknown constant, nor why rbs
|
3
|
+
# prototype has no interest in outputting this.
|
4
|
+
SecureRandom: untyped
|
5
|
+
# Generates a random, binary string for use as a salt.
|
6
|
+
class Engine
|
7
|
+
def self.saltgen: () -> untyped
|
8
|
+
end
|
9
|
+
end
|
data/sig/errors.rbs
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
module Argon2
|
2
|
+
class ArgonHashFail < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
ERRORS: ::Array["ARGON2_OK" | "ARGON2_OUTPUT_PTR_NULL" | "ARGON2_OUTPUT_TOO_SHORT" | "ARGON2_OUTPUT_TOO_LONG" | "ARGON2_PWD_TOO_SHORT" | "ARGON2_PWD_TOO_LONG" | "ARGON2_SALT_TOO_SHORT" | "ARGON2_SALT_TOO_LONG" | "ARGON2_AD_TOO_SHORT" | "ARGON2_AD_TOO_LONG" | "ARGON2_SECRET_TOO_SHORT" | "ARGON2_SECRET_TOO_LONG" | "ARGON2_TIME_TOO_SMALL" | "ARGON2_TIME_TOO_LARGE" | "ARGON2_MEMORY_TOO_LITTLE" | "ARGON2_MEMORY_TOO_MUCH" | "ARGON2_LANES_TOO_FEW" | "ARGON2_LANES_TOO_MANY" | "ARGON2_PWD_PTR_MISMATCH" | "ARGON2_SALT_PTR_MISMATCH" | "ARGON2_SECRET_PTR_MISMATCH" | "ARGON2_AD_PTR_MISMATCH" | "ARGON2_MEMORY_ALLOCATION_ERROR" | "ARGON2_FREE_MEMORY_CBK_NULL" | "ARGON2_ALLOCATE_MEMORY_CBK_NULL" | "ARGON2_INCORRECT_PARAMETER" | "ARGON2_INCORRECT_TYPE" | "ARGON2_OUT_PTR_MISMATCH" | "ARGON2_THREADS_TOO_FEW" | "ARGON2_THREADS_TOO_MANY" | "ARGON2_MISSING_ARGS" | "ARGON2_ENCODING_FAIL" | "ARGON2_DECODING_FAIL" | "ARGON2_THREAD_FAIL"]
|
6
|
+
end
|
data/sig/ffi.rbs
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Argon2
|
2
2
|
# Direct external bindings. Call these methods via the Engine class to ensure points are dealt with
|
3
|
-
module Ext
|
4
|
-
extend FFI::Library
|
5
|
-
end
|
3
|
+
# module Ext
|
4
|
+
# extend FFI::Library
|
5
|
+
# end
|
6
6
|
|
7
7
|
# The engine class shields users from the FFI interface.
|
8
8
|
# It is generally not advised to directly use this class.
|
data/sig/hash_format.rbs
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Argon2
|
2
|
+
#
|
3
|
+
# Get the values from an Argon2 compatible string.
|
4
|
+
#
|
5
|
+
class HashFormat
|
6
|
+
attr_reader variant: untyped
|
7
|
+
|
8
|
+
attr_reader version: untyped
|
9
|
+
|
10
|
+
attr_reader t_cost: untyped
|
11
|
+
|
12
|
+
attr_reader m_cost: untyped
|
13
|
+
|
14
|
+
attr_reader p_cost: untyped
|
15
|
+
|
16
|
+
attr_reader salt: untyped
|
17
|
+
|
18
|
+
attr_reader checksum: untyped
|
19
|
+
|
20
|
+
# FIXME: Reduce complexity/AbcSize
|
21
|
+
# rubocop:disable Metrics/AbcSize
|
22
|
+
def initialize: (untyped digest) -> void
|
23
|
+
|
24
|
+
#
|
25
|
+
# Checks whether a given digest is a valid Argon2 hash.
|
26
|
+
#
|
27
|
+
# Supports 1 and argon2id formats.
|
28
|
+
#
|
29
|
+
def self.valid_hash?: (untyped digest) -> untyped
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: argon2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Technion
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -250,17 +250,21 @@ files:
|
|
250
250
|
- lib/argon2/errors.rb
|
251
251
|
- lib/argon2/ffi_engine.rb
|
252
252
|
- lib/argon2/hash_format.rb
|
253
|
+
- lib/argon2/profiles.rb
|
253
254
|
- lib/argon2/version.rb
|
254
255
|
- sig/argon2.rbs
|
255
256
|
- sig/constants.rbs
|
257
|
+
- sig/engine.rbs
|
258
|
+
- sig/errors.rbs
|
256
259
|
- sig/ffi.rbs
|
260
|
+
- sig/hash_format.rbs
|
257
261
|
- sig/version.rbs
|
258
262
|
homepage: https://github.com/technion/ruby-argon2
|
259
263
|
licenses:
|
260
264
|
- MIT
|
261
265
|
metadata:
|
262
266
|
rubygems_mfa_required: 'true'
|
263
|
-
post_install_message:
|
267
|
+
post_install_message:
|
264
268
|
rdoc_options: []
|
265
269
|
require_paths:
|
266
270
|
- lib
|
@@ -275,8 +279,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
275
279
|
- !ruby/object:Gem::Version
|
276
280
|
version: '0'
|
277
281
|
requirements: []
|
278
|
-
rubygems_version: 3.3.
|
279
|
-
signing_key:
|
282
|
+
rubygems_version: 3.3.15
|
283
|
+
signing_key:
|
280
284
|
specification_version: 4
|
281
285
|
summary: Argon2 Password hashing binding
|
282
286
|
test_files: []
|