commit 20e696536cbdb48bbf5893e2433d83c5bbc1369d
Author: Simon Watson <spesk@pm.me>
Date: Fri Feb 11 20:39:25 2022 -0500
In progress. Not currently working
diff --git a/fin-lisp.lisp b/fin-lisp.lisp
index 6ac842b..b5c86bf 100644
--- a/fin-lisp.lisp
+++ b/fin-lisp.lisp
@@ -1,6 +1,8 @@
-(ql:quickload "cl-store")
+;;;(ql:quickload "cl-store")
+(ql:quickload "yason")
(ql:quickload "cl-ppcre")
(ql:quickload "unix-opts")
+(ql:quickload "ironclad")
;;; Features
;;; - Import records from old .txt format
@@ -57,8 +59,47 @@
(defun reload ()
(load "~/Repos/fin-lisp/fin-lisp.lisp"))
+(defun wfile (file-content file-path)
+ (alexandria:write-string-into-file
+ (concatenate 'string file-content) file-path :if-exists :overwrite
+ :if-does-not-exist :create))
+
+;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Encryption stuff ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;
+;;; See: https://www.cliki.net/Ironclad
+
+;;; Return cipher when provided key
+(defun get-cipher (key)
+ (ironclad:make-cipher
+ :blowfish
+ :mode :ecb
+ :key (ironclad:ascii-string-to-byte-array key)))
+
+;;; First serialize the file,
+;;; then encrypt it from disk
+(defun encrypt-records (key filename)
+ (let ((cipher (get-cipher key))
+ (file-content (uiop:read-file-string filename)))
+ (let ((content (ironclad:ascii-string-to-byte-array file-content)))
+ (ironclad:encrypt-in-place cipher content)
+ (wfile
+ (write-to-string (ironclad:octets-to-integer content))
+ (concatenate 'string filename ".enc")))))
+
+(defun decrypt-records (key filename)
+ (let ((cipher (get-cipher key))
+ (file-content (uiop:read-file-string filename)))
+ (let ((content (ironclad:integer-to-octets (parse-integer file-content))))
+ (ironclad:decrypt-in-place cipher content)
+ (coerce (mapcar #'code-char (coerce content 'list)) 'string))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; End Encryption Stuff ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
(defun reset-records ()
- (setf *records* (make-hash-table :test 'equalp)))
+ (setf *records* (make-hash-table :test 'equal)))
;; Called like: (add-month '202107)
(defun add-month (month-key)
@@ -97,17 +138,20 @@
(format t "~a : ~a~C" exp-key (gethash exp-key month-hash) #\linefeed))))
;;; Dump all records.
-;;; This will also be used for data serialization at some point
(defun dump-records ()
(let ((record-key-list (loop for key being the hash-keys of *records* collect key)))
(dolist (month-key record-key-list) (dump-month month-key))))
-(defun serialize-records (filename)
- (cl-store:store *records* filename))
+(defun serialize-records (key filename)
+ (with-open-file (stream filename
+ :direction :output
+ :if-exists :overwrite
+ :if-does-not-exist :create)
+ (yason:encode *records* stream))
+ (encrypt-records key filename))
-(defun deserialize-records (filename)
- ;(setf *records* (cl-store:restore (pathname filename))))
- (setf *records* (cl-store:restore filename)))
+(defun deserialize-records (key filename)
+
;; Import records from old perl version (plaintext file)
(defun import-records (filename)
@@ -168,7 +212,8 @@
"Invalid month"))
(if (string= answer "3")
(generic-handler
- (serialize-records (prompt-read "Enter filename"))
+ (serialize-records (prompt-read "Enter encryption key")
+ (prompt-read "Enter filename"))
"Serialization error or invalid filename"))
(if (string= answer "4")
(generic-handler
@@ -202,5 +247,5 @@
(when-option (matches :interactive-mode)
(progn
(interactive-mode)
- (quit)))))
+ (quit))))))