argon2id 0.8.0.rc1-x86-linux-gnu

Sign up to get free protection for your applications and to get access to all the features.
@@ -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