/
ssl.clj
91 lines (77 loc) · 3.87 KB
/
ssl.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
(ns herolabs.apns.ssl
(:use [clojure.tools.logging]
[clojure.java.io :only (input-stream)]
[clojure.string :only (join)])
(:import [org.apache.commons.codec.digest DigestUtils]
[java.security Security KeyStore]
[javax.net.ssl KeyManager KeyManagerFactory SSLContext SSLEngine TrustManager TrustManagerFactory X509TrustManager]
[java.security.cert Certificate X509Certificate CertificateException CertificateFactory])
)
(defn load-keystore
"Loads a keystore"
[path password type]
(doto (KeyStore/getInstance type)
(.load (input-stream path) (char-array password))))
(defn ssl-context
"Creates a SSL context to use the SSL encryption. The function takes a :store-path argument for the (JKS) keystore
to lookup the certificate. You may also specify :store-pass and :cert-pass for the keystore and certificate password
or :trust-managers to provide an array of trust managers to use. "
[& {:keys [keystore store-path store-pass store-type key-pass trust-managers algorithm]
:or {algorithm (or (Security/getProperty "ssl.KeyManagerFactory.algorithm") "SunX509")}}]
(let [keystore (if keystore keystore (load-keystore store-path store-pass store-type))
kmf (doto (KeyManagerFactory/getInstance algorithm)
(.init keystore (char-array key-pass)))
tms (if trust-managers trust-managers (.getTrustManagers (doto
(TrustManagerFactory/getInstance algorithm)
(.init keystore)
)))
context (doto (SSLContext/getInstance "TLS")
(.init (.getKeyManagers kmf) tms nil))
]
context
)
)
(defn aliases [keystore]
(letfn [(get-aliases [enum] (lazy-seq
(when (.hasMoreElements enum)
(cons (.nextElement enum) (get-aliases enum)))))]
(get-aliases (.aliases keystore))))
(defn get-cert-chain [path type]
(let [factory (CertificateFactory/getInstance type)
certs (.generateCertificates factory (input-stream path))]
(into-array Certificate certs)))
(defn keystore [& {:keys [key-path key-pass key-type cert-path cert-type] :or {key-type "PKCS12" cert-type "X.509"}}]
(let [key-store (load-keystore key-path key-pass key-type)
key (.getKey key-store (first (aliases key-store)) (char-array key-pass))
certs (get-cert-chain cert-path cert-type)]
(doto
(KeyStore/getInstance "JKS")
(.load nil (char-array key-pass))
(.setKeyEntry "apple-push-service" key (char-array nil) certs))))
(defn ssl-engine [context & {:keys [use-client-mode] :or {use-client-mode true}}]
"Creates an SSL engine"
(let [engine (.createSSLEngine context)]
(if use-client-mode
(doto engine (.setUseClientMode use-client-mode))
engine)
)
)
(defn ssl-engine-factory [context & {:keys [use-client-mode] :or {use-client-mode true}}]
"Creates an SSL engine"
(fn [] (let [engine (.createSSLEngine context)]
(if use-client-mode
(doto engine (.setUseClientMode use-client-mode))
engine)
)))
(defn naive-trust-managers [& {:keys [trace] :or [trace false]}]
"Creates a very naive trust manager that will accept all certificates."
(into-array (list (proxy [javax.net.ssl.X509TrustManager] []
(getAcceptedIssuers [] (make-array X509Certificate 0))
(checkClientTrusted [chain auth-type]
(when trace (info "Unknown client certificate:" (.getSubjectDN (get chain 0))))
)
(checkServerTrusted [chain auth-type]
(when trace (info "Unknown server certificate:" (.getSubjectDN (get chain 0))))
)
)))
)