summaryrefslogtreecommitdiff
path: root/src/mulk/benki/genkey.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/mulk/benki/genkey.clj')
-rw-r--r--src/mulk/benki/genkey.clj132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/mulk/benki/genkey.clj b/src/mulk/benki/genkey.clj
new file mode 100644
index 0000000..0378181
--- /dev/null
+++ b/src/mulk/benki/genkey.clj
@@ -0,0 +1,132 @@
+(ns mulk.benki.genkey
+ (:refer-clojure)
+ (:use [clojure core repl pprint]
+ [hiccup core page-helpers]
+ [mulk.benki config util db webutil]
+ [clojure.core.match
+ :only [match]]
+ [noir core]
+ [clojure.java.jdbc :only [transaction do-commands]])
+ (:require [noir.session :as session]
+ [noir.response :as response]
+ [noir.request :as request]
+ [clojure.java.jdbc :as sql]
+ [com.twinql.clojure.http :as http])
+ (:import [org.bouncycastle.jcajce.provider.asymmetric.rsa
+ BCRSAPublicKey]
+ [org.bouncycastle.cert
+ X509v3CertificateBuilder
+ X509CertificateHolder]
+ [org.bouncycastle.operator
+ DefaultSignatureAlgorithmIdentifierFinder
+ DefaultDigestAlgorithmIdentifierFinder]
+ [org.bouncycastle.operator.bc
+ BcRSAContentSignerBuilder]
+ [org.bouncycastle.asn1.x509
+ X509Name
+ SubjectPublicKeyInfo]
+ [org.bouncycastle.asn1.x500
+ X500Name]))
+
+
+
+(defonce signing-keypair
+ (-> (doto (org.bouncycastle.crypto.generators.RSAKeyPairGenerator.)
+ (.init (org.bouncycastle.crypto.params.RSAKeyGenerationParameters.
+ (BigInteger. "123") (java.security.SecureRandom.) 512 123)))
+ (.generateKeyPair)))
+
+(defonce cert-signer
+ (let [sig-id (.find (DefaultSignatureAlgorithmIdentifierFinder.) "SHA1withRSA")
+ digest-id (.find (DefaultDigestAlgorithmIdentifierFinder.) sig-id)
+ ;;digest-id (.find (DefaultDigestAlgorithmIdentifierFinder.) "SHA1")
+ ]
+ (-> (BcRSAContentSignerBuilder. sig-id digest-id)
+ (.build (.getPrivate signing-keypair)))))
+
+(defonce cert-serial
+ (atom 1N))
+
+(defn join-lines [s]
+ (apply str (clojure.string/split s #"\n")))
+
+(defn decode-spkac [spkac]
+ (org.bouncycastle.mozilla.SignedPublicKeyAndChallenge.
+ (ring.util.codec/base64-decode (join-lines spkac))))
+
+(defmulti spkac-pubkey->map type)
+
+(defmethod spkac-pubkey->map BCRSAPublicKey [pubkey]
+ {:modulus (.getModulus pubkey)
+ :exponent (.getPublicExponent pubkey)})
+
+(defn spkac-pubkey [creq]
+ (spkac-pubkey->map
+ (.getPublicKey creq "BC")))
+
+(defn now []
+ (java.util.Date.))
+
+(defn twenty-years-from-now []
+ (java.util.Date. (+ (* 20 3600 24 365 1000) (.getTime (now)))))
+
+(defn sign-spkac [spkac]
+ (let [serial (swap! cert-serial inc)
+ pubkeyinfo (-> spkac
+ (.getPublicKeyAndChallenge)
+ (.getSubjectPublicKeyInfo))
+ builder (X509v3CertificateBuilder.
+ (X500Name. "CN=Guenologlyan Mages Association")
+ (java.math.BigInteger. (str serial))
+ (now)
+ (twenty-years-from-now)
+ (X500Name. "CN=Benki User")
+ pubkeyinfo)
+ cert (.build builder cert-signer)]
+ cert))
+
+(defpage "/genkey" []
+ (redirect "/keys"))
+
+(defpage [:post "/keys/register"] []
+ (let [spkac-data (get-in (request/ring-request) [:params :key])
+ spkac (decode-spkac spkac-data)
+ pubkey (spkac-pubkey spkac)]
+ (with-dbt
+ (query "INSERT INTO rsa_keys (modulus, exponent) VALUES (?::NUMERIC, ?::NUMERIC) RETURNING 't'"
+ (str (:modulus pubkey)) (str (:exponent pubkey)))
+ (query "INSERT INTO user_rsa_keys (\"user\", modulus, exponent) VALUES (?, ?::NUMERIC, ?::NUMERIC) RETURNING 't'"
+ *user* (str (:modulus pubkey)) (str (:exponent pubkey)))
+ ;;(redirect (linkrel :keys))
+ {:status 200
+ :headers {"Content-Type" "application/x-x509-user-cert"}
+ :body (.getEncoded (sign-spkac spkac))})))
+
+(defpage "/keys" []
+ (with-auth
+ (layout {} "Key Management"
+ [:p
+ [:h2 "Your Keys"]
+ [:table
+ {:style "border: 1px solid #000"
+ :border "1"}
+ [:thead
+ [:th {:style "text-align: left"} "Exponent"]
+ [:th {:style "text-align: left"} "Modulus"]]
+ [:tbody
+ (with-dbt
+ (for [{e :exponent, m :modulus}
+ (query "select * from user_rsa_keys where \"user\" = ?" *user*)]
+ [:tr
+ [:td e]
+ [:td m]]))]]]
+ [:p
+ [:h2 "Generate a Key Pair"]
+ [:h3 "RSA"]
+ [:form {:method "POST", :action (linkrel :keys :register)}
+ [:keygen {:name "key", :keytype "RSA"}]
+ [:input {:type "submit" :value "Generate"}]]
+ [:h3 "ECDSA"
+ [:form {:method "POST", :href (linkrel :keys :register)}
+ [:keygen {:name "key", :keytype "EC", :keyparams "secp521r1"}]
+ [:input {:type "submit" :value "Generate"}]]]])))