summaryrefslogtreecommitdiff
path: root/src/eris.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/eris.lisp')
-rw-r--r--src/eris.lisp128
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