diff options
author | David Barksdale <amatus.amongus@gmail.com> | 2010-10-15 21:19:02 -0700 |
---|---|---|
committer | David Barksdale <amatus.amongus@gmail.com> | 2010-10-15 21:19:02 -0700 |
commit | 1791fa62d12ad8407e9e9b9a0033ed47fe7a5c2d (patch) | |
tree | da61456690d5b58ef8dc020358614b409cbbf10a /src | |
parent | 581c86a89df3fe2167fb1001ec84ba2505e42d6f (diff) |
More work on SET_KEY handling. Changed remote-peer state management a bit.
Better RNG security.
Diffstat (limited to 'src')
-rw-r--r-- | src/org/gnu/clojure/gnunet/core.clj | 152 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/crypto.clj | 31 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/peer.clj | 6 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/transport.clj | 2 |
4 files changed, 156 insertions, 35 deletions
diff --git a/src/org/gnu/clojure/gnunet/core.clj b/src/org/gnu/clojure/gnunet/core.clj index 54fc3a8..cb06e09 100644 --- a/src/org/gnu/clojure/gnunet/core.clj +++ b/src/org/gnu/clojure/gnunet/core.clj @@ -10,6 +10,26 @@ (def signature-purpose-set-key 3) +(def peer-status-down 0) +(def peer-status-key-sent 1) +(def peer-status-key-received 2) +(def peer-status-key-confirmed 3) + +(defn encode-set-key-signed-material + [set-key] + (encode-signed signature-purpose-set-key + (concat + (encode-date (:creation-time set-key)) + (:encrypted-key set-key) + (:peer-id set-key)))) + +(defn encode-set-key + [set-key signed-material] + (concat + (encode-int32 (:sender-status set-key)) + signed-material + (:signature set-key))) + (def parse-set-key (domonad parser-m [sender-status parse-int32 @@ -30,33 +50,121 @@ :signature signature} (:parsed signed)))) +(defn encode-core-ping + [ping] + (concat + (encode-int32 (:iv-seed ping)) + (:peer-id ping) + (encode-int32 (:challenge ping)))) + +(def parse-core-ping + (domonad parser-m [iv-seed parse-uint32 + peer-id (items id-size) + challenge parse-int32] + {:iv-seed iv-seed + :peer-id peer-id + :challenge challenge})) + +(defn send-key! + [peer remote-peer] + (send (:state-agent remote-peer) + (fn [state] + (if-let [public-key (deref (:public-key-atom remote-peer))] + (if (state :is-connected false) + (let [state (if (= peer-status-down (:status state)) + (assoc state :status peer-status-key-sent) + state) + set-key {:sender-status (:status state) + :creation-time (:encrypt-key-created state) + :peer-id (:id remote-peer) + :encrypted-key (rsa-encrypt! (:public-key peer) + (:encrypt-key state) + (:random peer))} + signed-material (encode-set-key-signed-material set-key) + signature (rsa-sign (:private-key peer) signed-material) + set-key (assoc set-key :signature signature) + encoded-set-key (encode-set-key set-key signed-material) + iv-seed (.nextInt (:random peer)) + ping {:iv-seed iv-seed + :challenge (:ping-challenge state) + :peer-id (:id remote-peer)} + encoded-ping (encode-core-ping ping)] + state) + state) + state)))) + +(defn verify-set-key + [peer remote-peer state message] + (when-let [public-key (deref (:public-key-atom remote-peer))] + (when-let [set-key (first (parse-set-key (:bytes message)))] + (let [status (:status state) + decrypt-key-created (:decrypt-key-created state)] + (cond + (not (= (:peer-id set-key) (seq (:id peer)))) nil + (not (rsa-verify public-key + (:signed-material set-key) (:signature set-key))) nil + (and + (or (= status peer-status-key-received) + (= status peer-status-key-confirmed)) + (< (:creation-time set-key) decrypt-key-created)) nil + :else set-key))))) + (defn handle-set-key! [peer remote-peer message] - (send (:core-state-agent remote-peer) + (send (:state-agent remote-peer) (fn [state] - (if-let [public-key (deref (:public-key-atom remote-peer))] - (if-let [set-key (first (parse-set-key (:bytes message)))] - (let [status (state :status :status-down) - decrypt-key-created (state :decrypt-key-created (Date. 0))] - (cond - (not (= (:peer-id set-key) (seq (:id peer)))) state - (not (rsa-verify public-key - (:signed-material set-key) (:signature set-key))) state - (and - (or (= status :status-key-received) - (= status :status-key-confirmed)) - (< (:creation-time set-key) decrypt-key-created)) state - :else (let [decrypt-key (rsa-decrypt (:private-key peer) - (:encrypted-key set-key))] - state))) + (if-let [set-key (verify-set-key peer remote-peer state message)] + (if-let [decrypt-key (rsa-decrypt (:private-key peer) + (:encrypted-key set-key))] + (let [state (assoc state :decrypt-key decrypt-key) + decrypt-key-created (state :decrypt-key-created (Date. 0)) + creation-time (:creation-time set-key) + state (if (= decrypt-key-created creation-time) + state + (conj state {:last-sequence-number-received 0 + :last-packets-bitmap 0 + :decrypt-key-created creation-time})) + status (state :status peer-status-down) + sender-status (:sender-status set-key)] + (condp contains? status + #{peer-status-down} + (do (send-key! peer remote-peer) + (assoc state :status peer-status-key-received)) + #{peer-status-key-sent + peer-status-key-received} + (do (if (and (not (= sender-status peer-status-key-received)) + (not (= sender-status peer-status-key-confirmed))) + (send-key! peer remote-peer)) + (assoc state :status peer-status-key-received)) + #{peer-status-key-confirmed} + (do (if (and (not (= sender-status peer-status-key-received)) + (not (= sender-status peer-status-key-confirmed))) + (send-key! peer remote-peer)) + state) + state)) state) state)))) +(defn initialize-remote-peer-state + [peer state] + (conj state + {:status peer-status-down + :decrypt-key-created (Date. 0) + :encrypt-key (generate-aes-key! (:random peer)) + :encrypt-key-created (Date.) + :ping-challenge (.nextInt (:random peer))})) + (defn handle-receive! [peer remote-peer message] - (condp = (:message-type message) - message-type-core-set-key (handle-set-key! peer remote-peer message) - message-type-core-encrypted-message nil - message-type-core-ping nil - message-type-core-pong nil - nil)) + (send (:state-agent remote-peer) + (fn [state] + (let [state (if (contains? state :status) + state + (initialize-remote-peer-state peer state))] + (condp = (:message-type message) + message-type-core-set-key (handle-set-key! peer remote-peer message) + message-type-core-encrypted-message nil + message-type-core-ping nil + message-type-core-pong nil + nil) + state)))) diff --git a/src/org/gnu/clojure/gnunet/crypto.clj b/src/org/gnu/clojure/gnunet/crypto.clj index 5eaa661..ffcc936 100644 --- a/src/org/gnu/clojure/gnunet/crypto.clj +++ b/src/org/gnu/clojure/gnunet/crypto.clj @@ -5,9 +5,20 @@ (java.security.spec RSAKeyGenParameterSpec RSAPublicKeySpec RSAPrivateCrtKeySpec) java.math.BigInteger - javax.crypto.Cipher)) + (javax.crypto Cipher SecretKeyFactory) + javax.crypto.spec.SecretKeySpec)) (def signature-size 256) +(def aes-key-size 32) +(def aes-iv-size (/ aes-key-size 2)) + +(defn generate-aes-key! + [random] + (let [buffer (byte-array (repeat aes-key-size (byte 0))) + _ (.nextBytes random buffer) + key-spec (SecretKeySpec. buffer "AES") + key-factory (SecretKeyFactory/getInstance "AES")] + (.generateSecret key-factory key-spec))) (defn encode-signed [purpose inner-material] @@ -36,12 +47,12 @@ :signed-material (take size input) :parsed parsed} residue]))))) -(defn generate-rsa-keypair +(defn generate-rsa-keypair! "Generate a 2048 bit RSA keypair." - [] + [random] (let [rsa (KeyPairGenerator/getInstance "RSA") spec (RSAKeyGenParameterSpec. 2048 (bigint 257))] - (.initialize rsa spec) + (.initialize rsa spec random) (.generateKeyPair rsa))) (defn make-rsa-public-key @@ -73,16 +84,18 @@ (byte-array signature))) (defn rsa-encrypt! - [rsa-key byte-seq] + [rsa-key byte-seq random] (.doFinal (doto (Cipher/getInstance "RSA") - (.init Cipher/ENCRYPT_MODE rsa-key)) + (.init Cipher/ENCRYPT_MODE rsa-key random)) (byte-array byte-seq))) (defn rsa-decrypt [rsa-key byte-seq] - (.doFinal (doto (Cipher/getInstance "RSA") - (.init Cipher/DECRYPT_MODE rsa-key)) - (byte-array byte-seq))) + (try + (.doFinal (doto (Cipher/getInstance "RSA") + (.init Cipher/DECRYPT_MODE rsa-key)) + (byte-array byte-seq)) + (catch Exception e nil))) (defn sha-512 "Compute the SHA-512 digest of a sequence of bytes." diff --git a/src/org/gnu/clojure/gnunet/peer.clj b/src/org/gnu/clojure/gnunet/peer.clj index 5a71c3c..73b6169 100644 --- a/src/org/gnu/clojure/gnunet/peer.clj +++ b/src/org/gnu/clojure/gnunet/peer.clj @@ -16,8 +16,8 @@ ;; (java.util.Date) :latency (int, if validated)} :transport-addresses-agent - ;; agent of a map of state used by core (nil for local peer?) - :core-state-agent) + ;; agent of a map of state (nil for local peer?) + :state-agent) (def peer-struct (apply create-struct (concat (keys (struct-map remote-peer-struct)) @@ -79,4 +79,4 @@ :selector selector :selector-thread (Thread. (partial selector-loop! selector continuations)) :selector-continuations-queue continuations - :random (SecureRandom.)))) + :random (:random options)))) diff --git a/src/org/gnu/clojure/gnunet/transport.clj b/src/org/gnu/clojure/gnunet/transport.clj index b91eba5..574aac6 100644 --- a/src/org/gnu/clojure/gnunet/transport.clj +++ b/src/org/gnu/clojure/gnunet/transport.clj @@ -169,7 +169,7 @@ :transport-addresses-agent (agent (merge-transport-addresses {} (:transport-addresses hello))) - :core-state-agent (agent {})))))) + :state-agent (agent {})))))) (defn verify-transport-address [peer remote-peer address] |