 different types.
 It comes with default implementation for: string,
 bytes, input stream, file, url and uri."
-  (make-poly1305 [obj key] "Calculate poly1305 mac for type.")
-  (verify-poly1305 [obj signature key] "Verify poly1305 mac for type."))
+  (make-poly1305 [obj key iv enginefactory] "Calculate poly1305 mac for type."))
+
+(alter-meta! #'make-poly1305 assoc :no-doc true :private true)
 
 (extend-protocol Poly1305Mac
   (Class/forName "[B")
-  (make-poly1305 [^bytes data ^String key]
-    (make-poly1305-plain-impl data key))
-  (verify-poly1305 [^bytes data ^bytes signature ^String key]
-    (verify-poly1305-impl data signature key))
+  (make-poly1305 [^bytes data ^bytes key ^bytes iv ^IFn enginefactory]
+    (make-poly1305-plain-impl data key iv enginefactory))
 
   java.lang.String
-  (make-poly1305 [^String data ^String key]
-    (make-poly1305-plain-impl (->byte-array data) key))
-  (verify-poly1305 [^String data ^bytes signature ^String key]
-    (verify-poly1305-impl (->byte-array data) signature key))
+  (make-poly1305 [^String data ^bytes key ^bytes iv ^IFn enginefactory]
+    (make-poly1305-plain-impl (->byte-array data) key iv enginefactory))
 
   java.io.InputStream
-  (make-poly1305 [^java.io.InputStream data ^String key]
-    (make-poly1305-stream-impl data key))
-  (verify-poly1305 [^java.io.InputStream data ^bytes signature ^String key]
-    (verify-poly1305-impl data signature key))
+  (make-poly1305 [^java.io.InputStream data ^bytes key ^bytes iv ^IFn enginefactory]
+    (make-poly1305-stream-impl data key iv enginefactory))
 
   java.io.File
-  (make-poly1305 [^java.io.File data ^String key]
-    (make-poly1305-stream-impl (io/input-stream data) key))
-  (verify-poly1305 [^java.io.File data ^bytes signature ^String key]
-    (verify-poly1305-impl (io/input-stream data) signature key))
+  (make-poly1305 [^java.io.File data ^bytes key ^bytes iv ^IFn enginefactory]
+    (make-poly1305-stream-impl (io/input-stream data) key iv enginefactory))
 
   java.net.URL
-  (make-poly1305 [^java.net.URL data ^String key]
-    (make-poly1305-stream-impl (io/input-stream data) key))
-  (verify-poly1305 [^java.net.URL data ^bytes signature ^String key]
-    (verify-poly1305-impl (io/input-stream data) signature key))
+  (make-poly1305 [^java.net.URL data ^bytes key ^bytes iv ^IFn enginefactory]
+    (make-poly1305-stream-impl (io/input-stream data) key iv enginefactory))
 
   java.net.URI
-  (make-poly1305 [^java.net.URI data ^String key]
-    (make-poly1305-stream-impl (io/input-stream data) key))
-  (verify-poly1305 [^java.net.URI data ^bytes signature ^String key]
-    (verify-poly1305-impl (io/input-stream data) signature key)))
+  (make-poly1305 [^java.net.URI data ^bytes key ^bytes iv ^IFn enginefactory]
+    (make-poly1305-stream-impl (io/input-stream data) key iv enginefactory)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; High level interface
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defn poly1305
+  "Make poly1305 mac for specified data, using arbitrary
+length key and 128 bits iv.
+Key can be any type that implements ByteArray protocol."
+  [data key ^bytes iv engine]
+  {:pre [(= (count iv) 16)]}
+  (let [key (->byte-array key)
+        ef  (resolve-engine-factory engine)]
+    (make-poly1305 data key iv ef)))
+
+(defn poly1305-verify
+  "Verify poly1305 mac for specified data and signature."
+  [data ^bytes signature pkey ^bytes iv engine]
+  {:pre [(= (count iv) 16)]}
+  (let [key (->byte-array pkey)
+        ef  (resolve-engine-factory engine)]
+    (verify-poly1305-impl data signature key iv ef)))
+
+(def ^{:doc "Alias for Poly1305 + AES mac."}
+  poly1305-aes #(poly1305 %1 %2 %3 :aes))
+
+(def ^{:doc "Alias for Poly1305 + AES mac verify function."}
+  poly1305-aes-verify #(poly1305-verify %1 %2 %3 %4 :aes))
+
+(def ^{:doc "Alias for Poly1305 + Twofish mac."}
+  poly1305-twofish #(poly1305 %1 %2 %3 :twofish))
+
+(def ^{:doc "Alias for Poly1305 + Twofish mac verify function."}
+  poly1305-twofish-verify #(poly1305-verify %1 %2 %3 %4 :twofish))
+
+(def ^{:doc "Alias for Poly1305 + Serpent mac."}
+  poly1305-serpent #(poly1305 %1 %2 %3 :serpent))
+
+(def ^{:doc "Alias for Poly1305 + Serpent mac verify function."}
+  poly1305-serpent-verify #(poly1305-verify %1 %2 %3 %4 :serpent))

    (.doFinal mac out 0)
    out))

(declare make-poly1305)

(defn- verify-poly1305-impl
  [data signature pkey]
  (let [sig (make-poly1305 data pkey)]
    (Arrays/equals sig signature)))

(defprotocol Poly1305Mac

    out))

(defn- make-poly1305-stream-impl
  [^java.io.InputStream stream ^bytes pkey ^bytes iv ^IFn enginefactory]
  (let [mac  (Poly1305. (enginefactory))
        out  (byte-array 16)
        kp   (KeyParameter. (key->poly1305key pkey))
        pwi  (ParametersWithIV. kp iv)
        bfr  (byte-array 5120)]
    (.init mac pwi)
