Begin (provisional!!) RSA key management

This commit is contained in:
Jaidyn Ann 2023-09-14 18:45:03 -05:00
parent b5a1b1f645
commit 504e155f5d
2 changed files with 90 additions and 5 deletions

View File

@ -1,3 +1,3 @@
(defsystem "activitypub-servist"
:depends-on ("alexandria" "clack" "purl" "str" "webtentacle" "yason")
:depends-on ("alexandria" "clack" "inferior-shell" "ironclad" "purl" "str" "webtentacle" "yason")
:components ((:file "activitypub-servist")))

View File

@ -19,8 +19,6 @@
(in-package #:activitypub-servist)
;;(ql:quickload '(alexandria asn1 clack cl-base64 ironclad purl str trivia trivial-utf-8 webtentacle yason))
(defun users ()
"List of the server's usernames."
@ -29,7 +27,7 @@
(defun directories ()
"Alist of the server's paths and their response functions."
'(("u/" . http-dir) (".well-known/webfinger" . http-webfinger)))
'(("u/" . http-user-dir) (".well-known/webfinger" . http-webfinger)))
@ -131,7 +129,6 @@ the plist in the docstring for its WEBTENTACLE:SERVER function."
("404, you goddamn fool!")))
;; ————————————————————————————————————————
;; Invocation
;; ————————————————————————————————————————
@ -204,3 +201,91 @@ or “/bear/apple/” or “/bear/”, but not “/bear” (not a directory)."
"Split a pathname into a list of its components.
/u/bear/apple.txt '(u bear apple.txt)"
(str:split #\/ pathname :omit-nulls 't))
;; ————————————————————————————————————————
;; RSA keys
;; ————————————————————————————————————————
;; At the moment, Ive yet to use figure out how to create PEM representations of
;; a public keypair properly in Lisp.
;; So at the moment, keys are generated into PEM files by the openssl binary on
;; the hosts system; and the output of the openssl command is used to parse into
;; Ironclad keys.
;; In the future, Ill stop that. But at the moment,I want to focus on other core
;; parts of ActivityPub; Ive tired of messing with ASN1 & co.
(defun parse-openssl-output (lines &optional (results '()))
"When passed the output of the shell command `openssl rsa -text -noout`, will
parse the output into a plist containing relavent numbers:
:n (modulus), :e (public exponent), :d (private exponent), :p (1st prime),
:q (2nd prime), :e1 (1st exponent), :e2 (2nd exponent), and :c (coefficient)."
(let ((line (str:trim (car lines))))
(cond
((not lines)
(mapcar
(lambda (result-item)
(if (stringp result-item)
(parse-integer (str:replace-all ":" "" result-item) :radix 16)
result-item))
results))
((str:starts-with-p "Private" line)
(parse-openssl-output (cdr lines) results))
((str:starts-with-p "modulus:" line)
(parse-openssl-output (cdr lines) (nconc results '(:n))))
((str:starts-with-p "prime1" line)
(parse-openssl-output (cdr lines) (nconc results '(:p))))
((str:starts-with-p "prime2" line)
(parse-openssl-output (cdr lines) (nconc results '(:q))))
((str:starts-with-p "exponent1" line)
(parse-openssl-output (cdr lines) (nconc results '(:e1))))
((str:starts-with-p "exponent2" line)
(parse-openssl-output (cdr lines) (nconc results '(:e2))))
((str:starts-with-p "coefficient" line)
(parse-openssl-output (cdr lines) (nconc results '(:c))))
((str:starts-with-p "privateExponent" line)
(parse-openssl-output (cdr lines) (nconc results '(:d))))
((str:starts-with-p "publicExponent" line)
(parse-openssl-output
(cdr lines)
(nconc
results
(list
:e
(parse-integer
(car (str:split #\space
(str:replace-first
"publicExponent: "
""
line))))))))
('t
(let* ((last-element (car (last results)))
(total-string (if (stringp last-element)
(str:concat last-element line)
line)))
(parse-openssl-output (cdr lines)
(if (stringp last-element)
(nconc (reverse (cdr (reverse results)))
(list total-string))
(nconc results
(list total-string)))))))))
(defun openssl-shell-pem-keypair (pem-file)
"Given a private RSA PEM file, this will parse it into two returned values:
An Ironclad private key, and an Ironclad public key."
(let ((key-values
(parse-openssl-output
(inferior-shell:run/lines
(str:concat "openssl rsa -text -noout -in " pem-file)))))
(values (ironclad:make-private-key
:rsa
:n (getf key-values :n)
:e (getf key-values :e)
:d (getf key-values :d)
:p (getf key-values :p)
:q (getf key-values :q))
(ironclad:make-public-key
:rsa
:n (getf key-values :n)
:e (getf key-values :e)))))