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

  "Puts a signed version of the given message using given secret key into the
  given out buffer."
  [out sk m]
  (let [mlen (alength ^bytes m)]
    (.crypto_sign sodium out nil m mlen sk)
    out))

(defn signed
  "Produces a signed version of the given message m using given secret key."
  [sk m]
  (let [sm (byte-array (+ bytes (alength ^bytes 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]
  (let [mlen (alength ^bytes m)]
    (.crypto_sign_detached sodium out nil m mlen sk)
    out))

(defn sign
  "Produces a detached signature for a message m using given secret key."

  message. When given a valid signature, returns nil. When given an
  invalid signed message or signature, raises RuntimeException."
  ([pk sm]
   (let [smlen (buflen sm)
         m (byte-array (- smlen bytes))
         res (.crypto_sign_open sodium m nil sm smlen pk)]
     (if (zero? res)
       m
       (throw (RuntimeException. "Signature validation failed")))))
  ([pk msg sig]
   (let [mlen (buflen msg)
         res (.crypto_sign_verify_detached sodium sig msg mlen pk)]
     (when-not (zero? res)
       (throw (RuntimeException. "Signature validation failed"))))))
