sodium.cr/src/sodium/password/key.cr

45 lines
1.4 KiB
Crystal

require "./abstract"
require "./mode"
require "../kdf"
module Sodium::Password
# See `Sodium::Password::Key::Create`
#
# TODO: Usage example using the same params with multiple passwords.
class Key < Abstract
# Used by and must be set before calling #derive_key
property mode : Mode = Mode.default
property salt : Bytes?
# Must set a mode before calling.
def derive_key(pass : Bytes | String, key_bytes : Int32, *, salt : String | Bytes | Nil = nil) : SecureBuffer
key = SecureBuffer.new key_bytes
derive_key key, pass, salt: salt
key.readonly
end
def derive_kdf(pass, *, salt = nil) : Kdf
key = derive_key pass, Kdf::KEY_SIZE, salt: salt
Kdf.new key
end
# :nodoc:
def derive_key(key : SecureBuffer, pass : Bytes | String, *, salt : Bytes? = nil) : Nil
m = mode || raise ArgumentError.new("mode not set")
salt ||= @salt
raise ArgumentError.new("missing salt") unless salt
salt = salt.not_nil!
raise "salt expected #{SALT_SIZE} bytes, got #{salt.bytesize} " if salt.bytesize != SALT_SIZE
if LibSodium.crypto_pwhash(key.to_slice, key.bytesize, pass.to_slice, pass.bytesize, salt.to_slice, @ops, @mem, m) != 0
raise Sodium::Error.new("crypto_pwhash")
end
end
def to_params(*, salt = nil, key_size = nil, tcost : Float64? = nil)
Params.new @mode, @ops, @mem, salt: salt, key_size: key_size, tcost: tcost
end
end
end