diff options
Diffstat (limited to 'src/eris.lisp')
-rw-r--r-- | src/eris.lisp | 128 |
1 files changed, 42 insertions, 86 deletions
diff --git a/src/eris.lisp b/src/eris.lisp index 8f836f8..7efdc73 100644 --- a/src/eris.lisp +++ b/src/eris.lisp @@ -21,69 +21,44 @@ (defconstant 32kib 32768) (defconstant 1kib 1024) -(defclass reference-pair () - ((reference :initarg :reference :accessor reference :type (octet-vector 32)) - (key :initarg :key :accessor key :type (octet-vector 32)))) - (define-constant null-secret (make-array 32 :element-type 'octet :initial-element 0) :test #'equalp :documentation "32-byte null vector.") -(defun reference-pair-to-octets (pair buf &optional (start 0)) - "Convert a reference-pair object PAIR into the standard binary representation by -filling the buffer BUF from the START keyword argument. " - (declare (type vector buf)) - (replace buf (reference pair) :start1 start) - (replace buf (key pair) :start1 (+ 32 start))) - -(defun octets-to-reference-pair (octets &optional (start 0)) - "Convert the standard reference-pair binary representation into a reference-pair -object, using the bytes from the OCTETS vector from at START." - (declare (type vector octets)) - (make-instance 'reference-pair :key (subseq octets (+ 32 start) (+ 64 start)) - :reference (subseq octets start (+ 32 start)))) - - -(defun compute-reference (block) - (declare (type octet-vector block)) - (let ((reference (make-array 32 :element-type 'octet))) - (ironclad:digest-sequence :blake2/256 block :digest reference) - reference)) - (defun make-nonce (level) (let ((nonce (make-array 12 :element-type 'octet :initial-element 0))) (setf (aref nonce 0) level) nonce)) -(defun encrypt-block (input secret reference) - (declare (type octet-vector input secret reference)) + +(defun encrypt-block (input secret) + (declare (type octet-vector input secret)) (let ((mac (ironclad:make-mac :blake2-mac secret :digest-length 32)) - (key (make-array 32 :element-type 'octet))) + (rk (make-array 64 :element-type 'octet))) ;; reference-key pair (ironclad:update-mac mac input) - (ironclad:produce-mac mac :digest key) - ;; NOT the IETF chacha. Need to fix this by patching ironclad. Maybe. - (ironclad:encrypt-in-place (ironclad:make-cipher :chacha :mode :stream :key key + (ironclad:produce-mac mac :digest rk :digest-start 32) ;; get key + (ironclad:encrypt-in-place (ironclad:make-cipher :chacha :mode :stream :key (subseq rk 32 64) :initialization-vector null-secret) - input) - (ironclad:digest-sequence :blake2/256 input :digest reference) - (make-instance 'reference-pair :key key :reference reference))) - -(defun encrypt-internal-block (input reference nonce) - (declare (type octet-vector input reference)) - (let ((key (make-array 32 :element-type 'octet))) - (ironclad:digest-sequence :blake2/256 input :digest key) - ;; NOT the IETF chacha. Need to fix this by patching ironclad. Maybe. - (ironclad:encrypt-in-place (ironclad:make-cipher :chacha :mode :stream :key key + input) ;; encrypt block + (ironclad:digest-sequence :blake2/256 input :digest rk) ;; get reference + rk)) + + +(defun encrypt-internal-block (input nonce) + (declare (type octet-vector input)) + (let ((rk (make-array 64 :element-type 'octet))) ;; reference-key pair + (ironclad:digest-sequence :blake2/256 input :digest rk :digest-start 32);; get key + (ironclad:encrypt-in-place (ironclad:make-cipher :chacha :mode :stream :key (subseq rk 32 64) :initialization-vector nonce) - input) - (ironclad:digest-sequence :blake2/256 input :digest reference) - (make-instance 'reference-pair :key key :reference reference))) + input) ;; encrypt block + (ironclad:digest-sequence :blake2/256 input :digest rk) ;; get reference + rk)) -(defun decrypt-block (input key &optional (nonce null-secret)) - (declare (type octet-vector input key nonce)) +(defun decrypt-block (input rk &optional (nonce null-secret)) + (declare (type octet-vector input rk nonce)) (ironclad:decrypt-in-place - (ironclad:make-cipher :chacha :mode :stream :key key :initialization-vector nonce) + (ironclad:make-cipher :chacha :mode :stream :key (subseq rk 32 64) :initialization-vector nonce) input) input) @@ -107,7 +82,8 @@ a (simple-array (unsigned-byte 8)) object." (1024 (setf (aref cap 0) #x0a)) (32768 (setf (aref cap 0) #x0f))) (setf (aref cap 1) (level read-capability)) - (reference-pair-to-octets (reference-pair read-capability) cap 2))) + (replace cap (reference-pair read-capability) :start1 2) + cap)) (-> octets-to-read-capability ((octet-vector 66)) (values read-capability &optional)) (defun octets-to-read-capability (octets) @@ -126,7 +102,9 @@ versioning bytes are not supported by eris-cl." (setf (level capability) (aref octets 1)) (setf (reference-pair capability) - (octets-to-reference-pair octets 2)) + (let ((kr (make-array 64 :element-type 'octet))) + (replace kr octets :start2 2) + kr)) ;; TODO CHECK CORRECTNESS capability)) (-> read-capability-to-urn (read-capability) string) @@ -165,34 +143,17 @@ versioning bytes are not supported by eris-cl." (setf (aref padded-input (length input)) #x80) padded-input)) -(defvar *output-hashmap* nil) - (defmacro output-block (ref-vector) - `(let ((reference (compute-reference block))) - (if hash-output - (if (gethash reference *output-hashmap*) - block - (let ((rk (encrypt-block block secret reference))) - (vector-push-extend rk ,ref-vector) - (setf (gethash reference *output-hashmap*) t) - (funcall output-function block (reference rk)))) - (let ((rk (encrypt-block block secret reference))) - (vector-push-extend rk ,ref-vector) - (funcall output-function block (reference rk)))))) + `(let ((rk (encrypt-block block secret))) + (vector-push-extend rk ,ref-vector) + (funcall output-function block (subseq rk 0 32)))) (defmacro output-internal-block (ref-vector nonce) - `(let ((reference (compute-reference block))) - (if hash-output - (unless (gethash reference *output-hashmap*) - (let ((rk (encrypt-internal-block block reference ,nonce))) - (vector-push-extend rk ,ref-vector) - (setf (gethash reference *output-hashmap*) t) - (funcall output-function block (reference rk)))) - (let ((rk (encrypt-internal-block block reference ,nonce))) - (vector-push-extend rk ,ref-vector) - (funcall output-function block (reference rk)))))) - -(defgeneric eris-encode (input block-size output-function &key secret hash-output) + `(let ((rk (encrypt-internal-block block ,nonce))) + (vector-push-extend rk ,ref-vector) + (funcall output-function block (subseq rk 0 32)))) + +(defgeneric eris-encode (input block-size output-function &key secret) (:documentation "Encode an INPUT into BLOCK-SIZE (32kib or 1kib) blocks, that are output using the function OUTPUT-FUNCTION. This function wil be called with two arguments: an @@ -201,12 +162,9 @@ a (SIMPLE-ARRAY (UNSIGNED-BYTE 8)) of equal size to the one given, which will be destructively modified. Returns a read-capability object. An optional 32-byte secret can be passed for additional encryption using the -SECRET keyword argument. - -The HASH-OUTPUT keyword argument controls whether a hash-table is used to -guarantee that a reference is only output once.")) +SECRET keyword argument.")) -(defmethod eris-encode ((input vector) block-size output-function &key (secret null-secret) (hash-output t)) +(defmethod eris-encode ((input vector) block-size output-function &key (secret null-secret)) (declare (type block-size block-size) (type function output-function) (type (octet-vector 32) secret)) @@ -214,7 +172,6 @@ guarantee that a reference is only output once.")) (setf input (pad input block-size)) (let ((reference-vector (make-array 16 :adjustable t :fill-pointer 0)) - (*output-hashmap* (if hash-output (make-hash-table :test #'equalp) nil)) (block (make-array block-size :element-type 'octet :initial-element 0))) (declare (type octet-vector block)) (loop for i = 0 then (incf i) @@ -224,15 +181,14 @@ guarantee that a reference is only output once.")) (fill block 0))) ;; always bzero the buffer; this is unoptimal (it only needs to be zeroed out to eliminate trailing junk) ;; TODO: consider removing this entire function and replacing it with an octet stream - (eris-create-tree reference-vector block-size output-function :hash-output hash-output))) + (eris-create-tree reference-vector block-size output-function))) -(defmethod eris-encode ((input stream) block-size output-function &key (secret null-secret) hash-output) +(defmethod eris-encode ((input stream) block-size output-function &key (secret null-secret)) "This method does not handle any IO related conditions." (declare (type block-size block-size) (type function output-function) (type (octet-vector 32) secret)) (let ((reference-vector (make-array 16 :adjustable t :fill-pointer 0)) - (*output-hashmap* (if hash-output (make-hash-table :test #'equalp) nil)) (block (make-array block-size :element-type 'octet :initial-element 0))) (declare (type octet-vector block)) (loop for bytes-read = (read-sequence block input) @@ -242,9 +198,9 @@ guarantee that a reference is only output once.")) (fill block 0 :start (1+ bytes-read))) ;; bzero the buffer here to eliminate trailing junk do (progn (setf block (output-block reference-vector))) until (< bytes-read block-size)) - (eris-create-tree reference-vector block-size output-function :hash-output hash-output))) + (eris-create-tree reference-vector block-size output-function))) -(defun eris-create-tree (reference-vector block-size output-function &key hash-output) +(defun eris-create-tree (reference-vector block-size output-function) (declare (type block-size block-size) (type function output-function)) (loop with block-keys = (/ block-size 64) @@ -266,7 +222,7 @@ guarantee that a reference is only output once.")) do (progn (setf block (output-internal-block reference-vector-l nonce)) (setf i 0) (fill block 0)) - do (progn (reference-pair-to-octets rk block (* 64 i)) + do (progn (replace block rk :start1 (* 64 i)) (incf i)) finally (unless (zerop i) ;; If i is zero, then the amount of blocks is just |