{-# LANGUAGE DataKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}

module Crypto.Paseto.ScrubbedBytes
  ( ScrubbedBytes32 (ScrubbedBytes32)
  , mkScrubbedBytes32
  , fromSizedBytes
  , toBytes
  , toSizedBytes
  , generateScrubbedBytes32
  ) where

import Basement.NormalForm ( NormalForm )
import Control.DeepSeq ( NFData (..) )
import qualified Crypto.Random as Crypto
import Data.ByteArray ( ByteArrayAccess, ScrubbedBytes )
import qualified Data.ByteArray as BA
import Data.ByteArray.Sized
  ( ByteArrayN (..), SizedByteArray, sizedByteArray, unSizedByteArray )
import Prelude

-- | Simple wrapper around a 32-byte (256-bit) 'ScrubbedBytes' value.
--
-- Note that this type's 'Eq' instance performs a constant-time equality check.
newtype ScrubbedBytes32 = MkScrubbedBytes32
  { ScrubbedBytes32 -> SizedByteArray 32 ScrubbedBytes
unScrubbedBytes32 :: SizedByteArray 32 ScrubbedBytes }
  deriving newtype (Int -> ScrubbedBytes32 -> ShowS
[ScrubbedBytes32] -> ShowS
ScrubbedBytes32 -> String
(Int -> ScrubbedBytes32 -> ShowS)
-> (ScrubbedBytes32 -> String)
-> ([ScrubbedBytes32] -> ShowS)
-> Show ScrubbedBytes32
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ScrubbedBytes32 -> ShowS
showsPrec :: Int -> ScrubbedBytes32 -> ShowS
$cshow :: ScrubbedBytes32 -> String
show :: ScrubbedBytes32 -> String
$cshowList :: [ScrubbedBytes32] -> ShowS
showList :: [ScrubbedBytes32] -> ShowS
Show, ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
(ScrubbedBytes32 -> ScrubbedBytes32 -> Bool)
-> (ScrubbedBytes32 -> ScrubbedBytes32 -> Bool)
-> Eq ScrubbedBytes32
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
== :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
$c/= :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
/= :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
Eq, Eq ScrubbedBytes32
Eq ScrubbedBytes32 =>
(ScrubbedBytes32 -> ScrubbedBytes32 -> Ordering)
-> (ScrubbedBytes32 -> ScrubbedBytes32 -> Bool)
-> (ScrubbedBytes32 -> ScrubbedBytes32 -> Bool)
-> (ScrubbedBytes32 -> ScrubbedBytes32 -> Bool)
-> (ScrubbedBytes32 -> ScrubbedBytes32 -> Bool)
-> (ScrubbedBytes32 -> ScrubbedBytes32 -> ScrubbedBytes32)
-> (ScrubbedBytes32 -> ScrubbedBytes32 -> ScrubbedBytes32)
-> Ord ScrubbedBytes32
ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
ScrubbedBytes32 -> ScrubbedBytes32 -> Ordering
ScrubbedBytes32 -> ScrubbedBytes32 -> ScrubbedBytes32
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ScrubbedBytes32 -> ScrubbedBytes32 -> Ordering
compare :: ScrubbedBytes32 -> ScrubbedBytes32 -> Ordering
$c< :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
< :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
$c<= :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
<= :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
$c> :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
> :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
$c>= :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
>= :: ScrubbedBytes32 -> ScrubbedBytes32 -> Bool
$cmax :: ScrubbedBytes32 -> ScrubbedBytes32 -> ScrubbedBytes32
max :: ScrubbedBytes32 -> ScrubbedBytes32 -> ScrubbedBytes32
$cmin :: ScrubbedBytes32 -> ScrubbedBytes32 -> ScrubbedBytes32
min :: ScrubbedBytes32 -> ScrubbedBytes32 -> ScrubbedBytes32
Ord, ScrubbedBytes32 -> ()
(ScrubbedBytes32 -> ()) -> NormalForm ScrubbedBytes32
forall a. (a -> ()) -> NormalForm a
$ctoNormalForm :: ScrubbedBytes32 -> ()
toNormalForm :: ScrubbedBytes32 -> ()
NormalForm, ScrubbedBytes32 -> Int
(ScrubbedBytes32 -> Int)
-> (forall p a. ScrubbedBytes32 -> (Ptr p -> IO a) -> IO a)
-> (forall p. ScrubbedBytes32 -> Ptr p -> IO ())
-> ByteArrayAccess ScrubbedBytes32
forall p. ScrubbedBytes32 -> Ptr p -> IO ()
forall ba.
(ba -> Int)
-> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
-> (forall p. ba -> Ptr p -> IO ())
-> ByteArrayAccess ba
forall p a. ScrubbedBytes32 -> (Ptr p -> IO a) -> IO a
$clength :: ScrubbedBytes32 -> Int
length :: ScrubbedBytes32 -> Int
$cwithByteArray :: forall p a. ScrubbedBytes32 -> (Ptr p -> IO a) -> IO a
withByteArray :: forall p a. ScrubbedBytes32 -> (Ptr p -> IO a) -> IO a
$ccopyByteArrayToPtr :: forall p. ScrubbedBytes32 -> Ptr p -> IO ()
copyByteArrayToPtr :: forall p. ScrubbedBytes32 -> Ptr p -> IO ()
ByteArrayAccess)

instance NFData ScrubbedBytes32 where
  rnf :: ScrubbedBytes32 -> ()
rnf (MkScrubbedBytes32 SizedByteArray 32 ScrubbedBytes
bs) = ScrubbedBytes -> ()
forall a. NFData a => a -> ()
rnf (SizedByteArray 32 ScrubbedBytes -> ScrubbedBytes
forall (n :: Nat) ba. SizedByteArray n ba -> ba
unSizedByteArray SizedByteArray 32 ScrubbedBytes
bs)

instance ByteArrayN 32 ScrubbedBytes32 where
  allocRet :: forall p a. Proxy 32 -> (Ptr p -> IO a) -> IO (a, ScrubbedBytes32)
allocRet Proxy 32
p Ptr p -> IO a
f = do
    (a
a, SizedByteArray 32 ScrubbedBytes
ba) <- Proxy 32
-> (Ptr p -> IO a) -> IO (a, SizedByteArray 32 ScrubbedBytes)
forall (n :: Nat) c p a.
ByteArrayN n c =>
Proxy n -> (Ptr p -> IO a) -> IO (a, c)
forall p a.
Proxy 32
-> (Ptr p -> IO a) -> IO (a, SizedByteArray 32 ScrubbedBytes)
allocRet Proxy 32
p Ptr p -> IO a
f
    (a, ScrubbedBytes32) -> IO (a, ScrubbedBytes32)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a, SizedByteArray 32 ScrubbedBytes -> ScrubbedBytes32
MkScrubbedBytes32 SizedByteArray 32 ScrubbedBytes
ba)

pattern ScrubbedBytes32 :: ScrubbedBytes -> ScrubbedBytes32
pattern $mScrubbedBytes32 :: forall {r}.
ScrubbedBytes32 -> (ScrubbedBytes -> r) -> ((# #) -> r) -> r
ScrubbedBytes32 bs <- (unSizedByteArray . unScrubbedBytes32 -> bs)

{-# COMPLETE ScrubbedBytes32 #-}

-- | Construct a 32-byte (256-bit) 'ScrubbedBytes' value from an array of
-- bytes.
mkScrubbedBytes32 :: ByteArrayAccess b => b -> Maybe ScrubbedBytes32
mkScrubbedBytes32 :: forall b. ByteArrayAccess b => b -> Maybe ScrubbedBytes32
mkScrubbedBytes32 = (SizedByteArray 32 ScrubbedBytes -> ScrubbedBytes32
MkScrubbedBytes32 (SizedByteArray 32 ScrubbedBytes -> ScrubbedBytes32)
-> Maybe (SizedByteArray 32 ScrubbedBytes) -> Maybe ScrubbedBytes32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (Maybe (SizedByteArray 32 ScrubbedBytes) -> Maybe ScrubbedBytes32)
-> (b -> Maybe (SizedByteArray 32 ScrubbedBytes))
-> b
-> Maybe ScrubbedBytes32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScrubbedBytes -> Maybe (SizedByteArray 32 ScrubbedBytes)
forall (n :: Nat) ba.
(KnownNat n, ByteArrayAccess ba) =>
ba -> Maybe (SizedByteArray n ba)
sizedByteArray (ScrubbedBytes -> Maybe (SizedByteArray 32 ScrubbedBytes))
-> (b -> ScrubbedBytes)
-> b
-> Maybe (SizedByteArray 32 ScrubbedBytes)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> ScrubbedBytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
BA.convert

-- | Construct a 'ScrubbedBytes32' value from a 'SizedByteArray' of
-- 'ScrubbedBytes'.
fromSizedBytes :: SizedByteArray 32 ScrubbedBytes -> ScrubbedBytes32
fromSizedBytes :: SizedByteArray 32 ScrubbedBytes -> ScrubbedBytes32
fromSizedBytes SizedByteArray 32 ScrubbedBytes
bs = SizedByteArray 32 ScrubbedBytes -> ScrubbedBytes32
MkScrubbedBytes32 SizedByteArray 32 ScrubbedBytes
bs

-- | Convert a 'ScrubbedBytes32' value to 'ScrubbedBytes'.
toBytes :: ScrubbedBytes32 -> ScrubbedBytes
toBytes :: ScrubbedBytes32 -> ScrubbedBytes
toBytes (ScrubbedBytes32 ScrubbedBytes
bs) = ScrubbedBytes
bs

-- | Convert a 'ScrubbedBytes32' value to a 'SizedByteArray' of
-- 'ScrubbedBytes'.
toSizedBytes :: ScrubbedBytes32 -> SizedByteArray 32 ScrubbedBytes
toSizedBytes :: ScrubbedBytes32 -> SizedByteArray 32 ScrubbedBytes
toSizedBytes (MkScrubbedBytes32 SizedByteArray 32 ScrubbedBytes
bs) = SizedByteArray 32 ScrubbedBytes
bs

-- | Randomly generate a 'ScrubbedBytes32' value.
generateScrubbedBytes32 :: IO ScrubbedBytes32
generateScrubbedBytes32 :: IO ScrubbedBytes32
generateScrubbedBytes32 = do
  ScrubbedBytes
bs <- Int -> IO ScrubbedBytes
forall byteArray. ByteArray byteArray => Int -> IO byteArray
forall (m :: * -> *) byteArray.
(MonadRandom m, ByteArray byteArray) =>
Int -> m byteArray
Crypto.getRandomBytes Int
32 :: IO ScrubbedBytes
  case ScrubbedBytes -> Maybe ScrubbedBytes32
forall b. ByteArrayAccess b => b -> Maybe ScrubbedBytes32
mkScrubbedBytes32 ScrubbedBytes
bs of
    Just ScrubbedBytes32
x -> ScrubbedBytes32 -> IO ScrubbedBytes32
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ScrubbedBytes32
x
    Maybe ScrubbedBytes32
Nothing -> String -> IO ScrubbedBytes32
forall a. HasCallStack => String -> a
error String
"generateScrubbedBytes32: impossible: failed to randomly generate 32 bytes"