argon2id 0.2.1 → 0.3.0

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: 4db6c17aba7494ec3513051e649f3ceda78b2da64a0fd1b326cf4d1d87c157c3
4
- data.tar.gz: 20128abfe853bf2cd2013b2ac366a7a5220025ed8c222d65c4ccbdff99cbdbfd
3
+ metadata.gz: 37869678ea2afe9b0cd0ae0aa40d74dc697413d1184782bb9cce45e09c1bcba0
4
+ data.tar.gz: '095f548a9967a7f228d03893530314731e18a1796a4eadc58fae1147f4450df5'
5
5
  SHA512:
6
- metadata.gz: 29a68d9fc61f3effd8eb6fcb017e13a02cd7e4a24b529059694b682ab452a0184fb63ad437dc406a75fd8f75e0759e683af5bb409d52abcfe43cc3aa578cf3de
7
- data.tar.gz: 8b5a8fbc302163efa94e344ae1bcf4c523a84d487402b98f4e80881dc2eec4d485551e18c8f249e5b515fd797fb826ed6d580f2c5289d6663f2648b12d96fac5
6
+ metadata.gz: 0ed644a214ce98c680ff9ab5e6cb423e683f318bfd191d94711139494483a07b6496c064cda803fd8819858aeceabaa67464dcc6afd23b07ac1a9ecce690c070
7
+ data.tar.gz: 10cdce7ed52f9d9774b1b4846b100a03797913351a16eba1fa2fce251c901a38787f4a4adf00899e5282e90e0e2c9fed524958a43006bb39a29e7c88d15dce29
data/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ 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.3.0] - 2024-11-01
9
+
10
+ ### Added
11
+
12
+ - Expose all parameters of a hash through new readers on `Argon2id::Password`:
13
+ namely, `type`, `version`, `m_cost`, `t_cost`, and `parallelism`
14
+
15
+ ### Changed
16
+
17
+ - Remove the dependency on the `base64` gem by inlining the definition of
18
+ `Base64.decode64` (thanks to @etiennebarrie for the tip)
19
+
8
20
  ## [0.2.1] - 2024-11-01
9
21
 
10
22
  ### Added
@@ -51,6 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
51
63
  reference C implementation of Argon2, the password-hashing function that won
52
64
  the Password Hashing Competition.
53
65
 
66
+ [0.3.0]: https://github.com/mudge/argon2id/releases/tag/v0.3.0
54
67
  [0.2.1]: https://github.com/mudge/argon2id/releases/tag/v0.2.1
55
68
  [0.2.0]: https://github.com/mudge/argon2id/releases/tag/v0.2.0
56
69
  [0.1.2]: https://github.com/mudge/argon2id/releases/tag/v0.1.2
data/README.md CHANGED
@@ -5,18 +5,19 @@ 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.2.1
8
+ **Current version:** 0.3.0
9
9
  **Bundled Argon2 version:** libargon2.1 (20190702)
10
10
 
11
11
  ```ruby
12
- Argon2id::Password.create("opensesame").to_s
13
- #=> "$argon2id$v=19$m=19456,t=2,p=1$ZS2nBFWBpnt28HjtzNOW4w$SQ+p+dIcWbpzWpZQ/ZZFj8IQkyhYZf127U4QdkRmKFU"
12
+ Argon2id::Password.create("password").to_s
13
+ #=> "$argon2id$v=19$m=19456,t=2,p=1$agNV6OfDL1OwE44WdrFCJw$ITrBwvCsW4b5GjgZuL67RCcvVMEWBWXtASc9TVyI3rY"
14
14
 
15
- Argon2id::Password.create("opensesame") == "opensesame"
16
- #=> true
15
+ password = Argon2id::Password.new("$argon2id$v=19$m=19456,t=2,p=1$ZS2nBFWBpnt28HjtzNOW4w$SQ+p+dIcWbpzWpZQ/ZZFj8IQkyhYZf127U4QdkRmKFU")
16
+ password == "password" #=> true
17
+ password == "not password" #=> false
17
18
 
18
- Argon2id::Password.new("$argon2id$v=19$m=19456,t=2,p=1$ZS2nBFWBpnt28HjtzNOW4w$SQ+p+dIcWbpzWpZQ/ZZFj8IQkyhYZf127U4QdkRmKFU") == "opensesame"
19
- #=> true
19
+ password.m_cost #=> 19456
20
+ password.salt #=> "e-\xA7\x04U\x81\xA6{v\xF0x\xED\xCC\xD3\x96\xE3"
20
21
  ```
21
22
 
22
23
  ## Table of contents
@@ -142,12 +143,16 @@ password.is_password?("opensesame") #=> true
142
143
  password.is_password?("notopensesame") #=> false
143
144
  ```
144
145
 
145
- The original salt for a password can be retrieved with `Argon2id::Password#salt`:
146
+ The various parameters for the password can be retrieved:
146
147
 
147
148
  ```ruby
148
149
  password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
149
- password.salt
150
- #=> "somesalt"
150
+ password.type #=> "argon2id"
151
+ password.version #=> 19
152
+ password.m_cost #=> 256
153
+ password.t_cost #=> 2
154
+ password.parallelism #=> 1
155
+ password.salt #=> "somesalt"
151
156
  ```
152
157
 
153
158
  ### Errors
@@ -155,9 +160,8 @@ password.salt
155
160
  Any errors returned from Argon2 will be raised as `Argon2id::Error`, e.g.
156
161
 
157
162
  ```ruby
158
- password = Argon2id::Password.new("not a valid hash encoding")
159
- password == "opensesame"
160
- # Decoding failed (Argon2id::Error)
163
+ Argon2id::Password.create("password", salt_len: 0)
164
+ # Salt is too short (Argon2id::Error)
161
165
  ```
162
166
 
163
167
  ## Requirements
@@ -184,11 +188,11 @@ notes](https://github.com/mudge/argon2id/releases) for each version and can be
184
188
  checked with `sha256sum`, e.g.
185
189
 
186
190
  ```console
187
- $ gem fetch argon2id -v 0.2.0
188
- Fetching argon2id-0.2.0-arm64-darwin.gem
189
- Downloaded argon2id-0.2.0-arm64-darwin
190
- $ sha256sum argon2id-0.2.0-arm64-darwin.gem
191
- ce1fa632393e814da750f44146dc6de1353e4b24746fb94f6f4ea748b9dad26b argon2id-0.2.0-arm64-darwin.gem
191
+ $ gem fetch argon2id -v 0.2.1
192
+ Fetching argon2id-0.2.1-arm64-darwin.gem
193
+ Downloaded argon2id-0.2.1-arm64-darwin
194
+ $ sha256sum argon2id-0.2.1-arm64-darwin.gem
195
+ aea93700e989e421dd4e66b99038b9fec1acc9a265fe9d35e2100ceb5c18e5a9 argon2id-0.2.1-arm64-darwin.gem
192
196
  ```
193
197
 
194
198
  [GPG](https://www.gnupg.org/) signatures are attached to each release (the
@@ -198,8 +202,8 @@ from a public keyserver, e.g. `gpg --keyserver keyserver.ubuntu.com --recv-key
198
202
  0x39AC3530070E0F75`):
199
203
 
200
204
  ```console
201
- $ gpg --verify argon2id-0.2.0-arm64-darwin.gem.sig argon2id-0.2.0-arm64-darwin.gem
202
- gpg: Signature made Fri 1 Nov 14:48:57 2024 GMT
205
+ $ gpg --verify argon2id-0.2.1-arm64-darwin.gem.sig argon2id-0.2.1-arm64-darwin.gem
206
+ gpg: Signature made Fri 1 Nov 15:06:30 2024 GMT
203
207
  gpg: using RSA key 702609D9C790F45B577D7BEC39AC3530070E0F75
204
208
  gpg: Good signature from "Paul Mucur <mudge@mudge.name>" [unknown]
205
209
  gpg: aka "Paul Mucur <paul@ghostcassette.com>" [unknown]
data/argon2id.gemspec CHANGED
@@ -53,7 +53,6 @@ Gem::Specification.new do |s|
53
53
  ]
54
54
  s.rdoc_options = ["--main", "README.md"]
55
55
 
56
- s.add_runtime_dependency("base64")
57
56
  s.add_development_dependency("rake-compiler", "~> 1.2")
58
57
  s.add_development_dependency("rake-compiler-dock", "~> 1.5")
59
58
  s.add_development_dependency("minitest", "~> 5.25")
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "base64"
4
3
  require "openssl"
5
4
 
6
5
  module Argon2id
@@ -12,23 +11,38 @@ module Argon2id
12
11
  # password.to_s
13
12
  # #=> "$argon2id$v=19$m=19456,t=2,p=1$+Lrjry9Ifq0poLr15OGU1Q$utkDvejJB0ugwm4s9+a+vF6+1a/W+Y3CYa5Wte/85ig"
14
13
  #
15
- # To verify an encoded Argon2id password hash, use Argon2id::Password.new:
14
+ # To wrap an encoded Argon2id password hash, use Argon2id::Password.new:
16
15
  #
17
- # password = Argon2id::Password.new("$argon2id$v=19$m=19456,t=2,p=1$+Lrjry9Ifq0poLr15OGU1Q$utkDvejJB0ugwm4s9+a+vF6+1a/W+Y3CYa5Wte/85ig")
18
- # password == "password"
19
- # #=> true
16
+ # password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
17
+ #
18
+ # You can then verify it matches a given plain text:
19
+ #
20
+ # password == "password" #=> true
21
+ # password == "not password" #=> false
22
+ #
23
+ # password.is_password?("password") #=> true
24
+ # password.is_password?("not password") #=> false
25
+ #
26
+ # You can read various parameters out of a password hash:
27
+ #
28
+ # password.type #=> "argon2id"
29
+ # password.version #=> 19
30
+ # password.m_cost #=> 19456
31
+ # password.t_cost #=> 2
32
+ # password.parallelism #=> 1
33
+ # password.salt #=> "somesalt"
20
34
  class Password
21
35
  # A regular expression to match valid hashes.
22
36
  PATTERN = %r{
23
37
  \A
24
38
  \$
25
- argon2(?:id|i|d)
26
- (?:\$v=\d+)?
27
- \$m=\d+
28
- ,t=\d+
29
- ,p=\d+
39
+ (argon2(?:id|i|d))
40
+ (?:\$v=(\d+))?
41
+ \$m=(\d+)
42
+ ,t=(\d+)
43
+ ,p=(\d+)
30
44
  \$
31
- (?<base64_salt>[a-zA-Z0-9+/]+)
45
+ ([a-zA-Z0-9+/]+)
32
46
  \$
33
47
  [a-zA-Z0-9+/]+
34
48
  \z
@@ -37,6 +51,21 @@ module Argon2id
37
51
  # The encoded password hash.
38
52
  attr_reader :encoded
39
53
 
54
+ # The type of the hashing function.
55
+ attr_reader :type
56
+
57
+ # The version number of the hashing function.
58
+ attr_reader :version
59
+
60
+ # The "time cost" of the hashing function.
61
+ attr_reader :t_cost
62
+
63
+ # The "memory cost" of the hashing function.
64
+ attr_reader :m_cost
65
+
66
+ # The number of threads and compute lanes of the hashing function.
67
+ attr_reader :parallelism
68
+
40
69
  # The salt.
41
70
  attr_reader :salt
42
71
 
@@ -82,17 +111,20 @@ module Argon2id
82
111
  def initialize(encoded)
83
112
  raise ArgumentError, "invalid hash" unless PATTERN =~ String(encoded)
84
113
 
85
- @encoded = Regexp.last_match(0)
86
- @salt = Base64.decode64(Regexp.last_match(1))
114
+ @encoded = $&
115
+ @type = $1
116
+ @version = ($2 || 0x10).to_i
117
+ @m_cost = $3.to_i
118
+ @t_cost = $4.to_i
119
+ @parallelism = $5.to_i
120
+ @salt = $6.unpack1("m")
87
121
  end
88
122
 
89
123
  # Return the encoded password hash.
90
- def to_s
91
- encoded
92
- end
124
+ alias_method :to_s, :encoded
93
125
 
94
- # Compare the password with given plain text, returning true if it verifies
95
- # successfully.
126
+ # Compare the password with the given plain text, returning true if it
127
+ # verifies successfully.
96
128
  #
97
129
  # password = Argon2id::Password.new("$argon2id$v=19$m=19456,t=2,p=1$FI8yp1gXbthJCskBlpKPoQ$nOfCCpS2r+I8GRN71cZND4cskn7YKBNzuHUEO3YpY2s")
98
130
  # password == "password" #=> true
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Argon2id
4
- VERSION = "0.2.1"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -109,4 +109,64 @@ class TestPassword < Minitest::Test
109
109
 
110
110
  assert Argon2id::Password.new(password) == "password"
111
111
  end
112
+
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
+ def test_extracting_version_from_hash
126
+ password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
127
+
128
+ assert_equal 19, password.version
129
+ end
130
+
131
+ def test_extracting_version_from_versionless_hash
132
+ password = Argon2id::Password.new("$argon2id$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
133
+
134
+ assert_equal 16, password.version
135
+ end
136
+
137
+ def test_extracting_time_cost_from_hash
138
+ password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
139
+
140
+ assert_equal 2, password.t_cost
141
+ end
142
+
143
+ def test_extracting_time_cost_from_versionless_hash
144
+ password = Argon2id::Password.new("$argon2id$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
145
+
146
+ assert_equal 2, password.t_cost
147
+ end
148
+
149
+ def test_extracting_memory_cost_from_hash
150
+ password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
151
+
152
+ assert_equal 256, password.m_cost
153
+ end
154
+
155
+ def test_extracting_memory_cost_from_versionless_hash
156
+ password = Argon2id::Password.new("$argon2id$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
157
+
158
+ assert_equal 256, password.m_cost
159
+ end
160
+
161
+ def test_extracting_parallelism_from_hash
162
+ password = Argon2id::Password.new("$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
163
+
164
+ assert_equal 1, password.parallelism
165
+ end
166
+
167
+ def test_extracting_parallelism_from_versionless_hash
168
+ password = Argon2id::Password.new("$argon2id$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4")
169
+
170
+ assert_equal 1, password.parallelism
171
+ end
112
172
  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.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Mucur
@@ -10,20 +10,6 @@ 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'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: rake-compiler
29
15
  requirement: !ruby/object:Gem::Requirement