      :salt (hex->bytes salt)
      :password (hex->bytes password)
      :iterations (Integer/parseInt iterations)}))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Update Algorithm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defmethod must-update? :default
+  [{:keys [algorithm iterations]}]
+  (let [desired-iterations (get *default-iterations* algorithm)]
+    (and desired-iterations (> desired-iterations iterations))))
+
+(defmethod must-update? :scrypt
+  [{:keys [algorithm memcost cpucost]}]
+  (let [desired-memcost (get-in *default-iterations* [:scrypt :memcost])
+        desired-cpucost (get-in *default-iterations* [:scrypt :cpucost])]
+    (and desired-cpucost
+         desired-memcost
+         (or (> desired-memcost memcost)
+             (> desired-cpucost cpucost)))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Public Api

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Key Formatting
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defmulti format-password
  "Format password depending on algorithm."
  :algorithm)

(defmethod format-password :scrypt
  [{:keys [password salt cpucost memcost parallelism]}]

(defn check
  "Check if a unencrypted password matches
  with another encrypted password."
  ([attempt encrypted]
   (check attempt encrypted {}))
  ([attempt encrypted {:keys [limit setter prefered]}]
   (when (and attempt encrypted)
     (let [pwdparams (parse-password encrypted)]
       (if (and (set? limit) (not (contains? limit (:algorithm pwdparams))))
         false
         (let [attempt (str->bytes attempt)
               result (check-password pwdparams attempt)]
           (when (and result (fn? setter) (must-update? pwdparams))
             (setter attempt))
           result))))))
