(defmodule lamina_crypto_tests
(export all)
(include-lib "eunit/include/eunit.hrl"))
;;---- 密码 ----
(defun hash-verify-roundtrip_test ()
(let ((hash (lamina_crypto:hash_password #"s3cret!")))
(if (and (lamina_crypto:verify_password #"s3cret!" hash)
(not (lamina_crypto:verify_password #"wrong" hash)))
'ok
(erlang:error "hash/verify roundtrip failed"))))
(defun unique-salt_test ()
(let ((h1 (lamina_crypto:hash_password #"pw"))
(h2 (lamina_crypto:hash_password #"pw")))
(if (not (=:= h1 h2))
'ok
(erlang:error "two hashes identical (salt missing?)"))))
(defun verify-malformed-test ()
(if (not (lamina_crypto:verify_password #"pw" "garbage"))
'ok
(erlang:error "malformed hash accepted")))
;;---- secret key ----
(defun key-create-and-reload_test ()
(let ((path (filename:join (tmpdir) "secret.key")))
(let ((r1 (lamina_crypto:load_or_create_key path)))
(case r1
(`#(ok ,k1)
(let ((r2 (lamina_crypto:load_or_create_key path)))
(file:del_dir_r (filename:dirname path))
(case r2
(`#(ok ,k2)
(if (=:= k1 k2)
'ok
(erlang:error "key not stable across loads")))
(other (erlang:error other)))))
(other (erlang:error other))))))
;;---- AES-GCM ----
(defun encrypt-decrypt-roundtrip_test ()
(let ((key (crypto:strong_rand_bytes 32)))
(let ((`#(,iv ,ct ,tag) (lamina_crypto:encrypt #"my-git-token" key)))
(case (lamina_crypto:decrypt iv ct tag key)
(`#(ok ,plaintext)
(if (=:= plaintext #"my-git-token")
'ok
(erlang:error "decrypted plaintext mismatch")))
(other (erlang:error other))))))
(defun decrypt-tamper-fails_test ()
(let ((key (crypto:strong_rand_bytes 32)))
(let ((`#(,iv ,ct ,tag) (lamina_crypto:encrypt #"data" key)))
(let ((tampered (binary:part ct 0 (- (byte_size ct) 1))))
(case (lamina_crypto:decrypt iv tampered tag key)
('error 'ok)
(other (erlang:error "tampered ciphertext decrypted")))))))
;;---- helpers ----
(defun tmpdir ()
(let* ((cwd (element 2 (file:get_cwd)))
(base (filename:join cwd "_build/tmp")))
(filelib:ensure_dir (filename:join base "x"))
(let* ((name (integer_to_list (element 3 (os:timestamp))))
(dir (filename:join base name)))
(file:make_dir dir)
dir)))