{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Crypto.Nonce ( Nonce32 , generateNonce32 , zeros32 ) where import Crypto.Random import Data.ByteArray as BA import Data.ByteString as B import qualified Data.ByteString.Base64 as Base64 import Data.ByteString.Char8 as B8 import Data.Data import Data.Serialize import Data.Sized newtype Nonce32 = Nonce32 ByteString deriving (Eq, Ord, ByteArrayAccess, Data) bin2base64 :: ByteArrayAccess bs => bs -> String bin2base64 = B8.unpack . Base64.encode . BA.convert instance Show Nonce32 where showsPrec d nonce = mappend $ bin2base64 nonce instance Read Nonce32 where readsPrec _ str = either (const []) id $ do let (ds,ss) = Prelude.splitAt 43 str ss' <- case ss of '=':xs -> Right xs -- optional terminating '=' _ -> Right ss bs <- Base64.decode (B8.pack $ ds ++ ['=']) if B.length bs == 32 then Right [ (Nonce32 bs, ss') ] else Left "Truncated Nonce32 (expected 43 base64 digits)." instance Serialize Nonce32 where get = Nonce32 <$> getBytes 32 put (Nonce32 bs) = putByteString bs instance Sized Nonce32 where size = ConstSize 32 zeros32 :: Nonce32 zeros32 = Nonce32 $ BA.replicate 32 0 generateNonce32 :: MonadRandom m => m Nonce32 generateNonce32 = Nonce32 <$> getRandomBytes 32