diff options
author | David Barksdale <amatus.amongus@gmail.com> | 2010-10-14 21:48:16 -0700 |
---|---|---|
committer | David Barksdale <amatus.amongus@gmail.com> | 2010-10-14 21:48:16 -0700 |
commit | 92b74572b949203592b942b1bd88447e18d1d013 (patch) | |
tree | 8fe7e5ac974b09a06cb7faf2721ec2c00f859276 /src | |
parent | 1e2bae61cda7b2556c5185dcd22e9991ef4a8222 (diff) |
Added core-state-agent, RSA encrypt-decrypt (untested).
Fixed encode-rsa-public-key, optimized parse-rsa-public-key.
Using clojure.test for tests, added generate-kblock-key test.
Diffstat (limited to 'src')
-rw-r--r-- | src/org/gnu/clojure/gnunet/core.clj | 34 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/crypto.clj | 99 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/message.clj | 2 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/parser.clj | 2 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/peer.clj | 7 | ||||
-rw-r--r-- | src/org/gnu/clojure/gnunet/transport.clj | 3 |
6 files changed, 98 insertions, 49 deletions
diff --git a/src/org/gnu/clojure/gnunet/core.clj b/src/org/gnu/clojure/gnunet/core.clj index 9c6c0df..54fc3a8 100644 --- a/src/org/gnu/clojure/gnunet/core.clj +++ b/src/org/gnu/clojure/gnunet/core.clj @@ -1,6 +1,7 @@ (ns org.gnu.clojure.gnunet.core (:use (org.gnu.clojure.gnunet parser message peer crypto) - clojure.contrib.monads)) + clojure.contrib.monads) + (:import java.util.Date)) (def message-type-core-set-key 80) (def message-type-core-encrypted-message 81) @@ -29,20 +30,27 @@ :signature signature} (:parsed signed)))) - (defn handle-set-key! [peer remote-peer message] - (when-let [public-key (deref (:public-key-atom remote-peer))] - (when-let [set-key (first (parse-set-key (:bytes message)))] - (cond - (not (= (:peer-id set-key) (seq (:id peer)))) (.write *out* "SET_KEY not for me\n") - (not (rsa-verify public-key - (:signed-material set-key) - (:signature set-key))) (.write *out* "SET_KEY invalid signature\n") - :else (do (.write *out* "Set key message ") - (.write *out* (.toString set-key)) - (.write *out* "\n")) - )))) + (send (:core-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))) + state) + state)))) (defn handle-receive! [peer remote-peer message] diff --git a/src/org/gnu/clojure/gnunet/crypto.clj b/src/org/gnu/clojure/gnunet/crypto.clj index cc57251..fcb48b5 100644 --- a/src/org/gnu/clojure/gnunet/crypto.clj +++ b/src/org/gnu/clojure/gnunet/crypto.clj @@ -1,10 +1,11 @@ (ns org.gnu.clojure.gnunet.crypto (:use (org.gnu.clojure.gnunet parser message) - clojure.contrib.monads) + clojure.contrib.monads clojure.test) (:import (java.security KeyPairGenerator KeyFactory MessageDigest Signature) (java.security.spec RSAKeyGenParameterSpec RSAPublicKeySpec RSAPrivateCrtKeySpec) - (java.math.BigInteger))) + java.math.BigInteger + javax.crypto.Cipher)) (def signature-size 256) @@ -58,23 +59,38 @@ (.generatePrivate keyfactory keyspec))) (defn rsa-sign - [private-key bytes] + [private-key byte-seq] (.sign (doto (Signature/getInstance "SHA512withRSA") (.initSign private-key) - (.update (byte-array bytes))))) + (.update (byte-array byte-seq))))) (defn rsa-verify - [public-key bytes signature] + [public-key byte-seq signature] (.verify (doto (Signature/getInstance "SHA512withRSA") (.initVerify public-key) - (.update (byte-array bytes))) - (byte-array signature))) + (.update (byte-array byte-seq))) + (byte-array signature))) + +(defn rsa-encrypt! + [rsa-key byte-seq] + (.doFinal (doto (Cipher/getInstance "RSA") + (.init Cipher/ENCRYPT_MODE rsa-key)) + (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))) (defn sha-512 "Compute the SHA-512 digest of a sequence of bytes." - [x] - (let [sha (MessageDigest/getInstance "SHA-512")] - (.digest sha (byte-array x)))) + [byte-seq] + (.digest (MessageDigest/getInstance "SHA-512") (byte-array byte-seq))) + +(def rsa-modulus-length 256) +(def rsa-exponent-length 2) +(def rsa-key-length (+ rsa-modulus-length rsa-exponent-length)) (defn encode-rsa-public-key "Convert an RSA public key to a sequence of bytes in gnunet format." @@ -84,9 +100,11 @@ exponent (encode-int (.getPublicExponent public-key)) exponent-len (count exponent)] (concat - (encode-int16 (+ modulus-len exponent-len 4)) - (encode-int16 modulus-len) + (encode-int16 (+ rsa-key-length 4)) + (encode-int16 rsa-modulus-length) + (repeat (- rsa-modulus-length modulus-len) (byte 0)) modulus + (repeat (- rsa-exponent-length exponent-len) (byte 0)) exponent (encode-int16 0)))) @@ -95,20 +113,15 @@ sizen parse-uint16 n (parse-uint sizen) e (parse-uint (- len sizen 4)) - :when (try - (do (make-rsa-public-key n e) true) - (catch Exception e false)) + :let [public-key (try (make-rsa-public-key n e) + (catch Exception e nil))] + :when public-key padding parse-uint16 :when (== 0 padding)] - (make-rsa-public-key n e))) + public-key)) -(defn - #^{:test (fn [] - (let [seed (sha-512 []) - [n seed] (random-int 1024 seed)] - (assert (== n 145722097586741401146081933101625908822609966371134029821236387730376760429245348048227251733217120026252986740857779434920617271166036248533631595465678498079543252354969108228859509711652038086980961685030673985343697554674529134136563684623116336979340330220033374478392520298004708077375018922611329202505)) - (assert (= (seq seed) [-83 -57 -58 -86 82 42 91 -29 -56 -97 -36 -125 47 5 -57 120 48 -112 51 -103 26 113 29 126 -80 46 88 13 -23 -59 -15 49 -34 50 54 -99 -61 -106 -2 37 18 -103 -85 -98 -58 -4 33 -13 118 -112 125 -121 -43 43 19 11 -113 -116 59 14 37 66 56 2]))))} - random-int +(with-test +(defn random-int "Return a cryptographically weak random non-negative integer of the given bit-length." [bit-length seed] @@ -119,7 +132,14 @@ len (.bitLength number) number (reduce bit-clear number (range (dec len) (dec bit-length) -1))] [number (nth hashes cnt)])) - +(is (= (let [[n seed] (random-int 1024 (sha-512 []))] + [n (vec seed)]) + [145722097586741401146081933101625908822609966371134029821236387730376760429245348048227251733217120026252986740857779434920617271166036248533631595465678498079543252354969108228859509711652038086980961685030673985343697554674529134136563684623116336979340330220033374478392520298004708077375018922611329202505 + [-83 -57 -58 -86 82 42 91 -29 -56 -97 -36 -125 47 5 -57 120 48 -112 51 + -103 26 113 29 126 -80 46 88 13 -23 -59 -15 49 -34 50 54 -99 -61 -106 + -2 37 18 -103 -85 -98 -58 -4 33 -13 118 -112 125 -121 -43 43 19 11 -113 + -116 59 14 37 66 56 2]]))) + (defn fermat-compositeness-test "Perform Fermat's Compositeness Test on the given bigint." [number] @@ -154,13 +174,8 @@ (def small-primes) -(defn - #^{:test (fn [] - (let [seed (sha-512 []) - [n seed] (generate-prime 1024 seed)] - (assert (== n 145722097586741401146081933101625908822609966371134029821236387730376760429245348048227251733217120026252986740857779434920617271166036248533631595465678498079543252354969108228859509711652038086980961685030673985343697554674529134136563684623116336979340330220033374478392520298004708077375018922611329203201)) - (assert (= (seq seed) [-110 35 7 6 -114 -46 -94 -76 41 94 76 110 -116 9 -39 30 71 48 -55 -9 -95 -9 -117 -6 -31 -47 117 125 71 73 25 95 -100 50 123 -64 86 31 101 53 -89 33 -38 70 -77 15 -85 44 18 -5 -29 -4 -120 0 114 -79 81 -127 -102 102 126 -14 5 60]))))} - generate-prime +(with-test +(defn generate-prime "Generates a cryptographically weak random prime of the given bit-length." [bit-length seed] {:pre [(>= bit-length 32)]} @@ -189,7 +204,15 @@ [prime seed])))) (recur (inc step) seed))))] (if prime [prime seed] (recur seed))))) +(is (= (let [[prime seed] (generate-prime 1024 (sha-512 []))] + [prime (vec seed)]) + [145722097586741401146081933101625908822609966371134029821236387730376760429245348048227251733217120026252986740857779434920617271166036248533631595465678498079543252354969108228859509711652038086980961685030673985343697554674529134136563684623116336979340330220033374478392520298004708077375018922611329203201 + [-110 35 7 6 -114 -46 -94 -76 41 94 76 110 -116 9 -39 30 71 48 -55 -9 -95 + -9 -117 -6 -31 -47 117 125 71 73 25 95 -100 50 123 -64 86 31 101 53 -89 + 33 -38 70 -77 15 -85 44 18 -5 -29 -4 -120 0 114 -79 81 -127 -102 102 126 + -14 5 60]]))) +(with-test (defn generate-kblock-key "Generates an RSA private key of a given bit-length." [bit-length seed] @@ -227,6 +250,20 @@ (.mod d t2))) (catch Exception e nil))] (if private-key private-key (recur seed)))))) +(is (= + (encode-rsa-public-key + (generate-kblock-key 1024 (sha-512 (.getBytes "X" "utf-8")))) + [1 6 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -73 60 33 95 122 94 107 9 -66 + -59 87 19 -55 1 120 108 9 50 74 21 9 -128 -32 20 -67 -80 -48 68 38 -109 + 73 41 -61 -76 -105 26 -105 17 -81 84 85 83 108 -42 -18 -72 -65 -96 4 -18 + -112 73 114 -89 55 69 95 83 -57 82 -104 125 -116 -126 -73 85 -68 2 -120 + 43 68 -107 12 74 -51 -63 103 43 -89 76 59 -108 -40 26 76 30 -93 -41 78 + 119 0 -82 85 -108 -61 -92 -13 -59 89 -28 -65 -14 -33 104 68 -6 -61 2 -28 + -74 97 117 -31 77 -56 -70 -45 -50 68 40 29 47 -20 26 26 -66 -16 99 1 1 0 + 0]))) (def small-primes [ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, diff --git a/src/org/gnu/clojure/gnunet/message.clj b/src/org/gnu/clojure/gnunet/message.clj index 7a7bf3f..771972c 100644 --- a/src/org/gnu/clojure/gnunet/message.clj +++ b/src/org/gnu/clojure/gnunet/message.clj @@ -64,7 +64,7 @@ (list (byte 0)))) (def parse-utf8 - (domonad parser-m [xs (none-or-more (is #(not (== 0 %)))) + (domonad parser-m [xs (none-or-more (satisfy #(not (== 0 %)))) zero item] (String. (byte-array xs) "UTF-8"))) diff --git a/src/org/gnu/clojure/gnunet/parser.clj b/src/org/gnu/clojure/gnunet/parser.clj index d131af9..b4899fa 100644 --- a/src/org/gnu/clojure/gnunet/parser.clj +++ b/src/org/gnu/clojure/gnunet/parser.clj @@ -19,7 +19,7 @@ [xs] (when (not (empty? xs)) [(first xs) (rest xs)])) -(defn is +(defn satisfy "Produces a parser that matches an item which satisfies the given predicate." [p] (domonad parser-m [x item diff --git a/src/org/gnu/clojure/gnunet/peer.clj b/src/org/gnu/clojure/gnunet/peer.clj index 7845320..5a71c3c 100644 --- a/src/org/gnu/clojure/gnunet/peer.clj +++ b/src/org/gnu/clojure/gnunet/peer.clj @@ -8,13 +8,16 @@ ;; atom of java.security.PublicKey :public-key-atom - ;; 64 byte (512-bit) sequence + ;; 64 byte (512-bit) vector :id ;; agent of a map associating transport names (String) to maps associating ;; transport addresses (byte vector) to maps containing {:expiration ;; (java.util.Date) :latency (int, if validated)} - :transport-addresses-agent) + :transport-addresses-agent + + ;; agent of a map of state used by core (nil for local peer?) + :core-state-agent) (def peer-struct (apply create-struct (concat (keys (struct-map remote-peer-struct)) diff --git a/src/org/gnu/clojure/gnunet/transport.clj b/src/org/gnu/clojure/gnunet/transport.clj index 2a83bdc..b91eba5 100644 --- a/src/org/gnu/clojure/gnunet/transport.clj +++ b/src/org/gnu/clojure/gnunet/transport.clj @@ -168,7 +168,8 @@ :id peer-id :transport-addresses-agent (agent (merge-transport-addresses {} - (:transport-addresses hello)))))))) + (:transport-addresses hello))) + :core-state-agent (agent {})))))) (defn verify-transport-address [peer remote-peer address] |