\subsection{Nonce} A random nonce is generated using the cryptographically secure random number generator from the NaCl library \texttt{randombytes}. A nonce is incremented by interpreting it as a Big Endian number and adding 1. If the nonce has the maximum value, the value after the increment is 0. Most parts of the protocol use random nonces. This prevents new nonces from being associated with previous nonces. If many different packets could be tied together due to how the nonces were generated, it might for example lead to tying DHT and onion announce packets together. This would introduce a flaw in the system as non friends could tie some people's DHT keys and long term keys together. \begin{code} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} {-# LANGUAGE StrictData #-} module Tox.Crypto.Core.Nonce where import qualified Crypto.Saltine.Class as Sodium (decode, encode, nudge) import qualified Crypto.Saltine.Core.Box as Sodium (newNonce) import qualified Data.ByteString as BS import Tox.Crypto.Core.Key newNonce :: IO Nonce newNonce :: IO Nonce newNonce = Nonce -> Nonce forall a. a -> Key a Key (Nonce -> Nonce) -> IO Nonce -> IO Nonce forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> IO Nonce Sodium.newNonce reverseNonce :: Nonce -> Nonce reverseNonce :: Nonce -> Nonce reverseNonce (Key Nonce nonce) = let Just Nonce reversed = ByteString -> Maybe Nonce forall a. IsEncoding a => ByteString -> Maybe a Sodium.decode (ByteString -> Maybe Nonce) -> ByteString -> Maybe Nonce forall a b. (a -> b) -> a -> b $ ByteString -> ByteString BS.reverse (ByteString -> ByteString) -> ByteString -> ByteString forall a b. (a -> b) -> a -> b $ Nonce -> ByteString forall a. IsEncoding a => a -> ByteString Sodium.encode Nonce nonce in Nonce -> Nonce forall a. a -> Key a Key Nonce reversed nudge :: Nonce -> Nonce nudge :: Nonce -> Nonce nudge = Nonce -> Nonce forall a. a -> Key a Key (Nonce -> Nonce) -> (Nonce -> Nonce) -> Nonce -> Nonce forall b c a. (b -> c) -> (a -> b) -> a -> c . Nonce -> Nonce forall n. IsNonce n => n -> n Sodium.nudge (Nonce -> Nonce) -> (Nonce -> Nonce) -> Nonce -> Nonce forall b c a. (b -> c) -> (a -> b) -> a -> c . Nonce -> Nonce forall a. Key a -> a unKey increment :: Nonce -> Nonce increment :: Nonce -> Nonce increment = Nonce -> Nonce reverseNonce (Nonce -> Nonce) -> (Nonce -> Nonce) -> Nonce -> Nonce forall b c a. (b -> c) -> (a -> b) -> a -> c . Nonce -> Nonce nudge (Nonce -> Nonce) -> (Nonce -> Nonce) -> Nonce -> Nonce forall b c a. (b -> c) -> (a -> b) -> a -> c . Nonce -> Nonce reverseNonce nonceToInteger :: Nonce -> Integer nonceToInteger :: Nonce -> Integer nonceToInteger (Key Nonce nonce) = (Integer -> Word8 -> Integer) -> Integer -> ByteString -> Integer forall a. (a -> Word8 -> a) -> a -> ByteString -> a BS.foldl' (\Integer acc Word8 b -> Integer acc Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer 256 Integer -> Integer -> Integer forall a. Num a => a -> a -> a + Word8 -> Integer forall a b. (Integral a, Num b) => a -> b fromIntegral Word8 b) Integer 0 (Nonce -> ByteString forall a. IsEncoding a => a -> ByteString Sodium.encode Nonce nonce) nonceLimit :: Integer nonceLimit :: Integer nonceLimit = Integer 256 Integer -> Int -> Integer forall a b. (Num a, Integral b) => a -> b -> a ^ (Int 24 :: Int) integerToNonce :: Integer -> Nonce integerToNonce :: Integer -> Nonce integerToNonce Integer n = let bs :: ByteString bs = [Word8] -> ByteString BS.pack ([Word8] -> ByteString) -> ([Word8] -> [Word8]) -> [Word8] -> ByteString forall b c a. (b -> c) -> (a -> b) -> a -> c . [Word8] -> [Word8] forall a. [a] -> [a] reverse ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8] forall b c a. (b -> c) -> (a -> b) -> a -> c . Int -> [Word8] -> [Word8] forall a. Int -> [a] -> [a] take Int 24 ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8] forall b c a. (b -> c) -> (a -> b) -> a -> c . ([Word8] -> [Word8] -> [Word8] forall a. [a] -> [a] -> [a] ++ Word8 -> [Word8] forall a. a -> [a] repeat Word8 0) ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8] forall b c a. (b -> c) -> (a -> b) -> a -> c . [Word8] -> [Word8] forall a. [a] -> [a] reverse ([Word8] -> ByteString) -> [Word8] -> ByteString forall a b. (a -> b) -> a -> b $ Integer -> [Word8] forall t a. (Integral t, Num a) => t -> [a] toBytes (Integer n Integer -> Integer -> Integer forall a. Integral a => a -> a -> a `mod` Integer nonceLimit) Just Nonce nonce = ByteString -> Maybe Nonce forall a. IsEncoding a => ByteString -> Maybe a Sodium.decode ByteString bs in Nonce -> Nonce forall a. a -> Key a Key Nonce nonce where toBytes :: t -> [a] toBytes t 0 = [] toBytes t x = t -> a forall a b. (Integral a, Num b) => a -> b fromIntegral (t x t -> t -> t forall a. Integral a => a -> a -> a `rem` t 256) a -> [a] -> [a] forall a. a -> [a] -> [a] : t -> [a] toBytes (t x t -> t -> t forall a. Integral a => a -> a -> a `quot` t 256) \end{code}