summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Barksdale <amatus.amongus@gmail.com>2010-10-15 21:19:02 -0700
committerDavid Barksdale <amatus.amongus@gmail.com>2010-10-15 21:19:02 -0700
commit1791fa62d12ad8407e9e9b9a0033ed47fe7a5c2d (patch)
treeda61456690d5b58ef8dc020358614b409cbbf10a /src
parent581c86a89df3fe2167fb1001ec84ba2505e42d6f (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.clj152
-rw-r--r--src/org/gnu/clojure/gnunet/crypto.clj31
-rw-r--r--src/org/gnu/clojure/gnunet/peer.clj6
-rw-r--r--src/org/gnu/clojure/gnunet/transport.clj2
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]