   (:require [caesium.crypto.generichash :as g]
             [caesium.crypto.secretbox :as s]
             [caesium.randombytes :as r]
-            [caesium.byte-bufs :as bb])
+            [caesium.byte-bufs :as bb]
+            [caesium.util :as u]
+            [taoensso.timbre :refer [spy info]])
   (:import (java.nio ByteBuffer)))
 
 (def keybytes s/keybytes)
+
+(defn secretbox-pfx-to-buf!
+  "Like [[secretbox-pfx]], but you manage the output buffer. See that fn for
+  details.
+
+  All buffers must be `java.nio.ByteBuffer`.
+
+  Buffer `c` must be of length of `m` + [[s/noncebytes]] + [[s/macbytes]]."
+  [^ByteBuffer c ^ByteBuffer m ^ByteBuffer n ^ByteBuffer k]
+  (.put c n)
+  (s/secretbox-easy-to-buf! c m n k))
 
 (defn secretbox-pfx
   "secretbox, with the given nonce embedded in the ciphertext as a prefix.

  To decrypt, use [[decrypt]] or [[open]], depending on which argument order
  you prefer."
  [m n k]
  (let [mlen (bb/buflen m)
        clen (+ s/macbytes mlen)
        outlen (+ s/noncebytes clen)
        out (byte-array outlen)
        cbuf (ByteBuffer/wrap out s/noncebytes clen)]
    (System/arraycopy n 0 out 0 s/noncebytes)
    (s/secretbox-easy-to-buf! cbuf m n k)
    out))

(defn ^:private random-nonce!

(defn open-to-buf!
  "Decrypts any secretbox message with a prefix nonce into the given buffer.

  This splits the given ciphertext buffer into the nonce and the
  resulting ciphertext and then defers to [[s/secretbox-open-easy-to-buf!]].

  All arguments must be `java.nio.ByteBuffer`.

  Analogous to [[caesium.crypto.secretbox/secretbox-open-easy-to-buf!]]."
  [m ^ByteBuffer c k]
  (info "c before dup" c)
  (info "c contents" (u/hexify (bb/->bytes c)))
  (let [n (-> c (.duplicate) (.limit s/noncebytes))
        c (-> c (.duplicate) (.position s/noncebytes))]
    (spy (u/hexify (bb/->bytes n)))
    (spy (u/hexify (bb/->bytes c)))
    (s/secretbox-open-easy-to-buf! m (spy c) (spy n) k)))

(defn open
  "Decrypts any secretbox message with a prefix nonce.

  Analogous to [[caesium.crypto.secretbox/secretbox-open-easy]]."
  [c k]
  (let [m (bb/alloc (- (bb/buflen c) s/noncebytes s/macbytes))]
    (open-to-buf! m (bb/->indirect-byte-buf c) (bb/->indirect-byte-buf k))
    (bb/->bytes m)))

(defn decrypt-to-buf!
  "Like [[open-to-buf!]], but with different argument order."
