 (ns caesium.crypto.sign
   (:refer-clojure :exclude [bytes])
   (:require [caesium.binding :as b]
-            [caesium.byte-bufs :refer [buflen]]))
+            [caesium.byte-bufs :as bb]))
 
 (b/defconsts [bytes seedbytes publickeybytes secretkeybytes primitive])
 

(defn signed-to-buf!
  "Puts a signed version of the given message using given secret key into the
  given out buffer."
  [out sk m]
  (.crypto_sign b/sodium out nil m (buflen m) sk)
  out)

(defn signed
  "Produces a signed version of the given message m using given secret key."
  [sk m]
  (let [sm (byte-array (+ bytes (buflen m)))]
    (signed-to-buf! sm sk m)))

(defn sign-to-buf!
  "Puts a signature of the given message using given secret key into the given
  out buffer."
  [out sk m]
  (.crypto_sign_detached b/sodium out nil m (buflen m) sk)
  out)

(defn sign
  "Produces a detached signature for a message m using given secret key."
  [sk m]
  (let [sig (byte-array bytes)]
    (sign-to-buf! sig sk m)))

(defn verify
  "Verify a signed message or a message and a detached signature.

  message. When given a valid signature, returns nil. When given an
  invalid signed message or signature, raises RuntimeException."
  ([pk sm]
   (let [m (bb/alloc (- (bb/buflen sm) bytes))
         sm (bb/->indirect-byte-buf sm)
         pk (bb/->indirect-byte-buf pk)
         res (b/✨ sign-open m sm pk)]
     (if (zero? res)
       (bb/->bytes m)
       (throw (RuntimeException. "Signature validation failed")))))
  ([pk m sig]
   (let [sig (bb/->indirect-byte-buf sig)
         m (bb/->indirect-byte-buf m)
         pk (bb/->indirect-byte-buf pk)
         res (b/✨ sign-verify-detached sig m pk)]
     (when-not (zero? res)
       (throw (RuntimeException. "Signature validation failed"))))))
