argon2id 0.1.1-x64-mingw-ucrt → 0.2.0-x64-mingw-ucrt

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: dde8a6707628f96bcf7e306e9d4a182f272e08d191be499d42ee1f342112d917
4
- data.tar.gz: 657e39ffb88686496afb9c5966a29441d97098bff2a9dc46d567cd007ba6253a
3
+ metadata.gz: 149699bfff38e1f7cd391844883e177098b0bc36f85d8ce498a50ea34465d28d
4
+ data.tar.gz: 7a8167c794a5e6f5088c4b75e1f264fd35c4ff1f0ec663173335a99355994d44
5
5
  SHA512:
6
- metadata.gz: 70fb55e0ea83c86b714bcb28580bfb29bda272a8ab8ee5b068eeabf6b0010d7c5a6a36463714cb179c3246666ac339e549303238f2c3786deec991da1d88835a
7
- data.tar.gz: ed76be3b06ee436df238bb40e8a53b92ff7c98ed9884d40e2f54e1615e8272b059b4eebdd16dfd8bf51ee7483adcd0b8b0e59f7947573220645fc0bb523156c7
6
+ metadata.gz: 6c2c47641f86448f649fab1c592f3e1a6f6f14e7b5c927c506729a3cd95b770be9df91772280e8a104e2b7225c1e25740a751a7b02de5c4735ab57b655a54a87
7
+ data.tar.gz: ce1b17eb362dcf9687fcf67fd8e96056d2177332da1364a90eb9e63b4ec9a73811b40acefa76440ceb51e5fcd2a417af4a771c6a9df2ce3eb02e71b131edd7b0
data/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ 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.1.2] - 2024-11-01
9
+
10
+ ### Added
11
+
12
+ - The original salt for an `Argon2id::Password` can now be retrieved with
13
+ `Argon2id::Password#salt`
14
+
15
+ ### Changed
16
+
17
+ - Encoded hashes are now validated when initialising an `Argon2id::Password`,
18
+ raising an `ArgumentError` if they are invalid
19
+
20
+ ## [0.1.2] - 2024-11-01
21
+
22
+ ### Fixed
23
+
24
+ - Validate that the encoded hash passed to `Argon2id::Password.new` is a
25
+ null-terminated C string, raising an `ArgumentError` if it contains extra null
26
+ bytes
27
+
8
28
  ## [0.1.1] - 2024-11-01
9
29
 
10
30
  ### Added
@@ -24,5 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
24
44
  reference C implementation of Argon2, the password-hashing function that won
25
45
  the Password Hashing Competition.
26
46
 
47
+ [0.2.0]: https://github.com/mudge/argon2id/releases/tag/v0.2.0
48
+ [0.1.2]: https://github.com/mudge/argon2id/releases/tag/v0.1.2
27
49
  [0.1.1]: https://github.com/mudge/argon2id/releases/tag/v0.1.1
28
50
  [0.1.0]: https://github.com/mudge/argon2id/releases/tag/v0.1.0
data/README.md CHANGED
@@ -5,17 +5,17 @@ function that won the 2015 [Password Hashing Competition][].
5
5
 
6
6
  [![Build Status](https://github.com/mudge/argon2id/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/mudge/argon2id/actions)
7
7
 
8
- **Current version:** 0.1.1
8
+ **Current version:** 0.2.0
9
9
  **Bundled Argon2 version:** libargon2.1 (20190702)
10
10
 
11
11
  ```ruby
12
- Argon2::Password.create("opensesame").to_s
12
+ Argon2id::Password.create("opensesame").to_s
13
13
  #=> "$argon2id$v=19$m=19456,t=2,p=1$ZS2nBFWBpnt28HjtzNOW4w$SQ+p+dIcWbpzWpZQ/ZZFj8IQkyhYZf127U4QdkRmKFU"
14
14
 
15
- Argon2::Password.create("opensesame") == "opensesame"
15
+ Argon2id::Password.create("opensesame") == "opensesame"
16
16
  #=> true
17
17
 
18
- Argon2::Password.new("$argon2id$v=19$m=19456,t=2,p=1$ZS2nBFWBpnt28HjtzNOW4w$SQ+p+dIcWbpzWpZQ/ZZFj8IQkyhYZf127U4QdkRmKFU") == "opensesame"
18
+ Argon2id::Password.new("$argon2id$v=19$m=19456,t=2,p=1$ZS2nBFWBpnt28HjtzNOW4w$SQ+p+dIcWbpzWpZQ/ZZFj8IQkyhYZf127U4QdkRmKFU") == "opensesame"
19
19
  #=> true
20
20
  ```
21
21
 
@@ -142,6 +142,14 @@ password.is_password?("opensesame") #=> true
142
142
  password.is_password?("notopensesame") #=> false
143
143
  ```
144
144
 
145
+ The original salt for a password can be retrieved with `Argon2id::Password#salt`:
146
+
147
+ ```ruby
148
+ password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
149
+ password.salt
150
+ #=> "somesalt"
151
+ ```
152
+
145
153
  ### Errors
146
154
 
147
155
  Any errors returned from Argon2 will be raised as `Argon2id::Error`, e.g.
@@ -176,11 +184,11 @@ notes](https://github.com/mudge/argon2id/releases) for each version and can be
176
184
  checked with `sha256sum`, e.g.
177
185
 
178
186
  ```console
179
- $ gem fetch argon2id -v 0.1.0
180
- Fetching argon2id-0.1.0-arm64-darwin.gem
181
- Downloaded argon2id-0.1.0-arm64-darwin
182
- $ sha256sum argon2id-0.1.0-arm64-darwin.gem
183
- 652ba4ebe4176c3fa944652b5db3bee52670c1e6b76632f921dd1455ec0810aa argon2id-0.1.0-arm64-darwin.gem
187
+ $ gem fetch argon2id -v 0.1.1
188
+ Fetching argon2id-0.1.1-arm64-darwin.gem
189
+ Downloaded argon2id-0.1.1-arm64-darwin
190
+ $ sha256sum argon2id-0.1.1-arm64-darwin.gem
191
+ 8d47464edf847ca52c1d41cac1a9feff376e9a1e7c0a98ab58df846990caa1bb argon2id-0.1.1-arm64-darwin.gem
184
192
  ```
185
193
 
186
194
  [GPG](https://www.gnupg.org/) signatures are attached to each release (the
@@ -190,8 +198,8 @@ from a public keyserver, e.g. `gpg --keyserver keyserver.ubuntu.com --recv-key
190
198
  0x39AC3530070E0F75`):
191
199
 
192
200
  ```console
193
- $ gpg --verify argon2id-0.1.0-arm64-darwin.gem.sig argon2id-0.1.0-arm64-darwin.gem
194
- gpg: Signature made Thu 31 Oct 16:09:45 2024 GMT
201
+ $ gpg --verify argon2id-0.1.1-arm64-darwin.gem.sig argon2id-0.1.1-arm64-darwin.gem
202
+ gpg: Signature made Fri 1 Nov 07:24:16 2024 GMT
195
203
  gpg: using RSA key 702609D9C790F45B577D7BEC39AC3530070E0F75
196
204
  gpg: Good signature from "Paul Mucur <mudge@mudge.name>" [unknown]
197
205
  gpg: aka "Paul Mucur <paul@ghostcassette.com>" [unknown]
data/argon2id.gemspec CHANGED
@@ -53,6 +53,7 @@ Gem::Specification.new do |s|
53
53
  ]
54
54
  s.rdoc_options = ["--main", "README.md"]
55
55
 
56
+ s.add_runtime_dependency("base64")
56
57
  s.add_development_dependency("rake-compiler", "~> 1.2")
57
58
  s.add_development_dependency("rake-compiler-dock", "~> 1.5")
58
59
  s.add_development_dependency("minitest", "~> 5.25")
@@ -7,7 +7,7 @@
7
7
 
8
8
  VALUE mArgon2id, cArgon2idError;
9
9
 
10
- /* call-seq: Argon2id.hash_encode(t_cost, m_cost, parallelism, pwd, salt, output_len)
10
+ /* call-seq: hash_encoded(t_cost, m_cost, parallelism, pwd, salt, output_len)
11
11
  *
12
12
  * Hashes a password with Argon2id, producing an encoded hash.
13
13
  *
@@ -53,7 +53,7 @@ rb_argon2id_hash_encoded(VALUE module, VALUE iterations, VALUE memory, VALUE thr
53
53
  return hash;
54
54
  }
55
55
 
56
- /* call-seq: Argon2id.verify(encoded, pwd)
56
+ /* call-seq: verify(encoded, pwd)
57
57
  *
58
58
  * Verifies a password against an encoded string.
59
59
  */
@@ -63,7 +63,7 @@ rb_argon2id_verify(VALUE module, VALUE encoded, VALUE pwd) {
63
63
 
64
64
  UNUSED(module);
65
65
 
66
- result = argon2id_verify(StringValuePtr(encoded), StringValuePtr(pwd), RSTRING_LEN(pwd));
66
+ result = argon2id_verify(StringValueCStr(encoded), StringValuePtr(pwd), RSTRING_LEN(pwd));
67
67
  if (result == ARGON2_OK) {
68
68
  return Qtrue;
69
69
  }
data/lib/3.1/argon2id.so CHANGED
Binary file
data/lib/3.2/argon2id.so CHANGED
Binary file
data/lib/3.3/argon2id.so CHANGED
Binary file
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "base64"
3
4
  require "openssl"
4
5
 
5
6
  module Argon2id
@@ -17,15 +18,47 @@ module Argon2id
17
18
  # password == "password"
18
19
  # #=> true
19
20
  class Password
21
+ # A regular expression to match valid hashes.
22
+ PATTERN = %r{
23
+ \A
24
+ \$
25
+ argon2(?:id|i|d)
26
+ (?:\$v=\d+)?
27
+ \$m=\d+
28
+ ,t=\d+
29
+ ,p=\d+
30
+ \$
31
+ (?<base64_salt>[a-zA-Z0-9+/]+)
32
+ \$
33
+ [a-zA-Z0-9+/]+
34
+ \z
35
+ }x.freeze
36
+
37
+ # The encoded password hash.
20
38
  attr_reader :encoded
21
39
 
22
- # Create a new Password object that hashes a given plain text password.
40
+ # The salt.
41
+ attr_reader :salt
42
+
43
+ # Create a new Password object that hashes a given plain text password +pwd+.
23
44
  #
24
45
  # - +:t_cost+: integer (default 2) the "time cost" given as a number of iterations
25
46
  # - +:m_cost+: integer (default 19456) the "memory cost" given in kibibytes
26
47
  # - +:parallelism+: integer (default 1) the number of threads and compute lanes to use
27
48
  # - +:salt_len+: integer (default 16) the salt size in bytes
28
49
  # - +:output_len+: integer (default 32) the desired length of the hash in bytes
50
+ #
51
+ # For example, with the default configuration:
52
+ #
53
+ # password = Argon2id::Password.create("password")
54
+ # password.to_s
55
+ # #=> "$argon2id$v=19$m=19456,t=2,p=1$FI8yp1gXbthJCskBlpKPoQ$nOfCCpS2r+I8GRN71cZND4cskn7YKBNzuHUEO3YpY2s"
56
+ #
57
+ # When overriding the configuration:
58
+ #
59
+ # password = Argon2id::Password.create("password", t_cost: 3, m_cost: 12288)
60
+ # password.to_s
61
+ # #=> "$argon2id$v=19$m=12288,t=3,p=1$JigW7fFn+N3NImt+aWpuzw$eM5F1cKeIBALNTU6LuWra75Zi2nymGvQLWzJzVFv0Nc"
29
62
  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)
30
63
  new(
31
64
  Argon2id.hash_encoded(
@@ -42,8 +75,15 @@ module Argon2id
42
75
  # call-seq: Argon2id::Password.new(encoded)
43
76
  #
44
77
  # Create a new Password with the given encoded password hash.
78
+ #
79
+ # password = Argon2id::Password.new("$argon2id$v=19$m=19456,t=2,p=1$FI8yp1gXbthJCskBlpKPoQ$nOfCCpS2r+I8GRN71cZND4cskn7YKBNzuHUEO3YpY2s")
80
+ #
81
+ # Raises an ArgumentError if given an invalid hash.
45
82
  def initialize(encoded)
83
+ raise ArgumentError, "invalid hash" unless PATTERN =~ encoded
84
+
46
85
  @encoded = encoded
86
+ @salt = Base64.decode64(Regexp.last_match(:base64_salt))
47
87
  end
48
88
 
49
89
  # Return the encoded password hash.
@@ -53,6 +93,10 @@ module Argon2id
53
93
 
54
94
  # Compare the password with given plain text, returning true if it verifies
55
95
  # successfully.
96
+ #
97
+ # password = Argon2id::Password.new("$argon2id$v=19$m=19456,t=2,p=1$FI8yp1gXbthJCskBlpKPoQ$nOfCCpS2r+I8GRN71cZND4cskn7YKBNzuHUEO3YpY2s")
98
+ # password == "password" #=> true
99
+ # password == "notpassword" #=> false
56
100
  def ==(other)
57
101
  Argon2id.verify(encoded, String(other))
58
102
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Argon2id
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/argon2id.rb CHANGED
@@ -11,10 +11,19 @@ require "argon2id/version"
11
11
  require "argon2id/password"
12
12
 
13
13
  module Argon2id
14
+ # The default "time cost" of 2 iterations recommended by OWASP.
14
15
  DEFAULT_T_COST = 2
15
- DEFAULT_M_COST = 19456
16
+
17
+ # The default "memory cost" of 19 mebibytes recommended by OWASP.
18
+ DEFAULT_M_COST = 19_456
19
+
20
+ # The default 1 thread and compute lane recommended by OWASP.
16
21
  DEFAULT_PARALLELISM = 1
22
+
23
+ # The default salt length of 16 bytes.
17
24
  DEFAULT_SALT_LEN = 16
25
+
26
+ # The default desired hash length of 32 bytes.
18
27
  DEFAULT_OUTPUT_LEN = 32
19
28
 
20
29
  @t_cost = DEFAULT_T_COST
@@ -74,13 +74,33 @@ class TestPassword < Minitest::Test
74
74
  refute password.is_password?("notopensesame")
75
75
  end
76
76
 
77
- def test_raises_if_verifying_with_invalid_encoded_password
78
- password = Argon2id::Password.new("invalid")
77
+ def test_salt_returns_the_original_salt
78
+ password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
79
79
 
80
- error = assert_raises(Argon2id::Error) do
81
- password.is_password?("opensesame")
80
+ assert_equal "somesalt", password.salt
81
+ end
82
+
83
+ def test_salt_returns_raw_bytes
84
+ password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$KmIxrXv4lrnSJPO0LN7Gdw$lB3724qLPL9MNi10lkvIb4VxIk3q841CLvq0WTCZ0VQ")
85
+
86
+ assert_equal "*b1\xAD{\xF8\x96\xB9\xD2$\xF3\xB4,\xDE\xC6w".b, password.salt
87
+ end
88
+
89
+ def test_raises_for_invalid_hashes
90
+ assert_raises(ArgumentError) do
91
+ Argon2id::Password.new("not a valid hash")
82
92
  end
93
+ end
94
+
95
+ def test_raises_for_partial_hashes
96
+ assert_raises(ArgumentError) do
97
+ Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$KmIxrXv4lrnSJPO0LN7Gdw")
98
+ end
99
+ end
100
+
101
+ def test_salt_supports_versionless_hashes
102
+ password = Argon2id::Password.new("$argon2id$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
83
103
 
84
- assert_equal "Decoding failed", error.message
104
+ assert_equal "somesalt", password.salt
85
105
  end
86
106
  end
data/test/test_verify.rb CHANGED
@@ -5,15 +5,17 @@ require "argon2id"
5
5
 
6
6
  class TestVerify < Minitest::Test
7
7
  def test_returns_true_with_correct_password
8
- encoded = Argon2id.hash_encoded(2, 256, 1, "password", "somesalt", 32)
9
-
10
- assert Argon2id.verify(encoded, "password")
8
+ assert Argon2id.verify(
9
+ "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4",
10
+ "password"
11
+ )
11
12
  end
12
13
 
13
14
  def test_returns_false_with_incorrect_password
14
- encoded = Argon2id.hash_encoded(2, 256, 1, "password", "somesalt", 32)
15
-
16
- refute Argon2id.verify(encoded, "notopensesame")
15
+ refute Argon2id.verify(
16
+ "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4",
17
+ "not password"
18
+ )
17
19
  end
18
20
 
19
21
  def test_raises_if_given_invalid_encoded
@@ -21,4 +23,13 @@ class TestVerify < Minitest::Test
21
23
  Argon2id.verify("", "opensesame")
22
24
  end
23
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
24
35
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: argon2id
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: x64-mingw-ucrt
6
6
  authors:
7
7
  - Paul Mucur
@@ -10,6 +10,20 @@ bindir: bin
10
10
  cert_chain: []
11
11
  date: 2024-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: base64
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rake-compiler
15
29
  requirement: !ruby/object:Gem::Requirement