From c4b44fb12108c0764d1fa4ef1c37f11a54379343 Mon Sep 17 00:00:00 2001 From: Piotr Szarmanski Date: Mon, 24 Oct 2022 10:50:11 +0200 Subject: Add hash-backend and update README. --- README | 17 +++++++++++++++++ eris.asd | 2 ++ src/eris-decode.lisp | 29 +++++++++++++++++++---------- src/eris.lisp | 1 + src/file-backend.lisp | 4 +++- src/hash-backend.lisp | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/package.lisp | 10 +++++++++- 7 files changed, 102 insertions(+), 12 deletions(-) create mode 100644 src/hash-backend.lisp diff --git a/README b/README index 21afb2f..606afba 100644 --- a/README +++ b/README @@ -41,3 +41,20 @@ function will attempt to decode an ERIS read-capability in parallel into a file specified by the OUTPUT-FILE string or pathspec. See the docstrings of the specific functions for more details. + + + +A high-level API is provided for convenience in backend.lisp. The concept is +that a backend object is created, which holds information like output-function, +fetch-function, caching details, block-size, etc. and the {en/de}coding +functions simply take the backend as an argument. + +This interface consists of two generic functions: store-data, for encoding data, +and fetch-read-capability, for retrieving the contents of a read-capability +object. + +As an example, a file-based backend called file-backend is provided. It can be +used simply by making an instance of the 'file-backend class with a :directory +argument, which will point to the directory in which ERIS data is to be stored. + +There is also hash-backend, which implements a simple hash-table backend. diff --git a/eris.asd b/eris.asd index 0ec5c7f..1c18f7f 100644 --- a/eris.asd +++ b/eris.asd @@ -13,6 +13,8 @@ (:file "base32") (:file "eris") (:file "eris-decode") + (:file "backend") + (:file "file-backend") #+unix (:file "parallel-decoder")))) :in-order-to ((test-op (test-op :eris/test)))) diff --git a/src/eris-decode.lisp b/src/eris-decode.lisp index ba20e9d..3d93312 100644 --- a/src/eris-decode.lisp +++ b/src/eris-decode.lisp @@ -218,19 +218,28 @@ hash-table is used, a (copy-seq) needs to be done on the return value of gethash. The keyword argument CACHE-CAPACITY indicates the amount of blocks stored in the -cache." +cache. It may be NIL to turn off caching entirely." (declare (type read-capability read-capability) (type function fetch-function) - (type integer cache-capacity)) + (type (or integer null) cache-capacity)) (with-slots (level block-size root-reference-pair) read-capability - (let* ((get-block (cached-lambda (:cache-class 'lru-cache - :capacity cache-capacity - :table (make-hash-table :size (1+ cache-capacity) :test #'equalp)) - (reference key &optional nonce) - (let* ((block (execute-fetch-function fetch-function reference))) - (unless block (error 'missing-block :reference reference)) - (hash-check block reference) - (decrypt-block block key nonce)))) + (let* ((get-block (if cache-capacity ;; handle caching + (cached-lambda (:cache-class 'lru-cache + :capacity cache-capacity + :table (make-hash-table :size (1+ cache-capacity) :test #'equalp)) + (reference key nonce) + (declare (type octet-vector reference key)) + (let ((block (execute-fetch-function fetch-function reference))) + (declare (type octet-vector block)) + (hash-check block reference) + (decrypt-block block key nonce))) + (lambda (reference key nonce) + (declare (type octet-vector reference key) + (optimize (debug 3))) + (let ((block (execute-fetch-function fetch-function reference))) + (declare (type octet-vector block)) + (hash-check block reference) + (decrypt-block block key nonce))))) (root (funcall get-block (reference root-reference-pair) (key root-reference-pair) (make-nonce level)))) ;; "Implementations MUST verify the key appearing in the read capability ;; if level of encoded content is larger than 0." diff --git a/src/eris.lisp b/src/eris.lisp index 4693104..ed4a05e 100644 --- a/src/eris.lisp +++ b/src/eris.lisp @@ -81,6 +81,7 @@ object, using the bytes from the OCTETS vector from at START." (make-instance 'reference-pair :key key :reference reference))) (defun decrypt-block (input key &optional (nonce null-secret)) + (declare (type octet-vector input key nonce)) (ironclad:decrypt-in-place (ironclad:make-cipher :chacha :mode :stream :key key :initialization-vector nonce) input) diff --git a/src/file-backend.lisp b/src/file-backend.lisp index 2bb8693..03e3ef7 100644 --- a/src/file-backend.lisp +++ b/src/file-backend.lisp @@ -43,7 +43,9 @@ (lambda (reference) (let* ((base32 (bytes-to-base32-unpadded reference)) (file (merge-pathnames directory base32))) - (alexandria:read-file-into-byte-vector file))) + (if (probe-file file) + (alexandria:read-file-into-byte-vector file) + (error 'missing-block :reference reference)))) output-function (lambda (block reference) (let* ((base32 (bytes-to-base32-unpadded reference)) diff --git a/src/hash-backend.lisp b/src/hash-backend.lisp new file mode 100644 index 0000000..91dc673 --- /dev/null +++ b/src/hash-backend.lisp @@ -0,0 +1,51 @@ +;; This file is part of eris-cl. +;; Copyright (C) 2022 Piotr SzarmaƄski + +;; eris-cl is free software: you can redistribute it and/or modify it under the +;; terms of the GNU Lesser General Public License as published by the Free +;; Software Foundation, either version 3 of the License, or (at your option) any +;; later version. + +;; eris-cl is distributed in the hope that it will be useful, but WITHOUT ANY +;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +;; A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License along with +;; eris-cl. If not, see . + +(in-package :eris) + +(defclass hash-backend (encoding-backend decoding-backend) + ((table :type hash-table))) + +(defmethod shared-initialize :after ((hash-backend hash-backend) slot-names + &rest initargs + &key &allow-other-keys) + + (declare (ignore initargs slot-names)) + (let ((hash-table (make-hash-table :test #'equalp))) + (with-slots (table output-function fetch-function) hash-backend + (setf table hash-table + fetch-function (lambda (reference) + (declare (type octet-vector reference)) + (copy-seq (gethash reference hash-table))) + output-function (lambda (block reference) + (declare (type octet-vector block reference)) + (setf (gethash reference hash-table) + block)))))) + +(defmethod fetch-read-capability (read-capability (backend hash-backend) &key &allow-other-keys) + (declare (type read-capability read-capability)) + (with-slots (fetch-function) backend + (eris-decode read-capability fetch-function :cache-capacity nil))) + +(defmethod store-data (input (backend hash-backend) &key (secret null-secret) (block-size 1kib) &allow-other-keys) + (declare (type octet-vector secret)) + (with-slots (output-function) backend + (eris-encode input + block-size + output-function + :hash-output nil + :secret secret))) + + diff --git a/src/package.lisp b/src/package.lisp index 873a453..0265f74 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -43,4 +43,12 @@ #:padding-error #:version-mismatch #:hash-mismatch - #:invalid-internal-block)) + #:invalid-internal-block + #:missing-block + + #:store-data + #:fetch-read-capability + #:encoding-backend + #:decoding-backend + #:file-backend + #:hash-backend)) -- cgit v1.2.3