mirror of
https://github.com/unclebob/more-speech.git
synced 2024-09-30 10:30:56 +00:00
Check signatures of incoming events. Move hex/num/bytes utilities from ecc to util.
This commit is contained in:
parent
c94bafd84a
commit
bdd2f32b37
@ -1,65 +1,10 @@
|
|||||||
(ns more-speech.nostr.ellliptic-signature-spec
|
(ns more-speech.nostr.elliptic-signature-spec
|
||||||
(:require [speclj.core :refer :all]
|
(:require [speclj.core :refer :all]
|
||||||
[more-speech.nostr.elliptic-signature :refer :all])
|
[more-speech.nostr.elliptic-signature :refer :all]
|
||||||
|
[more-speech.nostr.util :refer :all])
|
||||||
)
|
)
|
||||||
|
|
||||||
(describe "verification"
|
(describe "verification"
|
||||||
(it "decodes chars"
|
|
||||||
(should= 16rab (Integer/parseInt "ab" 16)))
|
|
||||||
|
|
||||||
(it "does hex-decode"
|
|
||||||
(should= "deadbeef" (bytes->hex-string (hex-string->bytes "deadbeef")))
|
|
||||||
(should= "aff9a9f017f32b2e8b60754a4102db9d9cf9ff2b967804b50e070780aa45c9a8"
|
|
||||||
(bytes->hex-string (hex-string->bytes "aff9a9f017f32b2e8b60754a4102db9d9cf9ff2b967804b50e070780aa45c9a8")))
|
|
||||||
)
|
|
||||||
|
|
||||||
(it "converts byte arrays to strings"
|
|
||||||
(should= "abcdef" (bytes->hex-string (hex-string->bytes "abcdef"))))
|
|
||||||
|
|
||||||
(it "xors bytes"
|
|
||||||
(should= "b2ce" (bytes->hex-string (xor-bytes (hex-string->bytes "af01")
|
|
||||||
(hex-string->bytes "1dcf"))))
|
|
||||||
(should= "000000000000"
|
|
||||||
(bytes->hex-string
|
|
||||||
(xor-bytes (hex-string->bytes "deadbeeffeed")
|
|
||||||
(hex-string->bytes "deadbeeffeed"))))
|
|
||||||
(should= "ffffffffffff"
|
|
||||||
(bytes->hex-string
|
|
||||||
(xor-bytes (hex-string->bytes "aaaacccc3333")
|
|
||||||
(hex-string->bytes "55553333cccc"))))
|
|
||||||
)
|
|
||||||
|
|
||||||
(it "should convert numbers to bytes"
|
|
||||||
(should= "1fcde563"
|
|
||||||
(bytes->hex-string
|
|
||||||
(num->bytes 4
|
|
||||||
(bytes->num
|
|
||||||
(hex-string->bytes "1fcde563")))))
|
|
||||||
|
|
||||||
(should= "ffcde563"
|
|
||||||
(bytes->hex-string
|
|
||||||
(num->bytes 4
|
|
||||||
(bytes->num
|
|
||||||
(hex-string->bytes "ffcde563")))))
|
|
||||||
)
|
|
||||||
|
|
||||||
;(it "signs"
|
|
||||||
; (let [private-key-1 (sha-256 (.getBytes "my private key 1" StandardCharsets/UTF_8))
|
|
||||||
; private-key-2 (sha-256 (.getBytes "my private key 2" StandardCharsets/UTF_8))
|
|
||||||
; public-key-1 (pub-key private-key-1)
|
|
||||||
; public-key-2 (pub-key private-key-2)
|
|
||||||
; message-1 (sha-256 (.getBytes "my message 1" StandardCharsets/UTF_8))
|
|
||||||
; message-2 (sha-256 (.getBytes "my message 2" StandardCharsets/UTF_8))
|
|
||||||
; sig-1 (sign private-key-1 message-1)
|
|
||||||
; sig-2 (sign private-key-2 message-2)
|
|
||||||
; ]
|
|
||||||
; (should= true (verify public-key-1 message-1 sig-1))
|
|
||||||
; (should= true (verify public-key-2 message-2 sig-2))
|
|
||||||
; (should-not (verify public-key-1 message-1 sig-2))
|
|
||||||
; (should-not (verify public-key-2 message-2 sig-1))
|
|
||||||
; (should-not (verify public-key-1 message-2 sig-1))
|
|
||||||
; (should-not (verify public-key-2 message-1 sig-2))))
|
|
||||||
|
|
||||||
(it "verifies Aaron Dixon's example."
|
(it "verifies Aaron Dixon's example."
|
||||||
(should= true
|
(should= true
|
||||||
(do-verify
|
(do-verify
|
@ -1,7 +1,8 @@
|
|||||||
(ns more-speech.nostr.events_spec
|
(ns more-speech.nostr.events_spec
|
||||||
(:require [speclj.core :refer :all]
|
(:require [speclj.core :refer :all]
|
||||||
[more-speech.nostr.events :refer :all]
|
[more-speech.nostr.events :refer :all]
|
||||||
[more-speech.nostr.elliptic-signature :as ecc]))
|
[more-speech.nostr.elliptic-signature :refer :all]
|
||||||
|
[more-speech.nostr.util :refer :all]))
|
||||||
|
|
||||||
(defrecord event-handler-dummy []
|
(defrecord event-handler-dummy []
|
||||||
event-handler
|
event-handler
|
||||||
@ -89,83 +90,83 @@
|
|||||||
|
|
||||||
(describe "Composing outgoing events"
|
(describe "Composing outgoing events"
|
||||||
(it "composes an original message."
|
(it "composes an original message."
|
||||||
(let [private-key (ecc/num->bytes 64 314159)
|
(let [private-key (num->bytes 64 314159)
|
||||||
event-state {:keys {:private-key (ecc/bytes->hex-string private-key)}}
|
event-state {:keys {:private-key (bytes->hex-string private-key)}}
|
||||||
public-key (ecc/get-pub-key private-key)
|
public-key (get-pub-key private-key)
|
||||||
text "message text"
|
text "message text"
|
||||||
event (compose-text-event event-state text)
|
event (compose-text-event event-state text)
|
||||||
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
||||||
now (quot (System/currentTimeMillis) 1000)]
|
now (quot (System/currentTimeMillis) 1000)]
|
||||||
(should= "EVENT" (first event))
|
(should= "EVENT" (first event))
|
||||||
(should= (ecc/bytes->hex-string public-key) pubkey)
|
(should= (bytes->hex-string public-key) pubkey)
|
||||||
(should (<= 0 (- now created_at) 1)) ;within one second.
|
(should (<= 0 (- now created_at) 1)) ;within one second.
|
||||||
(should= 1 kind)
|
(should= 1 kind)
|
||||||
(should= [] tags)
|
(should= [] tags)
|
||||||
(should= text content)
|
(should= text content)
|
||||||
(should (ecc/do-verify (ecc/hex-string->bytes id)
|
(should (do-verify (hex-string->bytes id)
|
||||||
public-key
|
public-key
|
||||||
(ecc/hex-string->bytes sig)))))
|
(hex-string->bytes sig)))))
|
||||||
|
|
||||||
(it "composes a reply to a root article."
|
(it "composes a reply to a root article."
|
||||||
(let [private-key (ecc/num->bytes 64 42)
|
(let [private-key (num->bytes 64 42)
|
||||||
root-id 7734
|
root-id 7734
|
||||||
root-id-hex (hexify root-id)
|
root-id-hex (hexify root-id)
|
||||||
root-author 99
|
root-author 99
|
||||||
event-state {:keys {:private-key (ecc/bytes->hex-string private-key)}
|
event-state {:keys {:private-key (bytes->hex-string private-key)}
|
||||||
:text-event-map {root-id {:pubkey root-author
|
:text-event-map {root-id {:pubkey root-author
|
||||||
:tags []}}}
|
:tags []}}}
|
||||||
public-key (ecc/get-pub-key private-key)
|
public-key (get-pub-key private-key)
|
||||||
text "message text"
|
text "message text"
|
||||||
event (compose-text-event event-state text root-id)
|
event (compose-text-event event-state text root-id)
|
||||||
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
||||||
now (quot (System/currentTimeMillis) 1000)]
|
now (quot (System/currentTimeMillis) 1000)]
|
||||||
(should= "EVENT" (first event))
|
(should= "EVENT" (first event))
|
||||||
(should= (ecc/bytes->hex-string public-key) pubkey)
|
(should= (bytes->hex-string public-key) pubkey)
|
||||||
(should (<= 0 (- now created_at) 1)) ;within one second.
|
(should (<= 0 (- now created_at) 1)) ;within one second.
|
||||||
(should= 1 kind)
|
(should= 1 kind)
|
||||||
(should= [[:e root-id-hex] [:p (hexify root-author)]] tags)
|
(should= [[:e root-id-hex] [:p (hexify root-author)]] tags)
|
||||||
(should= text content)
|
(should= text content)
|
||||||
(should (ecc/do-verify (ecc/hex-string->bytes id)
|
(should (do-verify (hex-string->bytes id)
|
||||||
public-key
|
public-key
|
||||||
(ecc/hex-string->bytes sig)))))
|
(hex-string->bytes sig)))))
|
||||||
|
|
||||||
(it "composes a reply to a non-root article."
|
(it "composes a reply to a non-root article."
|
||||||
(let [private-key (ecc/num->bytes 64 42)
|
(let [private-key (num->bytes 64 42)
|
||||||
root-child-id 7734
|
root-child-id 7734
|
||||||
root-child-id-hex (hexify root-child-id)
|
root-child-id-hex (hexify root-child-id)
|
||||||
root-child-author 88
|
root-child-author 88
|
||||||
root-id 1952
|
root-id 1952
|
||||||
root-id-hex (hexify root-id)
|
root-id-hex (hexify root-id)
|
||||||
root-author 99
|
root-author 99
|
||||||
event-state {:keys {:private-key (ecc/bytes->hex-string private-key)}
|
event-state {:keys {:private-key (bytes->hex-string private-key)}
|
||||||
:text-event-map {root-child-id {:pubkey root-child-author
|
:text-event-map {root-child-id {:pubkey root-child-author
|
||||||
:tags [[:e root-id-hex]
|
:tags [[:e root-id-hex]
|
||||||
[:p (hexify root-author)]]}
|
[:p (hexify root-author)]]}
|
||||||
root-id {:pubkey root-author
|
root-id {:pubkey root-author
|
||||||
:tags []}}}
|
:tags []}}}
|
||||||
public-key (ecc/get-pub-key private-key)
|
public-key (get-pub-key private-key)
|
||||||
text "message text"
|
text "message text"
|
||||||
event (compose-text-event event-state text root-child-id)
|
event (compose-text-event event-state text root-child-id)
|
||||||
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
||||||
now (quot (System/currentTimeMillis) 1000)]
|
now (quot (System/currentTimeMillis) 1000)]
|
||||||
(should= "EVENT" (first event))
|
(should= "EVENT" (first event))
|
||||||
(should= (ecc/bytes->hex-string public-key) pubkey)
|
(should= (bytes->hex-string public-key) pubkey)
|
||||||
(should (<= 0 (- now created_at) 1)) ;within one second.
|
(should (<= 0 (- now created_at) 1)) ;within one second.
|
||||||
(should= 1 kind)
|
(should= 1 kind)
|
||||||
(should= [[:e root-id-hex] [:e root-child-id-hex]
|
(should= [[:e root-id-hex] [:e root-child-id-hex]
|
||||||
[:p (hexify root-child-author)] [:p (hexify root-author)]] tags)
|
[:p (hexify root-child-author)] [:p (hexify root-author)]] tags)
|
||||||
(should= text content)
|
(should= text content)
|
||||||
(should (ecc/do-verify (ecc/hex-string->bytes id)
|
(should (do-verify (hex-string->bytes id)
|
||||||
public-key
|
public-key
|
||||||
(ecc/hex-string->bytes sig)))))
|
(hex-string->bytes sig)))))
|
||||||
|
|
||||||
(it "author is removed from replies"
|
(it "author is removed from replies"
|
||||||
(let [private-key (ecc/num->bytes 64 42)
|
(let [private-key (num->bytes 64 42)
|
||||||
author (ecc/bytes->num (ecc/get-pub-key private-key))
|
author (bytes->num (get-pub-key private-key))
|
||||||
root-id 7734
|
root-id 7734
|
||||||
root-id-hex (hexify root-id)
|
root-id-hex (hexify root-id)
|
||||||
root-author 99
|
root-author 99
|
||||||
event-state {:keys {:private-key (ecc/bytes->hex-string private-key)}
|
event-state {:keys {:private-key (bytes->hex-string private-key)}
|
||||||
:text-event-map {root-id {:pubkey root-author
|
:text-event-map {root-id {:pubkey root-author
|
||||||
:tags [[:p (hexify author)]]}}}
|
:tags [[:p (hexify author)]]}}}
|
||||||
event (compose-text-event event-state "" root-id)
|
event (compose-text-event event-state "" root-id)
|
||||||
@ -174,22 +175,22 @@
|
|||||||
(should= [[:e root-id-hex] [:p (hexify root-author)]] tags)))
|
(should= [[:e root-id-hex] [:p (hexify root-author)]] tags)))
|
||||||
|
|
||||||
(it "composes a message with a slash."
|
(it "composes a message with a slash."
|
||||||
(let [private-key (ecc/num->bytes 64 42)
|
(let [private-key (num->bytes 64 42)
|
||||||
event-state {:keys {:private-key (ecc/bytes->hex-string private-key)}}
|
event-state {:keys {:private-key (bytes->hex-string private-key)}}
|
||||||
public-key (ecc/get-pub-key private-key)
|
public-key (get-pub-key private-key)
|
||||||
text "message/text"
|
text "message/text"
|
||||||
event (compose-text-event event-state text)
|
event (compose-text-event event-state text)
|
||||||
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
||||||
now (quot (System/currentTimeMillis) 1000)]
|
now (quot (System/currentTimeMillis) 1000)]
|
||||||
(should= "EVENT" (first event))
|
(should= "EVENT" (first event))
|
||||||
(should= (ecc/bytes->hex-string public-key) pubkey)
|
(should= (bytes->hex-string public-key) pubkey)
|
||||||
(should (<= 0 (- now created_at) 1)) ;within one second.
|
(should (<= 0 (- now created_at) 1)) ;within one second.
|
||||||
(should= 1 kind)
|
(should= 1 kind)
|
||||||
(should= [] tags)
|
(should= [] tags)
|
||||||
(should= text content)
|
(should= text content)
|
||||||
(should (ecc/do-verify (ecc/hex-string->bytes id)
|
(should (do-verify (hex-string->bytes id)
|
||||||
public-key
|
public-key
|
||||||
(ecc/hex-string->bytes sig)))))
|
(hex-string->bytes sig)))))
|
||||||
)
|
)
|
||||||
|
|
||||||
(describe "get references"
|
(describe "get references"
|
||||||
|
@ -3,26 +3,42 @@
|
|||||||
[more-speech.nostr.util :refer :all]))
|
[more-speech.nostr.util :refer :all]))
|
||||||
|
|
||||||
(describe "Hex string and bytes conversions"
|
(describe "Hex string and bytes conversions"
|
||||||
(it "does hex-decode"
|
(it "decodes chars"
|
||||||
(should= "deadbeef" (bytes->hex-string (hex-string->bytes "deadbeef")))
|
(should= 16rab (Integer/parseInt "ab" 16)))
|
||||||
(should= "aff9a9f017f32b2e8b60754a4102db9d9cf9ff2b967804b50e070780aa45c9a8"
|
|
||||||
(bytes->hex-string (hex-string->bytes "aff9a9f017f32b2e8b60754a4102db9d9cf9ff2b967804b50e070780aa45c9a8")))
|
|
||||||
)
|
|
||||||
|
|
||||||
(it "converts byte arrays to strings"
|
(it "does hex-decode"
|
||||||
(should= "abcdef" (bytes->hex-string (hex-string->bytes "abcdef"))))
|
(should= "deadbeef" (bytes->hex-string (hex-string->bytes "deadbeef")))
|
||||||
|
(should= "aff9a9f017f32b2e8b60754a4102db9d9cf9ff2b967804b50e070780aa45c9a8"
|
||||||
|
(bytes->hex-string (hex-string->bytes "aff9a9f017f32b2e8b60754a4102db9d9cf9ff2b967804b50e070780aa45c9a8")))
|
||||||
|
)
|
||||||
|
|
||||||
(it "should convert numbers to bytes"
|
(it "converts byte arrays to strings"
|
||||||
(should= "1fcde563"
|
(should= "abcdef" (bytes->hex-string (hex-string->bytes "abcdef"))))
|
||||||
(bytes->hex-string
|
|
||||||
(num->bytes 4
|
|
||||||
(bytes->num
|
|
||||||
(hex-string->bytes "1fcde563")))))
|
|
||||||
|
|
||||||
(should= "ffcde563"
|
(it "xors bytes"
|
||||||
(bytes->hex-string
|
(should= "b2ce" (bytes->hex-string (xor-bytes (hex-string->bytes "af01")
|
||||||
(num->bytes 4
|
(hex-string->bytes "1dcf"))))
|
||||||
(bytes->num
|
(should= "000000000000"
|
||||||
(hex-string->bytes "ffcde563")))))
|
(bytes->hex-string
|
||||||
)
|
(xor-bytes (hex-string->bytes "deadbeeffeed")
|
||||||
|
(hex-string->bytes "deadbeeffeed"))))
|
||||||
|
(should= "ffffffffffff"
|
||||||
|
(bytes->hex-string
|
||||||
|
(xor-bytes (hex-string->bytes "aaaacccc3333")
|
||||||
|
(hex-string->bytes "55553333cccc"))))
|
||||||
|
)
|
||||||
|
|
||||||
|
(it "should convert numbers to bytes"
|
||||||
|
(should= "1fcde563"
|
||||||
|
(bytes->hex-string
|
||||||
|
(num->bytes 4
|
||||||
|
(bytes->num
|
||||||
|
(hex-string->bytes "1fcde563")))))
|
||||||
|
|
||||||
|
(should= "ffcde563"
|
||||||
|
(bytes->hex-string
|
||||||
|
(num->bytes 4
|
||||||
|
(bytes->num
|
||||||
|
(hex-string->bytes "ffcde563")))))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
;;Stories
|
;;Stories
|
||||||
;; - validate incoming messages.
|
|
||||||
;; - Add author/date, etc. to replies.
|
;; - Add author/date, etc. to replies.
|
||||||
;; - Start checking sdefs in update.
|
;; - Start checking sdefs in update.
|
||||||
;; - Clean up java schnorr library.
|
;; - Clean up java schnorr library.
|
||||||
;; - Threading does not work quite right. Do some diagnosis.
|
;; - Threading needs some rethinking.
|
||||||
;; - Mark read and highlight properly.
|
;; - Mark read and highlight properly.
|
||||||
;; - Save names and headers. Request after latest save.
|
;; - Save names and headers. Request after latest save.
|
||||||
;; - Consider subject/topic in the tags
|
;; - Consider subject/topic in the tags
|
||||||
|
@ -1,71 +1,5 @@
|
|||||||
(ns more-speech.nostr.elliptic-signature
|
(ns more-speech.nostr.elliptic-signature
|
||||||
(:import (java.security MessageDigest)
|
(:import (schnorr Schnorr)))
|
||||||
(schnorr Schnorr)))
|
|
||||||
|
|
||||||
(defn sha-256
|
|
||||||
"Returns the sha256 hash of the message.
|
|
||||||
Both the message and the hash are byte-arrays."
|
|
||||||
^bytes [^bytes message]
|
|
||||||
(let [digest (MessageDigest/getInstance "SHA-256")]
|
|
||||||
(.digest digest message)))
|
|
||||||
|
|
||||||
(defn num->bytes
|
|
||||||
"Returns the byte-array representation of n.
|
|
||||||
The array will have the specified length."
|
|
||||||
[length n]
|
|
||||||
(let [a (.toByteArray (biginteger n))
|
|
||||||
l (count a)
|
|
||||||
zeros (repeat (- length l) (byte 0))]
|
|
||||||
(if (> l length)
|
|
||||||
(byte-array (drop (- l length) (seq a)))
|
|
||||||
(byte-array (concat zeros a)))))
|
|
||||||
|
|
||||||
(defn bytes->num
|
|
||||||
"Returns a BigInteger from a byte-array."
|
|
||||||
^BigInteger [^bytes bytes]
|
|
||||||
(BigInteger. 1 bytes))
|
|
||||||
|
|
||||||
(defn bytes->hex-string
|
|
||||||
"Returns a string containing the hexadecimal
|
|
||||||
representation of the byte-array. This is the
|
|
||||||
inverse of hex-string->bytes."
|
|
||||||
[byte-array]
|
|
||||||
(let [byte-seq (for [i (range (alength byte-array))] (aget byte-array i))
|
|
||||||
byte-strings (map #(apply str (take-last 2 (format "%02x" %))) byte-seq)]
|
|
||||||
(apply str (apply concat byte-strings))))
|
|
||||||
|
|
||||||
(defn num32->hex-string [n]
|
|
||||||
(->> n (num->bytes 32) bytes->hex-string))
|
|
||||||
|
|
||||||
(defn ^bytes hex-string->bytes
|
|
||||||
"returns a byte-array containing the bytes described
|
|
||||||
by the hex-string. This is the inverse of bytes->hex-string."
|
|
||||||
[hex-string]
|
|
||||||
(let [byte-strings (map #(apply str %) (partition 2 hex-string))
|
|
||||||
byte-vector (map #(Integer/parseInt % 16) byte-strings)]
|
|
||||||
(byte-array byte-vector)))
|
|
||||||
|
|
||||||
(defn hex-string->num
|
|
||||||
"returns BigInteger from a hex string"
|
|
||||||
[hex-string]
|
|
||||||
(-> hex-string hex-string->bytes bytes->num))
|
|
||||||
|
|
||||||
(defn bytes= [^bytes b1 ^bytes b2]
|
|
||||||
(assert (= (alength b1) (alength b2)) "bytes= args not same size.")
|
|
||||||
(loop [index 0]
|
|
||||||
(if (= index (alength b1))
|
|
||||||
true
|
|
||||||
(if (= (aget b1 index) (aget b2 index))
|
|
||||||
(recur (inc index))
|
|
||||||
false)))
|
|
||||||
)
|
|
||||||
|
|
||||||
(defn xor-bytes [^bytes a ^bytes b]
|
|
||||||
(assert (= (alength a) (alength b)) "byte-wise-xor: arguments not same size.")
|
|
||||||
(let [result (byte-array (alength a))]
|
|
||||||
(doseq [i (range (alength a))]
|
|
||||||
(aset result i (byte (bit-xor (aget a i) (aget b i)))))
|
|
||||||
result))
|
|
||||||
|
|
||||||
(defn do-sign [message private-key aux-rand]
|
(defn do-sign [message private-key aux-rand]
|
||||||
(Schnorr/sign message private-key aux-rand))
|
(Schnorr/sign message private-key aux-rand))
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
[clojure.data.json :as json]
|
[clojure.data.json :as json]
|
||||||
[more-speech.nostr.util :refer [hex-string->num]]
|
[more-speech.nostr.util :refer [hex-string->num]]
|
||||||
[more-speech.nostr.elliptic-signature :as ecc]
|
[more-speech.nostr.elliptic-signature :as ecc]
|
||||||
[clojure.core.async :as async])
|
[clojure.core.async :as async]
|
||||||
|
[more-speech.nostr.util :as util])
|
||||||
(:import (java.nio.charset StandardCharsets)))
|
(:import (java.nio.charset StandardCharsets)))
|
||||||
|
|
||||||
(s/def ::id number?)
|
(s/def ::id number?)
|
||||||
@ -22,7 +23,7 @@
|
|||||||
::tags
|
::tags
|
||||||
::references]))
|
::references]))
|
||||||
(defn hexify [n]
|
(defn hexify [n]
|
||||||
(ecc/num32->hex-string n))
|
(util/num32->hex-string n))
|
||||||
|
|
||||||
(defprotocol event-handler
|
(defprotocol event-handler
|
||||||
(handle-text-event [handler event])
|
(handle-text-event [handler event])
|
||||||
@ -44,20 +45,27 @@
|
|||||||
(defn process-event [{:keys [nicknames] :as event-state} event]
|
(defn process-event [{:keys [nicknames] :as event-state} event]
|
||||||
(let [_name-of (fn [pubkey] (get nicknames pubkey pubkey))
|
(let [_name-of (fn [pubkey] (get nicknames pubkey pubkey))
|
||||||
[_name _subscription-id inner-event :as _decoded-msg] event
|
[_name _subscription-id inner-event :as _decoded-msg] event
|
||||||
{:strs [_id _pubkey _created_at kind _tags _content _sig]} inner-event]
|
{:strs [id pubkey _created_at kind _tags _content sig]} inner-event
|
||||||
(condp = kind
|
valid? (ecc/do-verify (util/hex-string->bytes id)
|
||||||
0 (process-name-event event-state inner-event)
|
(util/hex-string->bytes pubkey)
|
||||||
3 (do
|
(util/hex-string->bytes sig))]
|
||||||
;(printf "%s: %s %s %s\n" kind (f/format-time created_at) (name-of pubkey) content)
|
(if (not valid?)
|
||||||
event-state)
|
(do
|
||||||
1 (do
|
(prn 'signature-verification-failed event)
|
||||||
;(printf "%s: %s %s %s\n" kind (f/format-time created_at) (name-of pubkey) (subs content 0 (min 50 (count content))))
|
event-state)
|
||||||
(process-text-event event-state inner-event))
|
(condp = kind
|
||||||
4 (do
|
0 (process-name-event event-state inner-event)
|
||||||
;(printf "%s: %s %s %s\n" kind (f/format-time created_at) (name-of pubkey) content)
|
3 (do
|
||||||
event-state)
|
;(printf "%s: %s %s %s\n" kind (f/format-time created_at) (name-of pubkey) content)
|
||||||
(do (prn "unknown event: " event)
|
event-state)
|
||||||
event-state))))
|
1 (do
|
||||||
|
;(printf "%s: %s %s %s\n" kind (f/format-time created_at) (name-of pubkey) (subs content 0 (min 50 (count content))))
|
||||||
|
(process-text-event event-state inner-event))
|
||||||
|
4 (do
|
||||||
|
;(printf "%s: %s %s %s\n" kind (f/format-time created_at) (name-of pubkey) content)
|
||||||
|
event-state)
|
||||||
|
(do (prn "unknown event: " event)
|
||||||
|
event-state)))))
|
||||||
|
|
||||||
(defn process-name-event [event-state {:strs [_id pubkey _created_at _kind _tags content _sig] :as event}]
|
(defn process-name-event [event-state {:strs [_id pubkey _created_at _kind _tags content _sig] :as event}]
|
||||||
(try
|
(try
|
||||||
@ -141,7 +149,7 @@
|
|||||||
"returns byte array of id given the clojure form of the body"
|
"returns byte array of id given the clojure form of the body"
|
||||||
[{:keys [pubkey created_at kind tags content]}]
|
[{:keys [pubkey created_at kind tags content]}]
|
||||||
(let [id-event (to-json [0 pubkey created_at kind tags content])
|
(let [id-event (to-json [0 pubkey created_at kind tags content])
|
||||||
id (ecc/sha-256 (.getBytes id-event StandardCharsets/UTF_8))]
|
id (util/sha-256 (.getBytes id-event StandardCharsets/UTF_8))]
|
||||||
id)
|
id)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -155,23 +163,23 @@
|
|||||||
|
|
||||||
([event-state text reply-to-or-nil]
|
([event-state text reply-to-or-nil]
|
||||||
(let [private-key (get-in event-state [:keys :private-key])
|
(let [private-key (get-in event-state [:keys :private-key])
|
||||||
private-key (ecc/hex-string->bytes private-key)
|
private-key (util/hex-string->bytes private-key)
|
||||||
pubkey (ecc/get-pub-key private-key)
|
pubkey (ecc/get-pub-key private-key)
|
||||||
root (get-reply-root event-state reply-to-or-nil)
|
root (get-reply-root event-state reply-to-or-nil)
|
||||||
tags (concat (make-event-reference-tags reply-to-or-nil root)
|
tags (concat (make-event-reference-tags reply-to-or-nil root)
|
||||||
(make-people-reference-tags event-state pubkey reply-to-or-nil))
|
(make-people-reference-tags event-state pubkey reply-to-or-nil))
|
||||||
content text
|
content text
|
||||||
now (quot (System/currentTimeMillis) 1000)
|
now (quot (System/currentTimeMillis) 1000)
|
||||||
body {:pubkey (ecc/bytes->hex-string pubkey)
|
body {:pubkey (util/bytes->hex-string pubkey)
|
||||||
:created_at now
|
:created_at now
|
||||||
:kind 1
|
:kind 1
|
||||||
:tags tags
|
:tags tags
|
||||||
:content content}
|
:content content}
|
||||||
id (make-id body)
|
id (make-id body)
|
||||||
aux-rand (ecc/num->bytes 32 (biginteger (System/currentTimeMillis)))
|
aux-rand (util/num->bytes 32 (biginteger (System/currentTimeMillis)))
|
||||||
signature (ecc/do-sign id private-key aux-rand)
|
signature (ecc/do-sign id private-key aux-rand)
|
||||||
event (assoc body :id (ecc/bytes->hex-string id)
|
event (assoc body :id (util/bytes->hex-string id)
|
||||||
:sig (ecc/bytes->hex-string signature))
|
:sig (util/bytes->hex-string signature))
|
||||||
]
|
]
|
||||||
["EVENT" event])))
|
["EVENT" event])))
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@
|
|||||||
(defn get-events [event-agent]
|
(defn get-events [event-agent]
|
||||||
(let [conn (connect-to-relay (get relays 0) event-agent)
|
(let [conn (connect-to-relay (get relays 0) event-agent)
|
||||||
id "more-speech"
|
id "more-speech"
|
||||||
date (make-date "04/1/2022")
|
date (make-date "04/20/2022")
|
||||||
send-chan (:send-chan @event-agent)
|
send-chan (:send-chan @event-agent)
|
||||||
]
|
]
|
||||||
(prn date (format-time date))
|
(prn date (format-time date))
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
(ns more-speech.nostr.util)
|
(ns more-speech.nostr.util
|
||||||
|
(:import (java.security MessageDigest)))
|
||||||
|
|
||||||
(defn num->bytes
|
(defn num->bytes
|
||||||
"Returns the byte-array representation of n.
|
"Returns the byte-array representation of n.
|
||||||
@ -35,12 +36,36 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
(defn hex-string->num
|
(defn hex-string->num
|
||||||
"Converts a hex string to a BigInteger"
|
"returns BigInteger from a hex string"
|
||||||
^BigInteger [hex-string]
|
[hex-string]
|
||||||
(bytes->num (hex-string->bytes hex-string))
|
(-> hex-string hex-string->bytes bytes->num))
|
||||||
|
|
||||||
|
(defn num32->hex-string [n]
|
||||||
|
"converts a number to a 32 byte hex-string"
|
||||||
|
(->> n (num->bytes 32) bytes->hex-string))
|
||||||
|
|
||||||
|
(defn bytes=
|
||||||
|
"compares two byte arrays for equality."
|
||||||
|
[^bytes b1 ^bytes b2]
|
||||||
|
(assert (= (alength b1) (alength b2)) "bytes= args not same size.")
|
||||||
|
(loop [index 0]
|
||||||
|
(if (= index (alength b1))
|
||||||
|
true
|
||||||
|
(if (= (aget b1 index) (aget b2 index))
|
||||||
|
(recur (inc index))
|
||||||
|
false)))
|
||||||
)
|
)
|
||||||
|
|
||||||
(defn num->hex-string
|
(defn sha-256
|
||||||
"converts a BigInteger to a hex-string"
|
"Returns the sha256 hash of the message.
|
||||||
[^BigInteger num]
|
Both the message and the hash are byte-arrays."
|
||||||
(bytes->hex-string (num->bytes 32 num)))
|
^bytes [^bytes message]
|
||||||
|
(let [digest (MessageDigest/getInstance "SHA-256")]
|
||||||
|
(.digest digest message)))
|
||||||
|
|
||||||
|
(defn xor-bytes [^bytes a ^bytes b]
|
||||||
|
(assert (= (alength a) (alength b)) "byte-wise-xor: arguments not same size.")
|
||||||
|
(let [result (byte-array (alength a))]
|
||||||
|
(doseq [i (range (alength a))]
|
||||||
|
(aset result i (byte (bit-xor (aget a i) (aget b i)))))
|
||||||
|
result))
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
(defn format-user-id [nicknames user-id]
|
(defn format-user-id [nicknames user-id]
|
||||||
(if (nil? user-id)
|
(if (nil? user-id)
|
||||||
""
|
""
|
||||||
(abbreviate (get nicknames user-id (util/num->hex-string user-id)) 20)))
|
(abbreviate (get nicknames user-id (util/num32->hex-string user-id)) 20)))
|
||||||
|
|
||||||
(defn format-header [nicknames {:keys [pubkey created-at content] :as event}]
|
(defn format-header [nicknames {:keys [pubkey created-at content] :as event}]
|
||||||
(if (nil? event)
|
(if (nil? event)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
(ns more-speech.ui.swing.article-tree
|
(ns more-speech.ui.swing.article-tree
|
||||||
(:require [more-speech.nostr.events :as events]
|
(:require [more-speech.nostr.events :as events]
|
||||||
[more-speech.ui.formatters :as formatters]
|
[more-speech.ui.formatters :as formatters]
|
||||||
[more-speech.nostr.elliptic-signature :as ecc]
|
[more-speech.ui.config :as config]
|
||||||
[more-speech.ui.config :as config])
|
[more-speech.nostr.util :as util])
|
||||||
(:use [seesaw core font tree])
|
(:use [seesaw core font tree])
|
||||||
(:import (javax.swing.tree DefaultMutableTreeNode DefaultTreeModel TreePath)))
|
(:import (javax.swing.tree DefaultMutableTreeNode DefaultTreeModel TreePath)))
|
||||||
|
|
||||||
@ -36,7 +36,7 @@
|
|||||||
(if (some? referent)
|
(if (some? referent)
|
||||||
(let [replied-event (get text-map referent)]
|
(let [replied-event (get text-map referent)]
|
||||||
(text! reply-to (format-user (:pubkey replied-event)))
|
(text! reply-to (format-user (:pubkey replied-event)))
|
||||||
(text! citing (formatters/abbreviate (ecc/num32->hex-string referent) 32)))
|
(text! citing (formatters/abbreviate (util/num32->hex-string referent) 32)))
|
||||||
(do (text! reply-to "")
|
(do (text! reply-to "")
|
||||||
(text! citing "")))
|
(text! citing "")))
|
||||||
)))
|
)))
|
||||||
|
Loading…
Reference in New Issue
Block a user