Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions spec/cox/pwhash_spec.cr
Original file line number Diff line number Diff line change
@@ -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
30 changes: 30 additions & 0 deletions src/cox/lib_sodium.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ module Cox
fun crypto_sign_publickeybytes() : LibC::SizeT
fun crypto_sign_secretkeybytes() : LibC::SizeT
fun crypto_sign_bytes() : 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()
Expand All @@ -18,6 +27,7 @@ module Cox
PUBLIC_SIGN_BYTES = crypto_sign_publickeybytes()
SECRET_SIGN_BYTES = crypto_sign_secretkeybytes()
SIGNATURE_BYTES = crypto_sign_bytes()
PWHASH_STR_BYTES = crypto_pwhash_strbytes()

fun crypto_box_keypair(
public_key_output : Pointer(LibC::UChar),
Expand Down Expand Up @@ -61,5 +71,25 @@ module Cox
message_size : LibC::ULongLong,
public_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 changes: 49 additions & 0 deletions src/cox/pwhash.cr
Original file line number Diff line number Diff line change
@@ -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