\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}