Created
January 9, 2010 01:42
-
-
Save anonymous/272648 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns com.bebop.gate (:gen-class) | |
(:import [java.security KeyPair KeyPairGenerator] | |
[org.jasypt.util.password StrongPasswordEncryptor] | |
[org.apache.commons.codec.binary Base64]) | |
(:use dk.bestinclass.clojureql) | |
(:require [dk.bestinclass.clojureql.backend.derby :as derby])) | |
(def *conn-info* (make-connection-info "derby" ".gate/db;create=true")) | |
(defmacro dosql [& forms] `(run *conn-info* ~@forms)) | |
(defn setup | |
[] | |
(try (dosql | |
(create-table | |
users | |
[id int | |
username "varchar(64)" | |
password "varchar(64)" | |
public_key "varchar(1024)" | |
private_key "varchar(1024)"] | |
:primary-key id | |
:auto-inc id | |
:unique username | |
:not-nulls [id username password public_key private_key]) | |
) | |
(catch java.sql.SQLException e | |
(when (empty? (re-seq #"exists" (.getMessage e))) (throw e))) | |
)) | |
(defn generate-keys | |
"Generates RSA Keys of a given bit length." | |
([algo length] | |
(let [gen (doto (KeyPairGenerator/getInstance algo) (.initialize 1024)) | |
keypair (.generateKeyPair gen) | |
ders (doall (map #(.encode %1) [(.getPublic keypair) (.getPrivate keypair)])) | |
b64ders (doall (map #(Base64/encodeBase64 %1) ders)) | |
surround #(str "-----BEGIN " %1 " KEY-----\n" %2 "-----END " %1 " KEY-----\n")] | |
[(surround "PUBLIC" (String. (first b64ders))) | |
(surround "PRIVATE" (String. (second b64ders)))] | |
)) | |
([length] (generate-keys "rsa" length)) | |
([] (generate-keys 1024))) | |
(def *password-encryptor* (new StrongPasswordEncryptor)) | |
(def password-encryptor (constantly *password-encryptor*)) | |
(defn hash-password | |
"Strongly hash password" | |
[pword] | |
(-> (password-encryptor) (.encryptPassword pword))) | |
(defn lookup | |
"Retrieves login record optionally with public private keys" | |
([username withpublic withprivate] | |
(dosql | |
(cond | |
(and withpublic withprivate) (query [username password] users (= username ~username)) | |
withpublic (query users [username password public_key] (= username ~username)) | |
withprivate (query users [username password withprivate] (= username ~username)) | |
:else (query users * (= username ~username)) | |
))) | |
([username withpublic] (lookup username withpublic false)) | |
([username] (lookup username false false))) | |
(defn insert | |
"Write user to the Database" | |
[username password publickey privatekey] | |
(let [hpword (hash-password password)] | |
(dosql (insert-into users | |
[username ~username | |
password ~hpword | |
public_key ~publickey | |
private_key ~privatekey])))) | |
(defn register | |
"Registers a new username and password." | |
[username password] | |
(when-not (lookup username false false) | |
(let [[pub priv] (generate-keys)] | |
(dosql (insert username password pub priv))) | |
)) | |
(defn check-password | |
"Checks supplied password against hashed password in database." | |
[supplied hashed] | |
(-> (password-encryptor) (.checkPassword supplied hashed))) | |
(defn login | |
"Check username against password. Returns the public and private key." | |
[username password] | |
(when-let [user (lookup username)] | |
(if (check-password password (user :password)) | |
user | |
false))) | |
(defn reset-keys | |
[username password] | |
(when (login username) | |
(let [[pub priv] (generate-keys)] | |
(dosql (update users [public_key ~pub private_key ~priv] (= username ~username))) | |
))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment