argon2id 0.8.0.rc1-arm-linux-musl

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.
@@ -0,0 +1,57 @@
1
+ /*
2
+ * Argon2 reference source code package - reference C implementations
3
+ *
4
+ * Copyright 2015
5
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
6
+ *
7
+ * You may use this work under the terms of a Creative Commons CC0 1.0
8
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
9
+ * these licenses can be found at:
10
+ *
11
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
12
+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * You should have received a copy of both of these licenses along with this
15
+ * software. If not, they may be obtained at the above URLs.
16
+ */
17
+
18
+ #ifndef ENCODING_H
19
+ #define ENCODING_H
20
+ #include "argon2.h"
21
+
22
+ #define ARGON2_MAX_DECODED_LANES UINT32_C(255)
23
+ #define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
24
+ #define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)
25
+
26
+ /*
27
+ * encode an Argon2 hash string into the provided buffer. 'dst_len'
28
+ * contains the size, in characters, of the 'dst' buffer; if 'dst_len'
29
+ * is less than the number of required characters (including the
30
+ * terminating 0), then this function returns ARGON2_ENCODING_ERROR.
31
+ *
32
+ * on success, ARGON2_OK is returned.
33
+ */
34
+ int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
35
+ argon2_type type);
36
+
37
+ /*
38
+ * Decodes an Argon2 hash string into the provided structure 'ctx'.
39
+ * The only fields that must be set prior to this call are ctx.saltlen and
40
+ * ctx.outlen (which must be the maximal salt and out length values that are
41
+ * allowed), ctx.salt and ctx.out (which must be buffers of the specified
42
+ * length), and ctx.pwd and ctx.pwdlen which must hold a valid password.
43
+ *
44
+ * Invalid input string causes an error. On success, the ctx is valid and all
45
+ * fields have been initialized.
46
+ *
47
+ * Returned value is ARGON2_OK on success, other ARGON2_ codes on error.
48
+ */
49
+ int decode_string(argon2_context *ctx, const char *str, argon2_type type);
50
+
51
+ /* Returns the length of the encoded byte stream with length len */
52
+ size_t b64len(uint32_t len);
53
+
54
+ /* Returns the length of the encoded number num */
55
+ size_t numlen(uint32_t num);
56
+
57
+ #endif
@@ -0,0 +1,194 @@
1
+ /*
2
+ * Argon2 reference source code package - reference C implementations
3
+ *
4
+ * Copyright 2015
5
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
6
+ *
7
+ * You may use this work under the terms of a Creative Commons CC0 1.0
8
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
9
+ * these licenses can be found at:
10
+ *
11
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
12
+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * You should have received a copy of both of these licenses along with this
15
+ * software. If not, they may be obtained at the above URLs.
16
+ */
17
+
18
+ #include <stdint.h>
19
+ #include <string.h>
20
+ #include <stdlib.h>
21
+
22
+ #include "argon2.h"
23
+ #include "core.h"
24
+
25
+ #include "blake2/blamka-round-ref.h"
26
+ #include "blake2/blake2-impl.h"
27
+ #include "blake2/blake2.h"
28
+
29
+
30
+ /*
31
+ * Function fills a new memory block and optionally XORs the old block over the new one.
32
+ * @next_block must be initialized.
33
+ * @param prev_block Pointer to the previous block
34
+ * @param ref_block Pointer to the reference block
35
+ * @param next_block Pointer to the block to be constructed
36
+ * @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
37
+ * @pre all block pointers must be valid
38
+ */
39
+ static void fill_block(const block *prev_block, const block *ref_block,
40
+ block *next_block, int with_xor) {
41
+ block blockR, block_tmp;
42
+ unsigned i;
43
+
44
+ copy_block(&blockR, ref_block);
45
+ xor_block(&blockR, prev_block);
46
+ copy_block(&block_tmp, &blockR);
47
+ /* Now blockR = ref_block + prev_block and block_tmp = ref_block + prev_block */
48
+ if (with_xor) {
49
+ /* Saving the next block contents for XOR over: */
50
+ xor_block(&block_tmp, next_block);
51
+ /* Now blockR = ref_block + prev_block and
52
+ block_tmp = ref_block + prev_block + next_block */
53
+ }
54
+
55
+ /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
56
+ (16,17,..31)... finally (112,113,...127) */
57
+ for (i = 0; i < 8; ++i) {
58
+ BLAKE2_ROUND_NOMSG(
59
+ blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
60
+ blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
61
+ blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
62
+ blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
63
+ blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
64
+ blockR.v[16 * i + 15]);
65
+ }
66
+
67
+ /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
68
+ (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
69
+ for (i = 0; i < 8; i++) {
70
+ BLAKE2_ROUND_NOMSG(
71
+ blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
72
+ blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
73
+ blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
74
+ blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
75
+ blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
76
+ blockR.v[2 * i + 113]);
77
+ }
78
+
79
+ copy_block(next_block, &block_tmp);
80
+ xor_block(next_block, &blockR);
81
+ }
82
+
83
+ static void next_addresses(block *address_block, block *input_block,
84
+ const block *zero_block) {
85
+ input_block->v[6]++;
86
+ fill_block(zero_block, input_block, address_block, 0);
87
+ fill_block(zero_block, address_block, address_block, 0);
88
+ }
89
+
90
+ void fill_segment(const argon2_instance_t *instance,
91
+ argon2_position_t position) {
92
+ block *ref_block = NULL, *curr_block = NULL;
93
+ block address_block, input_block, zero_block;
94
+ uint64_t pseudo_rand, ref_index, ref_lane;
95
+ uint32_t prev_offset, curr_offset;
96
+ uint32_t starting_index;
97
+ uint32_t i;
98
+ int data_independent_addressing;
99
+
100
+ if (instance == NULL) {
101
+ return;
102
+ }
103
+
104
+ data_independent_addressing =
105
+ (instance->type == Argon2_i) ||
106
+ (instance->type == Argon2_id && (position.pass == 0) &&
107
+ (position.slice < ARGON2_SYNC_POINTS / 2));
108
+
109
+ if (data_independent_addressing) {
110
+ init_block_value(&zero_block, 0);
111
+ init_block_value(&input_block, 0);
112
+
113
+ input_block.v[0] = position.pass;
114
+ input_block.v[1] = position.lane;
115
+ input_block.v[2] = position.slice;
116
+ input_block.v[3] = instance->memory_blocks;
117
+ input_block.v[4] = instance->passes;
118
+ input_block.v[5] = instance->type;
119
+ }
120
+
121
+ starting_index = 0;
122
+
123
+ if ((0 == position.pass) && (0 == position.slice)) {
124
+ starting_index = 2; /* we have already generated the first two blocks */
125
+
126
+ /* Don't forget to generate the first block of addresses: */
127
+ if (data_independent_addressing) {
128
+ next_addresses(&address_block, &input_block, &zero_block);
129
+ }
130
+ }
131
+
132
+ /* Offset of the current block */
133
+ curr_offset = position.lane * instance->lane_length +
134
+ position.slice * instance->segment_length + starting_index;
135
+
136
+ if (0 == curr_offset % instance->lane_length) {
137
+ /* Last block in this lane */
138
+ prev_offset = curr_offset + instance->lane_length - 1;
139
+ } else {
140
+ /* Previous block */
141
+ prev_offset = curr_offset - 1;
142
+ }
143
+
144
+ for (i = starting_index; i < instance->segment_length;
145
+ ++i, ++curr_offset, ++prev_offset) {
146
+ /*1.1 Rotating prev_offset if needed */
147
+ if (curr_offset % instance->lane_length == 1) {
148
+ prev_offset = curr_offset - 1;
149
+ }
150
+
151
+ /* 1.2 Computing the index of the reference block */
152
+ /* 1.2.1 Taking pseudo-random value from the previous block */
153
+ if (data_independent_addressing) {
154
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
155
+ next_addresses(&address_block, &input_block, &zero_block);
156
+ }
157
+ pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
158
+ } else {
159
+ pseudo_rand = instance->memory[prev_offset].v[0];
160
+ }
161
+
162
+ /* 1.2.2 Computing the lane of the reference block */
163
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
164
+
165
+ if ((position.pass == 0) && (position.slice == 0)) {
166
+ /* Can not reference other lanes yet */
167
+ ref_lane = position.lane;
168
+ }
169
+
170
+ /* 1.2.3 Computing the number of possible reference block within the
171
+ * lane.
172
+ */
173
+ position.index = i;
174
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
175
+ ref_lane == position.lane);
176
+
177
+ /* 2 Creating a new block */
178
+ ref_block =
179
+ instance->memory + instance->lane_length * ref_lane + ref_index;
180
+ curr_block = instance->memory + curr_offset;
181
+ if (ARGON2_VERSION_10 == instance->version) {
182
+ /* version 1.2.1 and earlier: overwrite, not XOR */
183
+ fill_block(instance->memory + prev_offset, ref_block, curr_block, 0);
184
+ } else {
185
+ if(0 == position.pass) {
186
+ fill_block(instance->memory + prev_offset, ref_block,
187
+ curr_block, 0);
188
+ } else {
189
+ fill_block(instance->memory + prev_offset, ref_block,
190
+ curr_block, 1);
191
+ }
192
+ }
193
+ }
194
+ }
@@ -0,0 +1,57 @@
1
+ /*
2
+ * Argon2 reference source code package - reference C implementations
3
+ *
4
+ * Copyright 2015
5
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
6
+ *
7
+ * You may use this work under the terms of a Creative Commons CC0 1.0
8
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
9
+ * these licenses can be found at:
10
+ *
11
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
12
+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * You should have received a copy of both of these licenses along with this
15
+ * software. If not, they may be obtained at the above URLs.
16
+ */
17
+
18
+ #if !defined(ARGON2_NO_THREADS)
19
+
20
+ #include "thread.h"
21
+ #if defined(_WIN32)
22
+ #include <windows.h>
23
+ #endif
24
+
25
+ int argon2_thread_create(argon2_thread_handle_t *handle,
26
+ argon2_thread_func_t func, void *args) {
27
+ if (NULL == handle || func == NULL) {
28
+ return -1;
29
+ }
30
+ #if defined(_WIN32)
31
+ *handle = _beginthreadex(NULL, 0, func, args, 0, NULL);
32
+ return *handle != 0 ? 0 : -1;
33
+ #else
34
+ return pthread_create(handle, NULL, func, args);
35
+ #endif
36
+ }
37
+
38
+ int argon2_thread_join(argon2_thread_handle_t handle) {
39
+ #if defined(_WIN32)
40
+ if (WaitForSingleObject((HANDLE)handle, INFINITE) == WAIT_OBJECT_0) {
41
+ return CloseHandle((HANDLE)handle) != 0 ? 0 : -1;
42
+ }
43
+ return -1;
44
+ #else
45
+ return pthread_join(handle, NULL);
46
+ #endif
47
+ }
48
+
49
+ void argon2_thread_exit(void) {
50
+ #if defined(_WIN32)
51
+ _endthreadex(0);
52
+ #else
53
+ pthread_exit(NULL);
54
+ #endif
55
+ }
56
+
57
+ #endif /* ARGON2_NO_THREADS */
@@ -0,0 +1,67 @@
1
+ /*
2
+ * Argon2 reference source code package - reference C implementations
3
+ *
4
+ * Copyright 2015
5
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
6
+ *
7
+ * You may use this work under the terms of a Creative Commons CC0 1.0
8
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
9
+ * these licenses can be found at:
10
+ *
11
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
12
+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * You should have received a copy of both of these licenses along with this
15
+ * software. If not, they may be obtained at the above URLs.
16
+ */
17
+
18
+ #ifndef ARGON2_THREAD_H
19
+ #define ARGON2_THREAD_H
20
+
21
+ #if !defined(ARGON2_NO_THREADS)
22
+
23
+ /*
24
+ Here we implement an abstraction layer for the simpĺe requirements
25
+ of the Argon2 code. We only require 3 primitives---thread creation,
26
+ joining, and termination---so full emulation of the pthreads API
27
+ is unwarranted. Currently we wrap pthreads and Win32 threads.
28
+
29
+ The API defines 2 types: the function pointer type,
30
+ argon2_thread_func_t,
31
+ and the type of the thread handle---argon2_thread_handle_t.
32
+ */
33
+ #if defined(_WIN32)
34
+ #include <process.h>
35
+ typedef unsigned(__stdcall *argon2_thread_func_t)(void *);
36
+ typedef uintptr_t argon2_thread_handle_t;
37
+ #else
38
+ #include <pthread.h>
39
+ typedef void *(*argon2_thread_func_t)(void *);
40
+ typedef pthread_t argon2_thread_handle_t;
41
+ #endif
42
+
43
+ /* Creates a thread
44
+ * @param handle pointer to a thread handle, which is the output of this
45
+ * function. Must not be NULL.
46
+ * @param func A function pointer for the thread's entry point. Must not be
47
+ * NULL.
48
+ * @param args Pointer that is passed as an argument to @func. May be NULL.
49
+ * @return 0 if @handle and @func are valid pointers and a thread is successfully
50
+ * created.
51
+ */
52
+ int argon2_thread_create(argon2_thread_handle_t *handle,
53
+ argon2_thread_func_t func, void *args);
54
+
55
+ /* Waits for a thread to terminate
56
+ * @param handle Handle to a thread created with argon2_thread_create.
57
+ * @return 0 if @handle is a valid handle, and joining completed successfully.
58
+ */
59
+ int argon2_thread_join(argon2_thread_handle_t handle);
60
+
61
+ /* Terminate the current thread. Must be run inside a thread created by
62
+ * argon2_thread_create.
63
+ */
64
+ void argon2_thread_exit(void);
65
+
66
+ #endif /* ARGON2_NO_THREADS */
67
+ #endif
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,71 @@
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_version(Java::OrgBouncycastleCryptoParams::Argon2Parameters::ARGON2_VERSION_13)
19
+ .with_iterations(t_cost)
20
+ .with_memory_as_kb(m_cost)
21
+ .with_parallelism(parallelism)
22
+ .with_salt(salt_bytes)
23
+ .build
24
+ generator = Java::OrgBouncycastleCryptoGenerators::Argon2BytesGenerator.new
25
+
26
+ generator.init(params)
27
+ generator.generate_bytes(pwd.to_java_bytes, output)
28
+
29
+ encoder = Java::JavaUtil::Base64.get_encoder.without_padding
30
+ encoded_salt = encoder.encode_to_string(salt_bytes)
31
+ encoded_output = encoder.encode_to_string(output)
32
+
33
+ "$argon2id$v=19$m=#{m_cost},t=#{t_cost},p=#{parallelism}" \
34
+ "$#{encoded_salt}$#{encoded_output}"
35
+ rescue Java::JavaLang::IllegalStateException => e
36
+ raise Error, e.message
37
+ end
38
+
39
+ private_class_method :hash_encoded
40
+
41
+ private
42
+
43
+ def verify(pwd)
44
+ other_output = Java::byte[output.bytesize].new
45
+ params = Java::OrgBouncycastleCryptoParams::Argon2Parameters::Builder
46
+ .new(Java::OrgBouncycastleCryptoParams::Argon2Parameters::ARGON2_id)
47
+ .with_version(version)
48
+ .with_iterations(t_cost)
49
+ .with_memory_as_kb(m_cost)
50
+ .with_parallelism(parallelism)
51
+ .with_salt(salt.to_java_bytes)
52
+ .build
53
+ generator = Java::OrgBouncycastleCryptoGenerators::Argon2BytesGenerator.new
54
+ generator.init(params)
55
+ generator.generate_bytes(pwd.to_java_bytes, other_output)
56
+
57
+ Java::OrgBouncycastleUtil::Arrays.constant_time_are_equal?(
58
+ output.to_java_bytes,
59
+ other_output
60
+ )
61
+ end
62
+ end
63
+ end
64
+ else
65
+ begin
66
+ ::RUBY_VERSION =~ /(\d+\.\d+)/
67
+ require_relative "#{Regexp.last_match(1)}/argon2id"
68
+ rescue LoadError
69
+ require "argon2id/argon2id"
70
+ end
71
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+
5
+ module Argon2id
6
+ # The Password class encapsulates an encoded Argon2id password hash.
7
+ #
8
+ # To hash a plain text password, use Argon2id::Password.create:
9
+ #
10
+ # password = Argon2id::Password.create("password")
11
+ # password.to_s
12
+ # #=> "$argon2id$v=19$m=19456,t=2,p=1$+Lrjry9Ifq0poLr15OGU1Q$utkDvejJB0ugwm4s9+a+vF6+1a/W+Y3CYa5Wte/85ig"
13
+ #
14
+ # To wrap an encoded Argon2id password hash, use Argon2id::Password.new:
15
+ #
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.version #=> 19
29
+ # password.m_cost #=> 19456
30
+ # password.t_cost #=> 2
31
+ # password.parallelism #=> 1
32
+ # password.salt #=> "somesalt"
33
+ class Password
34
+ # A regular expression to match valid hashes.
35
+ PATTERN = %r{
36
+ \A
37
+ \$
38
+ argon2id
39
+ (?:\$v=(\d+))?
40
+ \$m=(\d+)
41
+ ,t=(\d+)
42
+ ,p=(\d+)
43
+ \$
44
+ ([a-zA-Z0-9+/]+)
45
+ \$
46
+ ([a-zA-Z0-9+/]+)
47
+ \z
48
+ }x.freeze
49
+
50
+ # The encoded password hash.
51
+ attr_reader :encoded
52
+
53
+ # The version number of the hashing function.
54
+ attr_reader :version
55
+
56
+ # The "time cost" of the hashing function.
57
+ attr_reader :t_cost
58
+
59
+ # The "memory cost" of the hashing function.
60
+ attr_reader :m_cost
61
+
62
+ # The number of threads and compute lanes of the hashing function.
63
+ attr_reader :parallelism
64
+
65
+ # The salt.
66
+ attr_reader :salt
67
+
68
+ # The hash output.
69
+ attr_reader :output
70
+
71
+ # Create a new Password object that hashes a given plain text password +pwd+.
72
+ #
73
+ # - +:t_cost+: integer (default 2) the "time cost" given as a number of iterations
74
+ # - +:m_cost+: integer (default 19456) the "memory cost" given in kibibytes
75
+ # - +:parallelism+: integer (default 1) the number of threads and compute lanes to use
76
+ # - +:salt_len+: integer (default 16) the salt size in bytes
77
+ # - +:output_len+: integer (default 32) the desired length of the hash in bytes
78
+ #
79
+ # For example, with the default configuration:
80
+ #
81
+ # password = Argon2id::Password.create("password")
82
+ # password.to_s
83
+ # #=> "$argon2id$v=19$m=19456,t=2,p=1$FI8yp1gXbthJCskBlpKPoQ$nOfCCpS2r+I8GRN71cZND4cskn7YKBNzuHUEO3YpY2s"
84
+ #
85
+ # When overriding the configuration:
86
+ #
87
+ # password = Argon2id::Password.create("password", t_cost: 3, m_cost: 12288)
88
+ # password.to_s
89
+ # #=> "$argon2id$v=19$m=12288,t=3,p=1$JigW7fFn+N3NImt+aWpuzw$eM5F1cKeIBALNTU6LuWra75Zi2nymGvQLWzJzVFv0Nc"
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)
91
+ new(
92
+ hash_encoded(
93
+ Integer(t_cost),
94
+ Integer(m_cost),
95
+ Integer(parallelism),
96
+ String(pwd),
97
+ OpenSSL::Random.random_bytes(Integer(salt_len)),
98
+ Integer(output_len)
99
+ )
100
+ )
101
+ end
102
+
103
+ # Check an encoded hash is a valid Argon2id hash.
104
+ #
105
+ # Returns true if so and false if not.
106
+ def self.valid_hash?(encoded)
107
+ PATTERN.match?(String(encoded))
108
+ end
109
+
110
+ # Create a new Password with the given encoded password hash.
111
+ #
112
+ # password = Argon2id::Password.new("$argon2id$v=19$m=19456,t=2,p=1$FI8yp1gXbthJCskBlpKPoQ$nOfCCpS2r+I8GRN71cZND4cskn7YKBNzuHUEO3YpY2s")
113
+ #
114
+ # Raises an ArgumentError if given an invalid hash.
115
+ def initialize(encoded)
116
+ raise ArgumentError, "invalid hash" unless PATTERN =~ String(encoded)
117
+
118
+ @encoded = $&
119
+ @version = Integer($1 || 0x10)
120
+ @m_cost = Integer($2)
121
+ @t_cost = Integer($3)
122
+ @parallelism = Integer($4)
123
+ @salt = $5.unpack1("m")
124
+ @output = $6.unpack1("m")
125
+ end
126
+
127
+ # Return the encoded password hash.
128
+ alias_method :to_s, :encoded
129
+
130
+ # Compare the password with the given plain text, returning true if it
131
+ # verifies successfully.
132
+ #
133
+ # password = Argon2id::Password.new("$argon2id$v=19$m=19456,t=2,p=1$FI8yp1gXbthJCskBlpKPoQ$nOfCCpS2r+I8GRN71cZND4cskn7YKBNzuHUEO3YpY2s")
134
+ # password == "password" #=> true
135
+ # password == "notpassword" #=> false
136
+ def ==(other)
137
+ verify(String(other))
138
+ end
139
+
140
+ alias_method :is_password?, :==
141
+ end
142
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Argon2id
4
+ VERSION = "0.8.0.rc1"
5
+ end
data/lib/argon2id.rb ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "argon2id/extension"
4
+ require "argon2id/password"
5
+ require "argon2id/version"
6
+
7
+ module Argon2id
8
+ # The default "time cost" of 2 iterations recommended by OWASP.
9
+ DEFAULT_T_COST = 2
10
+
11
+ # The default "memory cost" of 19 mebibytes recommended by OWASP.
12
+ DEFAULT_M_COST = 19_456
13
+
14
+ # The default 1 thread and compute lane recommended by OWASP.
15
+ DEFAULT_PARALLELISM = 1
16
+
17
+ # The default salt length of 16 bytes.
18
+ DEFAULT_SALT_LEN = 16
19
+
20
+ # The default desired hash length of 32 bytes.
21
+ DEFAULT_OUTPUT_LEN = 32
22
+
23
+ @t_cost = DEFAULT_T_COST
24
+ @m_cost = DEFAULT_M_COST
25
+ @parallelism = DEFAULT_PARALLELISM
26
+ @salt_len = DEFAULT_SALT_LEN
27
+ @output_len = DEFAULT_OUTPUT_LEN
28
+
29
+ class << self
30
+ # The default number of iterations used by Argon2id::Password.create
31
+ attr_accessor :t_cost
32
+
33
+ # The default memory cost in kibibytes used by Argon2id::Password.create
34
+ attr_accessor :m_cost
35
+
36
+ # The default number of threads and compute lanes used by Argon2id::Password.create
37
+ attr_accessor :parallelism
38
+
39
+ # The default salt size in bytes used by Argon2id::Password.create
40
+ attr_accessor :salt_len
41
+
42
+ # The default desired length of the hash in bytes used by Argon2id::Password.create
43
+ attr_accessor :output_len
44
+ end
45
+ end