Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

- added ability to load certificate and key from Apple default delive…

…ry formats
  • Loading branch information...
commit 5e4be190e1ba699e0ea13de174b0d519fc3a9655 1 parent 30efe2d
@niclasmeier niclasmeier authored
2  project.clj
@@ -1,4 +1,4 @@
-(defproject herolabs/apns "0.1.8"
+(defproject herolabs/apns "0.1.9"
:description "A simple lightweight library to use with the Apple push notification service."
:url ""
:dependencies [[org.clojure/clojure "1.4.0"]
58 src/herolabs/apns/ssl.clj
@@ -1,33 +1,63 @@
(ns herolabs.apns.ssl
(:use []
- [ :only (input-stream)])
- (:import [ Security KeyStore]
+ [ :only (input-stream)]
+ [clojure.string :only (join)])
+ (:import [org.apache.commons.codec.digest DigestUtils]
+ [ Security KeyStore]
[ KeyManager KeyManagerFactory SSLContext SSLEngine TrustManager TrustManagerFactory X509TrustManager]
- [ X509Certificate CertificateException])
+ [ 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 [& {:keys [store-path store-pass cert-pass trust-managers]}]
+(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.
- "
- (let [algorithm (if-let [a (Security/getProperty "ssl.KeyManagerFactory.algorithm")] a "SunX509")
- keystore (doto (KeyStore/getInstance "JKS")
- (.load (input-stream store-path) (char-array store-pass)))
+ 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 cert-pass)))
- tmf (if trust-managers trust-managers (doto (TrustManagerFactory/getInstance algorithm)
- (.init keystore)
- (.getTrustManagers)))
+ (.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) trust-managers nil))
+ (.init (.getKeyManagers kmf) tms nil))
+(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)]
2  test/herolabs_test/apns/message.clj
@@ -1,4 +1,4 @@
-(ns herolabs-test.apns
+(ns herolabs-test.apns.message
(:use midje.sweet
Please sign in to comment.
Something went wrong with that request. Please try again.