From 965e1be803884edd328efac8c164251d85c1f182 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Mon, 17 Feb 2025 16:15:43 +0100 Subject: [PATCH] Start with security package --- dev.metalisp.survey.asd | 5 +++-- src/password-hasher.lisp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/password-hasher.lisp diff --git a/dev.metalisp.survey.asd b/dev.metalisp.survey.asd index 1a7d6e3..f9cf9eb 100644 --- a/dev.metalisp.survey.asd +++ b/dev.metalisp.survey.asd @@ -2,14 +2,15 @@ (defsystem "dev.metalisp.survey" :description "Create questionnaires and analyze the results." - :version "0.5.24" + :version "0.5.25" :author "Marcus Kammer " :source-control (:git "https://code.metalisp.dev/marcuskammer/dev.metalisp.survey.git") :licence "MIT" - :depends-on ("local-time" "hunchentoot" "dev.metalisp.sbt" "dev.metalisp.qmetrics") + :depends-on ("ironclad" "local-time" "hunchentoot" "dev.metalisp.sbt" "dev.metalisp.qmetrics") :components ((:module "src/" :components ((:file "fileops") (:file "app") + (:file "password-hasher") (:module "models/" :serial t :components ((:file "package") diff --git a/src/password-hasher.lisp b/src/password-hasher.lisp new file mode 100644 index 0000000..7dfee55 --- /dev/null +++ b/src/password-hasher.lisp @@ -0,0 +1,32 @@ +;;; -*- mode: lisp; coding: utf-8; -*- + +(defpackage :ml-survey/security + (:use #:cl) + (:export #:password-hasher + #:hash-password)) + +(in-package :ml-survey/security) + +(defclass user () + ((name :initarg :name :reader user-name) + (password-hash :initarg :password-hash :reader user-password-hash))) + +(defclass password-hasher () + ((salt-length :initarg :salt-length :initform 8 :reader salt-length) + (iterations :initarg :iterations :initform 100000 :reader iterations) + (digest :initarg :digest :initform :sha256 :reader digest))) + +(defgeneric hash-password (hasher password) + (:documentation "Hash PASSWORD using the given HASHER.")) + +(defmethod hash-password ((hasher password-hasher) password) + (let* ((salt (ironclad:make-random-salt (salt-length hasher))) + (password-bytes (ironclad:ascii-string-to-byte-array password)) + (derived-key (ironclad:pbkdf2-hash-password password-bytes + :salt salt + :iterations (iterations hasher) + :digest (digest hasher)))) + (concatenate 'string + (ironclad:byte-array-to-hex-string salt) + ":" + (ironclad:byte-array-to-hex-string derived-key))))