Add libsodium password hashing
This commit is contained in:
parent
a358929e62
commit
a26800765e
22
spec/cox/pwhash_spec.cr
Normal file
22
spec/cox/pwhash_spec.cr
Normal file
@ -0,0 +1,22 @@
|
||||
require "../spec_helper"
|
||||
|
||||
describe Cox::Pwhash do
|
||||
it "hashes and verifies a password" do
|
||||
pwhash = Cox::Pwhash.new
|
||||
|
||||
# set to minimum to speed up tests
|
||||
pwhash.memlimit = Cox::Pwhash::MEMLIMIT_MIN
|
||||
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MIN
|
||||
|
||||
pass = "1234"
|
||||
hash = pwhash.hash_str pass
|
||||
pwhash.verify hash, pass
|
||||
expect_raises(Cox::Pwhash::PasswordVerifyError) do
|
||||
pwhash.verify hash, "5678"
|
||||
end
|
||||
|
||||
pwhash.needs_rehash?(hash).should be_false
|
||||
pwhash.opslimit = Cox::Pwhash::OPSLIMIT_MAX
|
||||
pwhash.needs_rehash?(hash).should be_true
|
||||
end
|
||||
end
|
@ -12,6 +12,15 @@ module Cox
|
||||
fun crypto_sign_bytes() : LibC::SizeT
|
||||
fun crypto_kdf_keybytes() : LibC::SizeT
|
||||
fun crypto_kdf_contextbytes() : LibC::SizeT
|
||||
fun crypto_pwhash_memlimit_min() : LibC::SizeT
|
||||
fun crypto_pwhash_memlimit_interactive() : LibC::SizeT
|
||||
fun crypto_pwhash_memlimit_max() : LibC::SizeT
|
||||
fun crypto_pwhash_opslimit_min() : LibC::SizeT
|
||||
fun crypto_pwhash_opslimit_interactive() : LibC::SizeT
|
||||
fun crypto_pwhash_opslimit_moderate() : LibC::SizeT
|
||||
fun crypto_pwhash_opslimit_sensitive() : LibC::SizeT
|
||||
fun crypto_pwhash_opslimit_max() : LibC::SizeT
|
||||
fun crypto_pwhash_strbytes() : LibC::SizeT
|
||||
|
||||
PUBLIC_KEY_BYTES = crypto_box_publickeybytes()
|
||||
SECRET_KEY_BYTES = crypto_box_secretkeybytes()
|
||||
@ -22,6 +31,7 @@ module Cox
|
||||
SIGNATURE_BYTES = crypto_sign_bytes()
|
||||
KDF_KEY_BYTES = crypto_kdf_keybytes()
|
||||
KDF_CONTEXT_BYTES = crypto_kdf_contextbytes()
|
||||
PWHASH_STR_BYTES = crypto_pwhash_strbytes()
|
||||
|
||||
fun crypto_box_keypair(
|
||||
public_key_output : Pointer(LibC::UChar),
|
||||
@ -66,7 +76,6 @@ module Cox
|
||||
public_key : Pointer(LibC::UChar)
|
||||
) : LibC::Int
|
||||
|
||||
|
||||
fun crypto_kdf_derive_from_key(
|
||||
subkey : Pointer(LibC::UChar),
|
||||
subkey_len : LibC::SizeT,
|
||||
@ -74,5 +83,25 @@ module Cox
|
||||
ctx : Pointer(LibC::UChar),
|
||||
key : Pointer(LibC::UChar)
|
||||
) : LibC::Int
|
||||
|
||||
fun crypto_pwhash_str(
|
||||
outstr : Pointer(LibC::UChar),
|
||||
pass : Pointer(LibC::UChar),
|
||||
pass_size : LibC::ULongLong,
|
||||
optslimit : LibC::ULongLong,
|
||||
memlimit : LibC::SizeT,
|
||||
) : LibC::Int
|
||||
|
||||
fun crypto_pwhash_str_verify(
|
||||
str : Pointer(LibC::UChar),
|
||||
pass : Pointer(LibC::UChar),
|
||||
pass_size : LibC::ULongLong,
|
||||
) : LibC::Int
|
||||
|
||||
fun crypto_pwhash_str_needs_rehash(
|
||||
str : Pointer(LibC::UChar),
|
||||
optslimit : LibC::ULongLong,
|
||||
memlimit : LibC::SizeT,
|
||||
) : LibC::Int
|
||||
end
|
||||
end
|
||||
|
49
src/cox/pwhash.cr
Normal file
49
src/cox/pwhash.cr
Normal file
@ -0,0 +1,49 @@
|
||||
module Cox
|
||||
class Pwhash
|
||||
class PasswordVerifyError < Cox::Error
|
||||
end
|
||||
|
||||
OPSLIMIT_MIN = LibSodium.crypto_pwhash_opslimit_min
|
||||
OPSLIMIT_INTERACTIVE = LibSodium.crypto_pwhash_opslimit_interactive
|
||||
OPSLIMIT_MODERATE = LibSodium.crypto_pwhash_opslimit_moderate
|
||||
OPSLIMIT_SENSITIVE = LibSodium.crypto_pwhash_opslimit_sensitive
|
||||
OPSLIMIT_MAX = LibSodium.crypto_pwhash_opslimit_max
|
||||
|
||||
MEMLIMIT_MIN = LibSodium.crypto_pwhash_memlimit_min
|
||||
MEMLIMIT_MAX = LibSodium.crypto_pwhash_memlimit_max
|
||||
MEMLIMIT_INTERACTIVE = LibSodium.crypto_pwhash_memlimit_interactive
|
||||
|
||||
property opslimit = OPSLIMIT_INTERACTIVE
|
||||
property memlimit = MEMLIMIT_INTERACTIVE
|
||||
|
||||
def hash_str(pass)
|
||||
outstr = Bytes.new LibSodium::PWHASH_STR_BYTES
|
||||
if LibSodium.crypto_pwhash_str(outstr, pass, pass.bytesize, @opslimit, @memlimit) != 0
|
||||
raise Cox::Error.new("crypto_pwhash_str")
|
||||
end
|
||||
outstr
|
||||
end
|
||||
|
||||
def verify(str, pass)
|
||||
# BUG: verify str length
|
||||
case LibSodium.crypto_pwhash_str_verify(str, pass, pass.bytesize)
|
||||
when 0
|
||||
true
|
||||
else
|
||||
raise PasswordVerifyError.new
|
||||
end
|
||||
end
|
||||
|
||||
def needs_rehash?(str)
|
||||
# BUG: verify str length
|
||||
case LibSodium.crypto_pwhash_str_needs_rehash(str, @opslimit, @memlimit)
|
||||
when 0
|
||||
false
|
||||
when 1
|
||||
true
|
||||
else
|
||||
raise Cox::Error.new("crypto_pwhash_str_needs_rehash")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user