passwordping 1.0.0 → 1.0.1
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/Gemfile +1 -1
- data/Rakefile +17 -0
- data/ext/argon2-wrapper/extconf.rb +1 -1
- data/ext/digest/whirlpool/extconf.rb +10 -0
- data/ext/digest/whirlpool/whirlpool-algorithm.c +476 -0
- data/ext/digest/whirlpool/whirlpool-algorithm.h +86 -0
- data/ext/digest/whirlpool/whirlpool-constants.h +1116 -0
- data/ext/digest/whirlpool/whirlpool-portability.h +142 -0
- data/ext/digest/whirlpool/whirlpool.c +51 -0
- data/lib/digest/whirlpool.bundle +0 -0
- data/lib/passwordping.rb +2 -2
- data/lib/passwordping/hashing.rb +66 -9
- data/lib/passwordping/version.rb +1 -1
- data/passwordping.gemspec +2 -2
- metadata +30 -22
@@ -0,0 +1,142 @@
|
|
1
|
+
/**
|
2
|
+
* The Whirlpool hashing function.
|
3
|
+
*
|
4
|
+
* The Whirlpool algorithm was developed by
|
5
|
+
* Paulo S. L. M. Barreto and Vincent Rijmen.
|
6
|
+
*
|
7
|
+
* See
|
8
|
+
* P.S.L.M. Barreto, V. Rijmen,
|
9
|
+
* ``The Whirlpool hashing function,''
|
10
|
+
* NESSIE submission, 2000 (tweaked version, 2001),
|
11
|
+
* <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip>
|
12
|
+
*
|
13
|
+
* @version 3.0 (2003.03.12)
|
14
|
+
*
|
15
|
+
* Modified for use in this software package.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#ifndef _WHIRLPOOL_PORTABILITY_H_
|
19
|
+
#define _WHIRLPOOL_PORTABILITY_H_
|
20
|
+
|
21
|
+
/* Definition of minimum-width integer types
|
22
|
+
*
|
23
|
+
* u8 -> unsigned integer type, at least 8 bits, equivalent to unsigned char
|
24
|
+
* u16 -> unsigned integer type, at least 16 bits
|
25
|
+
* u32 -> unsigned integer type, at least 32 bits
|
26
|
+
*
|
27
|
+
* s8, s16, s32 -> signed counterparts of u8, u16, u32
|
28
|
+
*
|
29
|
+
* Always use macro's T8(), T16() or T32() to obtain exact-width results,
|
30
|
+
* i.e., to specify the size of the result of each expression.
|
31
|
+
*/
|
32
|
+
|
33
|
+
typedef signed char s8;
|
34
|
+
typedef unsigned char u8;
|
35
|
+
|
36
|
+
#if UINT_MAX >= 4294967295UL
|
37
|
+
|
38
|
+
typedef signed short s16;
|
39
|
+
typedef signed int s32;
|
40
|
+
typedef unsigned short u16;
|
41
|
+
typedef unsigned int u32;
|
42
|
+
|
43
|
+
#define ONE32 0xffffffffU
|
44
|
+
|
45
|
+
#else
|
46
|
+
|
47
|
+
typedef signed int s16;
|
48
|
+
typedef signed long s32;
|
49
|
+
typedef unsigned int u16;
|
50
|
+
typedef unsigned long u32;
|
51
|
+
|
52
|
+
#define ONE32 0xffffffffUL
|
53
|
+
|
54
|
+
#endif
|
55
|
+
|
56
|
+
#define ONE8 0xffU
|
57
|
+
#define ONE16 0xffffU
|
58
|
+
|
59
|
+
#define T8(x) ((x) & ONE8)
|
60
|
+
#define T16(x) ((x) & ONE16)
|
61
|
+
#define T32(x) ((x) & ONE32)
|
62
|
+
|
63
|
+
#ifdef _MSC_VER
|
64
|
+
typedef unsigned __int64 u64;
|
65
|
+
typedef signed __int64 s64;
|
66
|
+
#define LL(v) (v##i64)
|
67
|
+
#define ONE64 LL(0xffffffffffffffff)
|
68
|
+
#else /* !_MSC_VER */
|
69
|
+
typedef unsigned long long u64;
|
70
|
+
typedef signed long long s64;
|
71
|
+
#define LL(v) (v##ULL)
|
72
|
+
#define ONE64 LL(0xffffffffffffffff)
|
73
|
+
#endif /* ?_MSC_VER */
|
74
|
+
#define T64(x) ((x) & ONE64)
|
75
|
+
#define ROTR64(v, n) (((v) >> (n)) | T64((v) << (64 - (n))))
|
76
|
+
/*
|
77
|
+
* Note: the test is used to detect native 64-bit architectures;
|
78
|
+
* if the unsigned long is strictly greater than 32-bit, it is
|
79
|
+
* assumed to be at least 64-bit. This will not work correctly
|
80
|
+
* on (old) 36-bit architectures (PDP-11 for instance).
|
81
|
+
*
|
82
|
+
* On non-64-bit architectures, "long long" is used.
|
83
|
+
*/
|
84
|
+
|
85
|
+
/*
|
86
|
+
* U8TO32_BIG(c) returns the 32-bit value stored in big-endian convention
|
87
|
+
* in the unsigned char array pointed to by c.
|
88
|
+
*/
|
89
|
+
#define U8TO32_BIG(c) (((u32)T8(*(c)) << 24) | ((u32)T8(*((c) + 1)) << 16) | ((u32)T8(*((c) + 2)) << 8) | ((u32)T8(*((c) + 3))))
|
90
|
+
|
91
|
+
/*
|
92
|
+
* U8TO32_LITTLE(c) returns the 32-bit value stored in little-endian convention
|
93
|
+
* in the unsigned char array pointed to by c.
|
94
|
+
*/
|
95
|
+
#define U8TO32_LITTLE(c) (((u32)T8(*(c))) | ((u32)T8(*((c) + 1)) << 8) | (u32)T8(*((c) + 2)) << 16) | ((u32)T8(*((c) + 3)) << 24))
|
96
|
+
|
97
|
+
/*
|
98
|
+
* U8TO32_BIG(c, v) stores the 32-bit-value v in big-endian convention
|
99
|
+
* into the unsigned char array pointed to by c.
|
100
|
+
*/
|
101
|
+
#define U32TO8_BIG(c, v) do { u32 x = (v); u8 *d = (c); d[0] = T8(x >> 24); d[1] = T8(x >> 16); d[2] = T8(x >> 8); d[3] = T8(x); } while (0)
|
102
|
+
|
103
|
+
/*
|
104
|
+
* U8TO32_LITTLE(c, v) stores the 32-bit-value v in little-endian convention
|
105
|
+
* into the unsigned char array pointed to by c.
|
106
|
+
*/
|
107
|
+
#define U32TO8_LITTLE(c, v) do { u32 x = (v); u8 *d = (c); d[0] = T8(x); d[1] = T8(x >> 8); d[2] = T8(x >> 16); d[3] = T8(x >> 24); } while (0)
|
108
|
+
|
109
|
+
/*
|
110
|
+
* ROTL32(v, n) returns the value of the 32-bit unsigned value v after
|
111
|
+
* a rotation of n bits to the left. It might be replaced by the appropriate
|
112
|
+
* architecture-specific macro.
|
113
|
+
*
|
114
|
+
* It evaluates v and n twice.
|
115
|
+
*
|
116
|
+
* The compiler might emit a warning if n is the constant 0. The result
|
117
|
+
* is undefined if n is greater than 31.
|
118
|
+
*/
|
119
|
+
#define ROTL32(v, n) (T32((v) << (n)) | ((v) >> (32 - (n))))
|
120
|
+
|
121
|
+
/*
|
122
|
+
* Whirlpool-specific definitions.
|
123
|
+
*/
|
124
|
+
|
125
|
+
#define DIGESTBYTES WP_DIGEST_SIZE
|
126
|
+
#define DIGESTBITS (8*DIGESTBYTES) /* 512 */
|
127
|
+
|
128
|
+
#define WBLOCKBYTES 64
|
129
|
+
#define WBLOCKBITS (8*WBLOCKBYTES) /* 512 */
|
130
|
+
|
131
|
+
#define LENGTHBYTES 32
|
132
|
+
#define LENGTHBITS (8*LENGTHBYTES) /* 256 */
|
133
|
+
|
134
|
+
struct WP_Struct {
|
135
|
+
u8 bitLength[LENGTHBYTES]; /* global number of hashed bits (256-bit counter) */
|
136
|
+
u8 buffer[WBLOCKBYTES]; /* buffer of data to hash */
|
137
|
+
int bufferBits; /* current number of bits on the buffer */
|
138
|
+
int bufferPos; /* current (possibly incomplete) byte slot on the buffer */
|
139
|
+
u64 hash[DIGESTBYTES/8]; /* the hashing state */
|
140
|
+
};
|
141
|
+
|
142
|
+
#endif
|
@@ -0,0 +1,51 @@
|
|
1
|
+
/************************************************
|
2
|
+
|
3
|
+
whirlpool.c - provides Digest::Whirlpool class
|
4
|
+
|
5
|
+
Copyright (C) 2006-2013 Akinori MUSHA
|
6
|
+
|
7
|
+
************************************************/
|
8
|
+
|
9
|
+
#ifdef HAVE_RUBY_DIGEST_H
|
10
|
+
#include "ruby/digest.h"
|
11
|
+
#else
|
12
|
+
#include "digest.h"
|
13
|
+
#endif
|
14
|
+
#include "whirlpool-algorithm.h"
|
15
|
+
#include "whirlpool-portability.h"
|
16
|
+
|
17
|
+
static void WP_Update(WP_Struct * const, const unsigned char * const, size_t);
|
18
|
+
|
19
|
+
static rb_digest_metadata_t whirlpool = {
|
20
|
+
RUBY_DIGEST_API_VERSION,
|
21
|
+
WP_DIGEST_SIZE,
|
22
|
+
WBLOCKBYTES,
|
23
|
+
sizeof(WP_Struct),
|
24
|
+
(rb_digest_hash_init_func_t)WP_Init,
|
25
|
+
(rb_digest_hash_update_func_t)WP_Update,
|
26
|
+
(rb_digest_hash_finish_func_t)WP_Finalize,
|
27
|
+
};
|
28
|
+
|
29
|
+
static void
|
30
|
+
WP_Update(WP_Struct * const wp, const unsigned char * const data, size_t len)
|
31
|
+
{
|
32
|
+
WP_Add(data, len * 8, wp);
|
33
|
+
}
|
34
|
+
|
35
|
+
void
|
36
|
+
Init_whirlpool()
|
37
|
+
{
|
38
|
+
VALUE mDigest, cDigest_Base, cDigest_Whirlpool;
|
39
|
+
|
40
|
+
rb_require("digest");
|
41
|
+
|
42
|
+
mDigest = rb_path2class("Digest");
|
43
|
+
cDigest_Base = rb_path2class("Digest::Base");
|
44
|
+
|
45
|
+
cDigest_Whirlpool = rb_define_class_under(mDigest, "Whirlpool", cDigest_Base);
|
46
|
+
|
47
|
+
// rb_ivar_set(cDigest_Whirlpool, rb_intern("metadata"),
|
48
|
+
// Data_Wrap_Struct(rb_cObject, 0, 0, &whirlpool));
|
49
|
+
rb_ivar_set(cDigest_Whirlpool, rb_intern("metadata"),
|
50
|
+
Data_Wrap_Struct(0, 0, 0, (void *)&whirlpool));
|
51
|
+
}
|
Binary file
|
data/lib/passwordping.rb
CHANGED
@@ -26,7 +26,7 @@ module PasswordPing
|
|
26
26
|
def check_credentials(username, password)
|
27
27
|
raise PasswordPingFail, "API key/Secret not set" if !@authString || @authString == ''
|
28
28
|
|
29
|
-
response = make_rest_call(@baseURL + Constants::ACCOUNTS_API_PATH + "?username=" +
|
29
|
+
response = make_rest_call(@baseURL + Constants::ACCOUNTS_API_PATH + "?username=" + Hashing.sha256(username), "GET", nil)
|
30
30
|
|
31
31
|
if (response == "404")
|
32
32
|
return false
|
@@ -84,7 +84,7 @@ module PasswordPing
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def get_exposures_for_user(username)
|
87
|
-
response = make_rest_call(@baseURL + Constants::EXPOSURES_API_PATH + "?username=" +
|
87
|
+
response = make_rest_call(@baseURL + Constants::EXPOSURES_API_PATH + "?username=" + Hashing.sha256(username),
|
88
88
|
"GET", nil)
|
89
89
|
|
90
90
|
if (response == "404")
|
data/lib/passwordping/hashing.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'passwordping/argon2_wrapper_ffi'
|
2
2
|
require 'digest'
|
3
|
-
require 'cryptopp'
|
4
3
|
require 'bcrypt'
|
5
4
|
require 'unix_crypt'
|
5
|
+
require 'zlib'
|
6
|
+
require 'digest/whirlpool'
|
7
|
+
require 'base64'
|
6
8
|
|
7
9
|
module PasswordPing
|
8
10
|
class Hashing
|
@@ -39,21 +41,19 @@ module PasswordPing
|
|
39
41
|
end
|
40
42
|
|
41
43
|
def self.whirlpool(to_hash)
|
42
|
-
return
|
44
|
+
return Digest::Whirlpool.hexdigest(to_hash)
|
43
45
|
end
|
44
46
|
|
45
47
|
def self.whirlpool_binary(to_hash)
|
46
|
-
return
|
48
|
+
return Digest::Whirlpool.digest(to_hash)
|
47
49
|
end
|
48
50
|
|
49
51
|
def self.whirlpool_binary_array(to_hash)
|
50
|
-
return
|
52
|
+
return Digest::Whirlpool.digest(to_hash).bytes
|
51
53
|
end
|
52
54
|
|
53
55
|
def self.crc32(to_hash)
|
54
|
-
|
55
|
-
# correct for endian-ness
|
56
|
-
return hash[6] + hash[7] + hash[4] + hash[5] + hash[2] + hash[3] + hash[0] + hash[1]
|
56
|
+
return Zlib.crc32(to_hash, 0).to_s(16)
|
57
57
|
end
|
58
58
|
|
59
59
|
def self.mybb(to_hash, salt)
|
@@ -65,7 +65,23 @@ module PasswordPing
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def self.bcrypt(to_hash, salt)
|
68
|
-
|
68
|
+
# if salt starts with $2y$, first replace with $2a$
|
69
|
+
if salt[0..3] == "$2y$"
|
70
|
+
y_variant = true
|
71
|
+
checked_salt = "$2a$" + salt[4..-1]
|
72
|
+
else
|
73
|
+
y_variant = false
|
74
|
+
checked_salt = salt
|
75
|
+
end
|
76
|
+
|
77
|
+
result = BCrypt::Engine.hash_secret(to_hash, checked_salt)
|
78
|
+
|
79
|
+
if y_variant
|
80
|
+
# replace with $2y$
|
81
|
+
result = "$2y$" + result[4..-1]
|
82
|
+
end
|
83
|
+
|
84
|
+
return result
|
69
85
|
end
|
70
86
|
|
71
87
|
def self.phpbb3(to_hash, salt)
|
@@ -135,8 +151,49 @@ module PasswordPing
|
|
135
151
|
return UnixCrypt::MD5.build(to_hash, salt.start_with?("$1$") ? salt[3..salt.length] : salt);
|
136
152
|
end
|
137
153
|
|
154
|
+
def self.custom_algorithm4(to_hash, salt)
|
155
|
+
return self.bcrypt(self.md5(to_hash), salt)
|
156
|
+
end
|
157
|
+
|
138
158
|
def self.argon2(to_hash, salt)
|
139
|
-
|
159
|
+
time_cost = 3
|
160
|
+
mem_cost = 10
|
161
|
+
threads = 2
|
162
|
+
hash_length = 20
|
163
|
+
just_salt = salt
|
164
|
+
|
165
|
+
#$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG
|
166
|
+
if (salt[0..6] == "$argon2")
|
167
|
+
# looks like we specified algo info for argon2 in the salt
|
168
|
+
salt_values = salt.split("$")
|
169
|
+
just_salt = Base64.decode64(salt_values[4])
|
170
|
+
cost_params = salt_values[3].split(",")
|
171
|
+
|
172
|
+
for param in cost_params
|
173
|
+
begin
|
174
|
+
param_parts = param.split("=")
|
175
|
+
if (param_parts[0] == "t")
|
176
|
+
time_cost = Integer(param_parts[1])
|
177
|
+
elsif (param_parts[0] == "m")
|
178
|
+
mem_cost = Math.log2(Integer(param_parts[1])).round
|
179
|
+
elsif (param_parts[0] == "p")
|
180
|
+
threads = Integer(param_parts[1])
|
181
|
+
elsif (param_parts[0] == "l")
|
182
|
+
hash_length = Integer(param_parts[1])
|
183
|
+
end
|
184
|
+
rescue ArgumentError
|
185
|
+
# ignore invalid params and just use default
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
if (salt_values[1] == "argon2i")
|
190
|
+
return Argon2Wrapper.hash_argon2i_encode(to_hash, just_salt, time_cost, mem_cost, threads, hash_length)
|
191
|
+
else
|
192
|
+
return Argon2Wrapper.hash_argon2d_encode(to_hash, just_salt, time_cost, mem_cost, threads, hash_length)
|
193
|
+
end
|
194
|
+
else
|
195
|
+
return Argon2Wrapper.hash_argon2d_encode(to_hash, just_salt, time_cost, mem_cost, threads, hash_length)
|
196
|
+
end
|
140
197
|
end
|
141
198
|
|
142
199
|
def self.xor(byte_array1, byte_array2)
|
data/lib/passwordping/version.rb
CHANGED
data/passwordping.gemspec
CHANGED
@@ -23,12 +23,12 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency 'ffi', '~> 1.9'
|
24
24
|
spec.add_dependency 'ffi-compiler', '~> 0.1'
|
25
25
|
spec.add_dependency 'rest-client', '~> 2.0', '>= 2.0.2'
|
26
|
-
spec.add_dependency 'cryptopp', '~> 0.0', '>= 0.0.5'
|
27
26
|
spec.add_dependency 'bcrypt', '~> 3.1', '>= 3.1.11'
|
28
27
|
spec.add_dependency 'unix-crypt', '~> 1.3'
|
29
28
|
|
30
29
|
spec.add_development_dependency "bundler", '~> 1.10', '>= 1.10.5'
|
31
30
|
spec.add_development_dependency "rake", '~> 10.4', '>= 10.4.2'
|
32
31
|
spec.add_development_dependency "test-unit", '~> 3.2', '>= 3.2.4'
|
33
|
-
spec.
|
32
|
+
spec.add_development_dependency "rake-compiler", '~> 1.0', '>= 1.0.4'
|
33
|
+
spec.extensions = ['ext/argon2-wrapper/extconf.rb', "ext/digest/whirlpool/extconf.rb" ]
|
34
34
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passwordping
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- PasswordPing
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -58,26 +58,6 @@ dependencies:
|
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 2.0.2
|
61
|
-
- !ruby/object:Gem::Dependency
|
62
|
-
name: cryptopp
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
64
|
-
requirements:
|
65
|
-
- - "~>"
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '0.0'
|
68
|
-
- - ">="
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
version: 0.0.5
|
71
|
-
type: :runtime
|
72
|
-
prerelease: false
|
73
|
-
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
requirements:
|
75
|
-
- - "~>"
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '0.0'
|
78
|
-
- - ">="
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
version: 0.0.5
|
81
61
|
- !ruby/object:Gem::Dependency
|
82
62
|
name: bcrypt
|
83
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -172,12 +152,33 @@ dependencies:
|
|
172
152
|
- - ">="
|
173
153
|
- !ruby/object:Gem::Version
|
174
154
|
version: 3.2.4
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: rake-compiler
|
157
|
+
requirement: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - "~>"
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '1.0'
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: 1.0.4
|
165
|
+
type: :development
|
166
|
+
prerelease: false
|
167
|
+
version_requirements: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - "~>"
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '1.0'
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: 1.0.4
|
175
175
|
description: Ruby library for PasswordPing API
|
176
176
|
email:
|
177
177
|
- support@passwordping.com
|
178
178
|
executables: []
|
179
179
|
extensions:
|
180
180
|
- ext/argon2-wrapper/extconf.rb
|
181
|
+
- ext/digest/whirlpool/extconf.rb
|
181
182
|
extra_rdoc_files: []
|
182
183
|
files:
|
183
184
|
- ".gitignore"
|
@@ -191,6 +192,12 @@ files:
|
|
191
192
|
- ext/argon2-wrapper/libargon2-wrapper.bundle
|
192
193
|
- ext/argon2-wrapper/libargon2-wrapper.bundle.dSYM/Contents/Info.plist
|
193
194
|
- ext/argon2-wrapper/libargon2-wrapper.bundle.dSYM/Contents/Resources/DWARF/libargon2-wrapper.bundle
|
195
|
+
- ext/digest/whirlpool/extconf.rb
|
196
|
+
- ext/digest/whirlpool/whirlpool-algorithm.c
|
197
|
+
- ext/digest/whirlpool/whirlpool-algorithm.h
|
198
|
+
- ext/digest/whirlpool/whirlpool-constants.h
|
199
|
+
- ext/digest/whirlpool/whirlpool-portability.h
|
200
|
+
- ext/digest/whirlpool/whirlpool.c
|
194
201
|
- ext/phc-winner-argon2/.git
|
195
202
|
- ext/phc-winner-argon2/.gitattributes
|
196
203
|
- ext/phc-winner-argon2/.gitignore
|
@@ -269,6 +276,7 @@ files:
|
|
269
276
|
- ext/phc-winner-argon2/vs2015/Argon2RefGenKAT/Argon2RefGenKAT.vcxproj.filters
|
270
277
|
- ext/phc-winner-argon2/vs2015/Argon2RefTestCI/Argon2RefTestCI.vcxproj
|
271
278
|
- ext/phc-winner-argon2/vs2015/Argon2RefTestCI/Argon2RefTestCI.vcxproj.filters
|
279
|
+
- lib/digest/whirlpool.bundle
|
272
280
|
- lib/passwordping.rb
|
273
281
|
- lib/passwordping/argon2_wrapper_ffi.rb
|
274
282
|
- lib/passwordping/constants.rb
|