summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-09-03 17:00:13 -0400
committerjoe <joe@jerkface.net>2017-09-03 17:00:13 -0400
commit287379163d93d58142972f5f94c2beb8e872f7d4 (patch)
treed36d782a92ef499af073785321f81cc1ae11fd39
parent6e82103d0e7f87127bb5b3f1f395e1d5b7adb1e0 (diff)
Implemented more stubs for DHT transport.
-rw-r--r--DHTHandlers.hs36
-rw-r--r--DHTTransport.hs131
-rw-r--r--ToxAddress.hs40
-rw-r--r--ToxCrypto.hs34
4 files changed, 192 insertions, 49 deletions
diff --git a/DHTHandlers.hs b/DHTHandlers.hs
index 41a4bc06..437b05f3 100644
--- a/DHTHandlers.hs
+++ b/DHTHandlers.hs
@@ -6,19 +6,24 @@ import DHTTransport
6import Network.QueryResponse as QR hiding (Client) 6import Network.QueryResponse as QR hiding (Client)
7import qualified Network.QueryResponse as QR (Client) 7import qualified Network.QueryResponse as QR (Client)
8import ToxCrypto 8import ToxCrypto
9import ToxMessage as Tox (PacketKind(..), pattern PingType, pattern GetNodesType, pattern DHTRequestType) 9import ToxMessage as Tox (PacketKind(..), pattern PingType, pattern PongType, pattern GetNodesType, pattern SendNodesType, pattern DHTRequestType)
10import Network.BitTorrent.DHT.Search
10 11
12import Control.Arrow
11import qualified Data.Wrapper.PSQInt as Int 13import qualified Data.Wrapper.PSQInt as Int
12import Kademlia 14import Kademlia
13import Network.Address (WantIP (..), ipFamily, testIdBit) 15import Network.Address (WantIP (..), ipFamily, testIdBit,fromSockAddr, sockAddrPort)
14import qualified Network.DHT.Routing as R 16import qualified Network.DHT.Routing as R
15import TriadCommittee 17import TriadCommittee
18import Global6
16 19
17import Control.Monad 20import Control.Monad
18import Control.Concurrent.STM 21import Control.Concurrent.STM
19import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime) 22import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime)
20import Network.Socket 23import Network.Socket
24import Data.Hashable
21import Data.IP 25import Data.IP
26import Data.Ord
22import Data.Maybe 27import Data.Maybe
23import Data.Bits 28import Data.Bits
24 29
@@ -77,9 +82,11 @@ newRouting addr crypto update4 update6 = do
77 82
78 83
79-- TODO: This should cover more cases 84-- TODO: This should cover more cases
85isLocal :: IP -> Bool
80isLocal (IPv6 ip6) = (ip6 == toEnum 0) 86isLocal (IPv6 ip6) = (ip6 == toEnum 0)
81isLocal (IPv4 ip4) = (ip4 == toEnum 0) 87isLocal (IPv4 ip4) = (ip4 == toEnum 0)
82 88
89isGlobal :: IP -> Bool
83isGlobal = not . isLocal 90isGlobal = not . isLocal
84 91
85prefer4or6 :: NodeInfo -> Maybe WantIP -> WantIP 92prefer4or6 :: NodeInfo -> Maybe WantIP -> WantIP
@@ -210,6 +217,27 @@ transitionCommittee committee _ = return $ return ()
210 217
211type Handler = MethodHandler String TransactionId NodeInfo Message 218type Handler = MethodHandler String TransactionId NodeInfo Message
212 219
220isPing :: (f Ping -> Ping) -> DHTMessage f -> Either String Ping
221isPing unpack (DHTPing a) = Right $ unpack $ assymData a
222isPing _ _ = Left "Bad ping"
223
224mkPong :: TransactionId -> NodeInfo -> NodeInfo -> Pong -> DHTMessage ((,) Nonce8)
225mkPong tid src dst pong = DHTPong $ wrapAssym tid src dst (, pong)
226
227isGetNodes :: (f GetNodes -> GetNodes) -> DHTMessage f -> Either String GetNodes
228isGetNodes unpack (DHTGetNodes a) = Right $ unpack $ assymData a
229isGetNodes _ _ = Left "Bad GetNodes"
230
231mkSendNodes :: TransactionId -> NodeInfo -> NodeInfo -> SendNodes -> DHTMessage ((,) Nonce8)
232mkSendNodes tid src dst sendnodes = DHTSendNodes $ wrapAssym tid src dst (, sendnodes)
233
213handlers :: Routing -> Tox.PacketKind -> Maybe Handler 234handlers :: Routing -> Tox.PacketKind -> Maybe Handler
214handlers routing PingType = handler PongType pingH 235handlers routing PingType = Just $ MethodHandler (isPing snd) mkPong pingH
215handlers routing GetNodesType = handler SendNodesType $ getNodesH routing 236handlers routing GetNodesType = Just $ MethodHandler (isGetNodes snd) mkSendNodes $ getNodesH routing
237
238nodeSearch :: Client -> Search NodeId (IP,PortNumber) () NodeInfo NodeInfo
239nodeSearch client = Search
240 { searchSpace = toxSpace
241 , searchNodeAddress = nodeIP &&& nodePort
242 , searchQuery = getNodes client
243 }
diff --git a/DHTTransport.hs b/DHTTransport.hs
index 690ee346..778390cf 100644
--- a/DHTTransport.hs
+++ b/DHTTransport.hs
@@ -29,10 +29,11 @@ import Network.QueryResponse
29 29
30import Control.Arrow 30import Control.Arrow
31import Control.Monad 31import Control.Monad
32import Data.Bool
32import qualified Data.ByteString as B 33import qualified Data.ByteString as B
33 ;import Data.ByteString (ByteString) 34 ;import Data.ByteString (ByteString)
34import Data.Tuple 35import Data.Tuple
35import Data.Serialize as S (Get, Serialize, get, put, runGet) 36import Data.Serialize as S
36import Data.Word 37import Data.Word
37import Network.Socket 38import Network.Socket
38 39
@@ -50,13 +51,14 @@ data DHTMessage (f :: * -> *)
50 | DHTDHTRequest PublicKey (Assym (f DHTRequest)) 51 | DHTDHTRequest PublicKey (Assym (f DHTRequest))
51 52
52mapMessage :: forall f b. (forall a. Nonce24 -> f a -> b) -> DHTMessage f -> b 53mapMessage :: forall f b. (forall a. Nonce24 -> f a -> b) -> DHTMessage f -> b
53mapMessage f msg = f _todo _todo 54mapMessage f (DHTPing a) = f (assymNonce a) (assymData a)
55mapMessage f (DHTPong a) = f (assymNonce a) (assymData a)
56mapMessage f (DHTGetNodes a) = f (assymNonce a) (assymData a)
57mapMessage f (DHTSendNodes a) = f (assymNonce a) (assymData a)
58mapMessage f (DHTCookieRequest a) = f (assymNonce a) (assymData a)
59mapMessage f (DHTDHTRequest _ a) = f (assymNonce a) (assymData a)
60mapMessage f (DHTCookie nonce fcookie) = f nonce fcookie
54 61
55instance Sized GetNodes where
56 size = ConstSize 32 -- TODO This right?
57
58instance Sized SendNodes where
59 size = VarSize $ \(SendNodes ns) -> _nodeFormatSize * length ns
60 62
61instance Sized Ping where size = ConstSize 1 63instance Sized Ping where size = ConstSize 1
62instance Sized Pong where size = ConstSize 1 64instance Sized Pong where size = ConstSize 1
@@ -77,27 +79,48 @@ parseDHTAddr (msg,saddr)
77 _ -> right 79 _ -> right
78 80
79encodeDHTAddr :: (DHTMessage Encrypted8,NodeInfo) -> (ByteString, SockAddr) 81encodeDHTAddr :: (DHTMessage Encrypted8,NodeInfo) -> (ByteString, SockAddr)
80encodeDHTAddr = _todo 82encodeDHTAddr (msg,ni) = (runPut $ putMessage msg, nodeAddr ni)
83
84dhtMessageType :: DHTMessage Encrypted8 -> ( Word8, Put )
85dhtMessageType (DHTPing a) = (0x00, putAssym a)
86dhtMessageType (DHTPong a) = (0x01, putAssym a)
87dhtMessageType (DHTGetNodes a) = (0x02, putAssym a)
88dhtMessageType (DHTSendNodes a) = (0x04, putAssym a)
89dhtMessageType (DHTCookieRequest a) = (0x18, putAssym a)
90dhtMessageType (DHTCookie n x) = (0x19, put n >> put x)
91dhtMessageType (DHTDHTRequest k a) = (0x20, putPublicKey k >> putAssym a)
92
93putMessage :: DHTMessage Encrypted8 -> Put
94putMessage msg = case dhtMessageType msg of (typ,p) -> put typ >> p
81 95
82getCookie :: Get (Nonce24, Encrypted8 Cookie) 96getCookie :: Get (Nonce24, Encrypted8 Cookie)
83getCookie = get 97getCookie = get
84 98
85getDHTReqest :: Get (PublicKey, Assym (Encrypted8 DHTRequest)) 99getDHTReqest :: Get (PublicKey, Assym (Encrypted8 DHTRequest))
86getDHTReqest = _todo 100getDHTReqest = (,) <$> getPublicKey <*> getAssym
101
102-- ## DHT Request packets
103--
104-- | Length | Contents |
105-- |:-------|:--------------------------|
106-- | `1` | `uint8_t` (0x20) |
107-- | `32` | receiver's DHT public key |
108-- ... ...
109
87 110
88getDHT :: Sized a => Get (Assym (Encrypted8 a)) 111getDHT :: Sized a => Get (Assym (Encrypted8 a))
89getDHT = _todo 112getDHT = getAssym
90 113
91 114
92-- Throws an error if called with a non-internet socket. 115-- Throws an error if called with a non-internet socket.
93direct :: Sized a => ByteString 116direct :: Sized a => ByteString
94 -> SockAddr 117 -> SockAddr
95 -> (Assym (Encrypted8 a) 118 -> (Assym (Encrypted8 a) -> DHTMessage Encrypted8)
96 -> DHTMessage Encrypted8)
97 -> Either String (DHTMessage Encrypted8, NodeInfo) 119 -> Either String (DHTMessage Encrypted8, NodeInfo)
98direct bs saddr f = fanGet bs getDHT f (asymNodeInfo saddr) 120direct bs saddr f = fanGet bs getDHT f (asymNodeInfo saddr)
99 121
100-- Throws an error if called with a non-internet socket. 122-- Throws an error if called with a non-internet socket.
123asymNodeInfo :: SockAddr -> Assym a -> NodeInfo
101asymNodeInfo saddr asym = either (error . mappend "asymNodeInfo: ") id $ nodeInfo (NodeId $ senderKey asym) saddr 124asymNodeInfo saddr asym = either (error . mappend "asymNodeInfo: ") id $ nodeInfo (NodeId $ senderKey asym) saddr
102 125
103 126
@@ -105,35 +128,49 @@ fanGet :: ByteString -> Get x -> (x -> a) -> (x -> b) -> Either String (a,b)
105fanGet bs getIt f nid = fmap (f &&& nid) $ runGet getIt bs 128fanGet bs getIt f nid = fmap (f &&& nid) $ runGet getIt bs
106 129
107-- Throws an error if called with a non-internet socket. 130-- Throws an error if called with a non-internet socket.
131noReplyAddr :: SockAddr -> NodeInfo
108noReplyAddr saddr = either (error . mappend "noReplyAddr: ") id $ nodeInfo zeroID saddr 132noReplyAddr saddr = either (error . mappend "noReplyAddr: ") id $ nodeInfo zeroID saddr
109 133
110 134
111-- ## DHT Request packets
112--
113-- | Length | Contents |
114-- |:-------|:--------------------------|
115-- | `1` | `uint8_t` (0x20) |
116-- | `32` | receiver's DHT public key |
117-- ... ...
118
119data DHTRequestPacket = DHTRequestPacket
120 { requestTarget :: PublicKey
121 , request :: Assym (Encrypted DHTRequest)
122 }
123
124instance Serialize DHTRequestPacket where
125 get = _todo
126 put = _todo
127
128
129data DHTRequest 135data DHTRequest
136-- #### NAT ping request
137--
138-- Length Contents
139-- :------- :-------------------------
140-- `1` `uint8_t` (0xfe)
141-- `1` `uint8_t` (0x00)
142-- `8` `uint64_t` random number
130 = NATPing Nonce8 143 = NATPing Nonce8
144-- #### NAT ping response
145--
146-- Length Contents
147-- :------- :-----------------------------------------------------------------
148-- `1` `uint8_t` (0xfe)
149-- `1` `uint8_t` (0x01)
150-- `8` `uint64_t` random number (the same that was received in request)
131 | NATPong Nonce8 151 | NATPong Nonce8
132 | DHTPK DHTPublicKey 152 | DHTPK DHTPublicKey
133 153
154instance Sized DHTRequest where
155 size = VarSize $ \case
156 NATPing _ -> 10
157 NATPong _ -> 10
158 DHTPK dhtpk -> 41 + case size of
159 ConstSize nodes -> nodes
160 VarSize sznodes -> sznodes (dhtpkNodes dhtpk)
161
134instance Serialize DHTRequest where 162instance Serialize DHTRequest where
135 get = return _todo 163 get = do
136 put _ = return () -- todo 164 tag <- get
165 case tag :: Word8 of
166 0xfe -> do
167 direction <- get
168 bool NATPong NATPing (direction==(0::Word8)) <$> get
169 0x9c -> DHTPK <$> get
170 _ -> fail ("unrecognized DHT request: "++show tag)
171 put (NATPing n) = put (0xfe00 :: Word16) >> put n
172 put (NATPong n) = put (0xfe01 :: Word16) >> put n
173 put (DHTPK pk) = put (0x9c :: Word8) >> put pk
137 174
138-- | Length | Contents | 175-- | Length | Contents |
139-- |:------------|:------------------------------------| 176-- |:------------|:------------------------------------|
@@ -147,12 +184,27 @@ data DHTPublicKey = DHTPublicKey
147 , dhtpkNodes :: SendNodes 184 , dhtpkNodes :: SendNodes
148 } 185 }
149 186
187instance Serialize DHTPublicKey where
188 get = DHTPublicKey <$> get <*> getPublicKey <*> get
189 put (DHTPublicKey nonce key nodes) = do
190 put nonce
191 putPublicKey key
192 put nodes
193
150newtype GetNodes = GetNodes NodeId 194newtype GetNodes = GetNodes NodeId
151 deriving (Eq,Ord,Show,Read,S.Serialize) 195 deriving (Eq,Ord,Show,Read,S.Serialize)
152 196
197instance Sized GetNodes where
198 size = ConstSize 32 -- TODO This right?
199
153newtype SendNodes = SendNodes [NodeInfo] 200newtype SendNodes = SendNodes [NodeInfo]
154 deriving (Eq,Ord,Show,Read) 201 deriving (Eq,Ord,Show,Read)
155 202
203instance Sized SendNodes where
204 size = VarSize $ \(SendNodes ns) -> case size of
205 ConstSize nodeFormatSize -> nodeFormatSize * length ns
206 VarSize nsize -> sum $ map nsize ns
207
156instance S.Serialize SendNodes where 208instance S.Serialize SendNodes where
157 get = do 209 get = do
158 cnt <- S.get :: S.Get Word8 210 cnt <- S.get :: S.Get Word8
@@ -189,8 +241,8 @@ data Cookie = Cookie Nonce24 (Encrypted CookieData)
189instance Sized Cookie where size = ConstSize 112 -- 24 byte nonce + 88 byte cookie data 241instance Sized Cookie where size = ConstSize 112 -- 24 byte nonce + 88 byte cookie data
190 242
191instance Serialize Cookie where 243instance Serialize Cookie where
192 get = return $ Cookie _todo _todo 244 get = Cookie <$> get <*> get
193 put _ = return () -- todo 245 put (Cookie nonce dta) = put nonce >> put dta
194 246
195data CookieData = CookieData -- 16 (mac) 247data CookieData = CookieData -- 16 (mac)
196 { cookieTime :: Word64 -- 8 248 { cookieTime :: Word64 -- 8
@@ -198,12 +250,15 @@ data CookieData = CookieData -- 16 (mac)
198 , dhtKey :: PublicKey -- + 32 250 , dhtKey :: PublicKey -- + 32
199 } -- = 88 bytes when encrypted. 251 } -- = 88 bytes when encrypted.
200 252
253instance Sized CookieData where
254 size = ConstSize 72
255
201instance Sized CookieRequest where 256instance Sized CookieRequest where
202 size = ConstSize 64 -- 32 byte key + 32 byte padding 257 size = ConstSize 64 -- 32 byte key + 32 byte padding
203 258
204instance Serialize CookieRequest where 259instance Serialize CookieRequest where
205 get = CookieRequest <$> return _todo 260 get = CookieRequest <$> getPublicKey <* {- padding -} getPublicKey
206 put (CookieRequest _) = return () -- todo 261 put (CookieRequest k) = putPublicKey k >> {- padding -} putPublicKey k
207 262
208forwardDHTRequests :: TransportCrypto -> (PublicKey -> IO (Maybe NodeInfo)) -> DHTTransport -> DHTTransport 263forwardDHTRequests :: TransportCrypto -> (PublicKey -> IO (Maybe NodeInfo)) -> DHTTransport -> DHTTransport
209forwardDHTRequests crypto closeLookup dht = dht { awaitMessage = await' } 264forwardDHTRequests crypto closeLookup dht = dht { awaitMessage = await' }
@@ -226,7 +281,7 @@ encryptMessage crypto n (Right assym) = E8 $ ToxCrypto.encrypt secret plain
226 where 281 where
227 secret = computeSharedSecret (transportSecret crypto) (senderKey assym) n 282 secret = computeSharedSecret (transportSecret crypto) (senderKey assym) n
228 plain = encodePlain $ swap $ assymData assym 283 plain = encodePlain $ swap $ assymData assym
229encryptMessage crypto n (Left plain) = _todo 284encryptMessage crypto n (Left plain) = _todo -- need cached public key.
230 285
231decrypt :: TransportCrypto -> DHTMessage Encrypted8 -> NodeInfo -> Either String (DHTMessage ((,) Nonce8), NodeInfo) 286decrypt :: TransportCrypto -> DHTMessage Encrypted8 -> NodeInfo -> Either String (DHTMessage ((,) Nonce8), NodeInfo)
232decrypt crypto msg ni = (, ni) <$> (sequenceMessage $ transcode (decryptMessage crypto) msg) 287decrypt crypto msg ni = (, ni) <$> (sequenceMessage $ transcode (decryptMessage crypto) msg)
@@ -241,7 +296,7 @@ decryptMessage crypto n (Right assymE) = plain8 $ ToxCrypto.decrypt secret e
241 secret = computeSharedSecret (transportSecret crypto) (senderKey assymE) n 296 secret = computeSharedSecret (transportSecret crypto) (senderKey assymE) n
242 E8 e = assymData assymE 297 E8 e = assymData assymE
243 plain8 = Composed . fmap swap . (>>= decodePlain) 298 plain8 = Composed . fmap swap . (>>= decodePlain)
244decryptMessage crypto n (Left (E8 e)) = _todo 299decryptMessage crypto n (Left (E8 e)) = _todo -- need cached public key
245 300
246sequenceMessage :: Applicative m => DHTMessage (m ∘ f) -> m (DHTMessage f) 301sequenceMessage :: Applicative m => DHTMessage (m ∘ f) -> m (DHTMessage f)
247sequenceMessage (DHTPing asym) = fmap DHTPing $ sequenceA $ fmap uncomposed asym 302sequenceMessage (DHTPing asym) = fmap DHTPing $ sequenceA $ fmap uncomposed asym
diff --git a/ToxAddress.hs b/ToxAddress.hs
index ea69f6e3..04ee7d6f 100644
--- a/ToxAddress.hs
+++ b/ToxAddress.hs
@@ -13,7 +13,7 @@
13{-# LANGUAGE ScopedTypeVariables #-} 13{-# LANGUAGE ScopedTypeVariables #-}
14{-# LANGUAGE TupleSections #-} 14{-# LANGUAGE TupleSections #-}
15{-# LANGUAGE TypeApplications #-} 15{-# LANGUAGE TypeApplications #-}
16module ToxAddress (NodeInfo(..),NodeId(..),nodeInfo,zeroID) where 16module ToxAddress (NodeInfo(..),NodeId(..),nodeInfo,nodeAddr,zeroID,key2id,id2key) where
17 17
18import Control.Applicative 18import Control.Applicative
19import Control.Monad 19import Control.Monad
@@ -42,6 +42,7 @@ import System.IO.Unsafe (unsafeDupablePerformIO)
42import qualified Text.ParserCombinators.ReadP as RP 42import qualified Text.ParserCombinators.ReadP as RP
43import Text.Read 43import Text.Read
44import Data.Bits 44import Data.Bits
45import ToxCrypto
45 46
46-- | perform io for hashes that do allocation and ffi. 47-- | perform io for hashes that do allocation and ffi.
47-- unsafeDupablePerformIO is used when possible as the 48-- unsafeDupablePerformIO is used when possible as the
@@ -66,6 +67,26 @@ unpackPublicKey bs = loop 0
66newtype NodeId = NodeId PublicKey 67newtype NodeId = NodeId PublicKey
67 deriving (Eq,ByteArrayAccess) -- (Eq,Ord,ByteArrayAccess, Bits, Hashable) 68 deriving (Eq,ByteArrayAccess) -- (Eq,Ord,ByteArrayAccess, Bits, Hashable)
68 69
70key2id :: PublicKey -> NodeId
71key2id = NodeId
72
73id2key :: NodeId -> PublicKey
74id2key (NodeId key) = key
75
76{-
77id2key :: NodeId -> PublicKey
78id2key recipient = case publicKey recipient of
79 CryptoPassed key -> key
80 -- This should never happen because a NodeId is 32 bytes.
81 CryptoFailed e -> error ("Unexpected pattern fail: "++show e)
82
83key2id :: PublicKey -> NodeId
84key2id pk = case S.decode (BA.convert pk) of
85 Left _ -> error "key2id"
86 Right nid -> nid
87
88-}
89
69instance Ord NodeId where 90instance Ord NodeId where
70 compare (NodeId a) (NodeId b) = compare (unpackPublicKey a) (unpackPublicKey b) 91 compare (NodeId a) (NodeId b) = compare (unpackPublicKey a) (unpackPublicKey b)
71 92
@@ -83,8 +104,8 @@ instance Show NodeId where
83 show (NodeId bs) = C8.unpack $ Base16.encode $ BA.convert bs 104 show (NodeId bs) = C8.unpack $ Base16.encode $ BA.convert bs
84 105
85instance S.Serialize NodeId where 106instance S.Serialize NodeId where
86 get = NodeId . throwCryptoError . publicKey <$> S.getBytes 32 107 get = NodeId <$> getPublicKey
87 put (NodeId bs) = S.putByteString $ BA.convert bs 108 put (NodeId bs) = putPublicKey bs
88 109
89instance Bits NodeId where -- TODO 110instance Bits NodeId where -- TODO
90 111
@@ -144,6 +165,12 @@ getIP 0x82 = IPv4 <$> S.get -- TODO: TCP
144getIP 0x8a = IPv6 <$> S.get -- TODO: TCP 165getIP 0x8a = IPv6 <$> S.get -- TODO: TCP
145getIP x = fail ("unsupported address family ("++show x++")") 166getIP x = fail ("unsupported address family ("++show x++")")
146 167
168instance Sized NodeInfo where
169 size = VarSize $ \(NodeInfo nid ip port) ->
170 case ip of
171 IPv4 _ -> 39 -- 35 + 4 = 1 + 4 + 2 + 32
172 IPv6 _ -> 51 -- 35 + 16 = 1 + 16 + 2 + 32
173
147instance S.Serialize NodeInfo where 174instance S.Serialize NodeInfo where
148 get = do 175 get = do
149 addrfam <- S.get :: S.Get Word8 176 addrfam <- S.get :: S.Get Word8
@@ -354,9 +381,6 @@ instance Show NodeInfo where
354 | IPv6 ip6 <- ip , Just ip4 <- un4map ip6 = shows ip4 381 | IPv6 ip6 <- ip , Just ip4 <- un4map ip6 = shows ip4
355 | otherwise = ('[' :) . shows ip . (']' :) 382 | otherwise = ('[' :) . shows ip . (']' :)
356 383
357nodeAddr :: NodeInfo -> SockAddr
358nodeAddr (NodeInfo _ ip port) = setPort port $ toSockAddr ip
359
360nodeInfo :: NodeId -> SockAddr -> Either String NodeInfo 384nodeInfo :: NodeId -> SockAddr -> Either String NodeInfo
361nodeInfo nid saddr 385nodeInfo nid saddr
362 | Just ip <- fromSockAddr saddr 386 | Just ip <- fromSockAddr saddr
@@ -368,6 +392,10 @@ zeroID = PubKey $ B.replicate 32 0
368 392
369-} 393-}
370 394
395nodeAddr :: NodeInfo -> SockAddr
396nodeAddr (NodeInfo _ ip port) = setPort port $ toSockAddr ip
397
398
371newtype ForwardPath (n::Nat) = ForwardPath ByteString 399newtype ForwardPath (n::Nat) = ForwardPath ByteString
372 deriving (Eq, Ord,Data) 400 deriving (Eq, Ord,Data)
373 401
diff --git a/ToxCrypto.hs b/ToxCrypto.hs
index c2e2bbeb..e3bc57f9 100644
--- a/ToxCrypto.hs
+++ b/ToxCrypto.hs
@@ -9,6 +9,8 @@
9module ToxCrypto 9module ToxCrypto
10 ( PublicKey 10 ( PublicKey
11 , publicKey 11 , publicKey
12 , getPublicKey
13 , putPublicKey
12 , SecretKey 14 , SecretKey
13 , SymmetricKey(..) 15 , SymmetricKey(..)
14 , TransportCrypto(..) 16 , TransportCrypto(..)
@@ -16,6 +18,10 @@ module ToxCrypto
16 , Encrypted8(..) 18 , Encrypted8(..)
17 , type (∘)(..) 19 , type (∘)(..)
18 , Assym(..) 20 , Assym(..)
21 , getAssym
22 , getAliasedAssym
23 , putAssym
24 , putAliasedAssym
19 , Plain 25 , Plain
20 , encodePlain 26 , encodePlain
21 , decodePlain 27 , decodePlain
@@ -49,7 +55,7 @@ import qualified Data.ByteString.Char8 as C8
49import Data.Data 55import Data.Data
50import Data.Kind 56import Data.Kind
51import Data.Ord 57import Data.Ord
52import Data.Serialize 58import Data.Serialize as S
53import Data.Word 59import Data.Word
54import Foreign.Marshal.Alloc 60import Foreign.Marshal.Alloc
55import Foreign.Ptr 61import Foreign.Ptr
@@ -57,6 +63,7 @@ import Foreign.Storable
57import System.Endian 63import System.Endian
58import qualified Data.ByteString.Internal 64import qualified Data.ByteString.Internal
59import Control.Concurrent.STM 65import Control.Concurrent.STM
66import Crypto.Error.Types (CryptoFailable (..), throwCryptoError)
60 67
61-- | A 16-byte mac and an arbitrary-length encrypted stream. 68-- | A 16-byte mac and an arbitrary-length encrypted stream.
62newtype Encrypted a = Encrypted ByteString 69newtype Encrypted a = Encrypted ByteString
@@ -76,6 +83,7 @@ instance Data Auth where
76 gunfold k z c = k (z (Auth . Poly1305.Auth . (BA.convert :: ByteString -> Bytes))) 83 gunfold k z c = k (z (Auth . Poly1305.Auth . (BA.convert :: ByteString -> Bytes)))
77 toConstr _ = con_Auth 84 toConstr _ = con_Auth
78 dataTypeOf _ = mkDataType "ToxMessage" [con_Auth] 85 dataTypeOf _ = mkDataType "ToxMessage" [con_Auth]
86con_Auth :: Constr
79con_Auth = mkConstr (dataTypeOf (Auth (error "con_Auth"))) "Auth" [] Prefix 87con_Auth = mkConstr (dataTypeOf (Auth (error "con_Auth"))) "Auth" [] Prefix
80instance Serialize Auth where 88instance Serialize Auth where
81 get = Auth . Poly1305.Auth . BA.convert <$> getBytes 16 89 get = Auth . Poly1305.Auth . BA.convert <$> getBytes 16
@@ -165,6 +173,7 @@ computeSharedSecret sk recipient nonce = State hash crypt
165 -- Since rs is 32 bytes, this pattern should never fail... 173 -- Since rs is 32 bytes, this pattern should never fail...
166 Cryptonite.CryptoPassed hash = Poly1305.initialize rs 174 Cryptonite.CryptoPassed hash = Poly1305.initialize rs
167 175
176hsalsa20 :: (ByteArrayAccess t, ByteArrayAccess t1) => t1 -> t -> BA.ScrubbedBytes
168hsalsa20 k n = BA.append a b 177hsalsa20 k n = BA.append a b
169 where 178 where
170 Salsa.State st = XSalsa.initialize 20 k n 179 Salsa.State st = XSalsa.initialize 20 k n
@@ -241,6 +250,23 @@ data Assym a = Assym
241 } 250 }
242 deriving (Functor,Foldable,Traversable) 251 deriving (Functor,Foldable,Traversable)
243 252
253-- | Field order: senderKey, then nonce This is the format used by
254-- Ping/Pong/GetNodes/SendNodes.
255--
256-- See 'getAliasedAssym' if the nonce precedes the key.
257getAssym :: Serialize a => Get (Assym a)
258getAssym = Assym <$> getPublicKey <*> get <*> get
259
260putAssym :: Serialize a => Assym a -> Put
261putAssym (Assym key nonce dta) = putPublicKey key >> put nonce >> put dta
262
263-- | Field order: nonce, and then senderKey.
264getAliasedAssym :: Serialize a => Get (Assym a)
265getAliasedAssym = flip Assym <$> get <*> getPublicKey <*> get
266
267putAliasedAssym :: Serialize a => Assym a -> Put
268putAliasedAssym (Assym key nonce dta) = put nonce >> putPublicKey key >> put dta
269
244newtype SymmetricKey = SymmetricKey ByteString 270newtype SymmetricKey = SymmetricKey ByteString
245 271
246data TransportCrypto = TransportCrypto 272data TransportCrypto = TransportCrypto
@@ -249,3 +275,9 @@ data TransportCrypto = TransportCrypto
249 , transportSymmetric :: STM SymmetricKey 275 , transportSymmetric :: STM SymmetricKey
250 } 276 }
251 277
278getPublicKey :: S.Get PublicKey
279getPublicKey = throwCryptoError . publicKey <$> S.getBytes 32
280
281putPublicKey :: PublicKey -> S.Put
282putPublicKey bs = S.putByteString $ BA.convert bs
283