first basic version of HS256 signing (for JWT creation)

This commit is contained in:
Helmut Merz 2024-08-24 19:54:02 +02:00
parent ccbd9cd4fe
commit a2a8474e93
3 changed files with 38 additions and 13 deletions

View file

@ -21,12 +21,12 @@
(setf (slot-value rec 'head) (util:rfill (head-fields rec) head)))
(defmethod print-object ((rec record) stream)
(print-unreadable-object (rec stream :type t)
(format-fields rec stream 'head 'data)))
(print-fields rec stream 'head 'data))
(defun format-fields (item stream &rest fields)
(let ((fm (format nil "~{~(~a~): ~~S ~}" fields)))
(apply #'format stream fm (mapcar #'(lambda (x) (funcall x item)) fields))))
(defun print-fields (rec stream &rest fields)
(let ((fm (util:make-vars-format fields)))
(print-unreadable-object (rec stream :type t)
(apply #'format stream fm (mapcar #'(lambda (x) (funcall x rec)) fields)))))
(defun head-value (rec key)
(elt (head rec) (position key (head-fields rec))))

View file

@ -63,6 +63,9 @@
(t:show-result))))
(deftest test-util ()
(util:lgi (util:create-secret))
(let ((now (get-universal-time)))
(== (util:from-unix-time (util:to-unix-time now)) now))
(== (util:rfill '(1 2 3 4 5) '(a b c)) '(a b c nil nil))
(== (util:rtrim '(1 2 nil 3 nil)) '(1 2 nil 3))
(== (util:to-keyword "hello-kitty") :hello-kitty)

View file

@ -4,8 +4,9 @@
(:use :common-lisp)
(:local-nicknames (:b64 :qbase64))
#+sbcl (:import-from :sb-ext #:add-package-local-nickname)
(:export #:lg #:lgd #:lgi
#:create-secret #:digest
(:export #:make-vars-format #:lg #:lgd #:lgi
#:from-unix-time #:to-unix-time
#:create-secret #:digest #:sign
#:rfill #:rtrim #:loop-plist #:filter-plist #:plist-pairs #:plist-equal
#:flatten-str #:to-keyword #:keyword-to-string #:to-integer #:to-string
#:absolute-dir #:check-dir #:ensure-dir #:home-path #:path-from-string
@ -14,27 +15,48 @@
(in-package :scopes/util)
;;;; logging shortcuts
;;;; formatting and logging shortcuts
(defun make-vars-format (vars)
(format nil "~{~(~a~): ~~S ~}" vars))
(defmacro lg (level &rest vars)
(let ((lm (find-symbol (string level) :log))
(fm (format nil "~{~(~a~): ~~S ~}" vars)))
(fm (make-vars-format vars)))
`(,lm ,fm ,@vars)))
(defmacro lgd (&rest vars) `(lg :debug ,@vars))
(defmacro lgi (&rest vars) `(lg :info ,@vars))
;;;; date and time manipulations
(defconstant *unix-time-base* (encode-universal-time 0 0 0 1 1 1970 0))
(defun from-unix-time (time)
(when time (+ time *unix-time-base*)))
(defun to-unix-time (time)
(when time (- time *unix-time-base*)))
;;;; secrets, digests, and other crypto stuff
(defun create-secret ()
(b64:encode-bytes (ironclad:random-data 16)))
(defun create-secret (&key (bytes 16) (scheme :original))
(b64:encode-bytes (ironclad:random-data bytes) :scheme scheme))
(defun digest (pw &key (scheme :original) (alg :sha256))
(defun digest (tx &key (scheme :original) (alg :sha256))
(b64:encode-bytes
(ironclad:digest-sequence alg
(flexi-streams:string-to-octets pw :external-format :utf8))
(flexi-streams:string-to-octets tx :external-format :utf8))
:scheme scheme))
(defun sign (tx key)
(let* ((binp (flexi-streams:string-to-octets tx :external-format :utf8))
(bkey (make-array 16 :element-type '(unsigned-byte 8)
:initial-contents (b64:decode-string key)))
(mac (ironclad:make-mac :hmac bkey :sha256)))
(ironclad:update-mac mac binp)
(b64:encode-bytes (ironclad:hmac-digest mac) :scheme :uri)))
;;;; lists and loops
(defun rfill (ll ls)