-
Notifications
You must be signed in to change notification settings - Fork 2
/
password.cr
59 lines (49 loc) · 1.54 KB
/
password.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
require "crypto/subtle"
module Scrypt
class Password
def self.create(password,
key_len = DEFAULT_KEY_LEN,
salt_size = DEFAULT_SALT_SIZE,
max_mem = DEFAULT_MAX_MEM,
max_memfrac = DEFAULT_MAX_MEMFRAC,
max_time = DEFAULT_MAX_TIME
)
salt = Engine.generate_salt(salt_size.clamp(8, 32))
hashed_password = Engine.hash_secret(password, salt,
key_len: key_len.clamp(16, 512),
max_mem: max_mem,
max_memfrac: max_memfrac,
max_time: max_time
)
new(hashed_password)
end
@parts : Array(String)
def initialize(@raw_hash : String)
@parts = @raw_hash.split("$")
end
def verify(password : String)
key_len = digest.bytesize // 2
hashed_password = Engine.hash_secret(password, salt, key_len: key_len, cost: cost)
Crypto::Subtle.constant_time_compare(@raw_hash.to_slice, hashed_password.to_slice)
end
@[Deprecated("Use Scrypt::Password#verify instead")]
def ==(password : String)
verify password
end
def cost
{@parts[0].to_u64(16), @parts[1].to_u32(16), @parts[2].to_u32(16)}
end
def salt
@parts[3]
end
def digest
@parts[4]
end
def to_s(io)
io << @raw_hash
end
def inspect(io)
to_s(io)
end
end
end