crypto-rng-effectful (empty) → 1.0.0.0
raw patch · 9 files changed
+269/−0 lines, 9 filesdep +basedep +bytestringdep +crypto-rng
Dependencies added: base, bytestring, crypto-rng, crypto-rng-effectful, effectful-core, random, tasty, tasty-hunit
Files
- CHANGELOG.md +2/−0
- LICENSE +20/−0
- README.md +9/−0
- crypto-rng-effectful.cabal +88/−0
- src/Effectful/Crypto/RNG.hs +29/−0
- src/Effectful/Crypto/RNG/Effect.hs +22/−0
- src/Effectful/Crypto/RNG/Unsafe.hs +30/−0
- tests/Main.hs +45/−0
- tests/Utils.hs +24/−0
+ CHANGELOG.md view
@@ -0,0 +1,2 @@+# crypto-rng-effectful-1.0.0.0 (2022-07-16)+* Initial release.
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2021 Hécate Moonlight++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,9 @@+# crypto-rng-effectful++[](https://github.com/haskell-effectful/crypto-rng-effectful/actions?query=branch%3Amaster)+[](https://hackage.haskell.org/package/crypto-rng-effectful)+[](https://packdeps.haskellers.com/feed?needle=andrzej@rybczak.net)+[](https://www.stackage.org/lts/package/resource-teffectful)+[](https://www.stackage.org/nightly/package/crypto-rng-effectful)++Adaptation of the [crypto-rng](https://hackage.haskell.org/package/crypto-rng) library for the [effectful](https://hackage.haskell.org/package/effectful) ecosystem.
+ crypto-rng-effectful.cabal view
@@ -0,0 +1,88 @@+cabal-version: 2.4+build-type: Simple+name: crypto-rng-effectful+version: 1.0.0.0+license: MIT+license-file: LICENSE+category: Crypto+maintainer: andrzej@rybczak.net+author: Andrzej Rybczak, Dominik Peteler, Hécate Moonlight++synopsis: Adaptation of the crypto-rng library for the effectful ecosystem.++description: Adaptation of the @<https://hackage.haskell.org/package/crypto-rng crypto-rng>@ library for the @<https://hackage.haskell.org/package/effectful effectful>@ ecosystem.++extra-source-files:+ CHANGELOG.md+ README.md++tested-with: GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.3 || ==9.4.1++bug-reports: https://github.com/haskell-effectful/crypto-rng-effectful/issues+source-repository head+ type: git+ location: https://github.com/haskell-effectful/crypto-rng-effectful++common language+ ghc-options: -Wall -Wcompat -Wno-unticked-promoted-constructors++ default-language: Haskell2010++ default-extensions: BangPatterns+ ConstraintKinds+ DataKinds+ DeriveFunctor+ DeriveGeneric+ DerivingStrategies+ FlexibleContexts+ FlexibleInstances+ GADTs+ GeneralizedNewtypeDeriving+ LambdaCase+ MultiParamTypeClasses+ NoStarIsType+ RankNTypes+ RoleAnnotations+ ScopedTypeVariables+ StandaloneDeriving+ TupleSections+ TypeApplications+ TypeFamilies+ TypeOperators++library+ import: language++ build-depends: base >= 4.13 && < 5+ , bytestring >= 0.10.8+ , crypto-rng >= 0.3 && < 0.4+ , effectful-core >= 1.0.0.0 && < 1.0.1.0+ , random >= 1.1 && < 1.3++ hs-source-dirs: src++ exposed-modules: Effectful.Crypto.RNG+ Effectful.Crypto.RNG.Unsafe++ other-modules: Effectful.Crypto.RNG.Effect+++test-suite test+ import: language++ ghc-options: -threaded -rtsopts -with-rtsopts=-N4++ build-depends: base+ , bytestring+ , crypto-rng+ , effectful-core+ , crypto-rng-effectful+ , tasty+ , tasty-hunit++ hs-source-dirs: tests++ type: exitcode-stdio-1.0+ main-is: Main.hs++ other-modules: Utils
+ src/Effectful/Crypto/RNG.hs view
@@ -0,0 +1,29 @@+-- | Generation of random numbers via "Crypto.RNG".+module Effectful.Crypto.RNG+ ( -- * Effect+ RNG(..)+ , CryptoRNG(..)++ -- ** Handlers+ , runCryptoRNG++ -- * Instantiation of the initial RNG state+ , CryptoRNGState+ , newCryptoRNGState+ , newCryptoRNGStateSized+ ) where++import Control.Monad.IO.Class+import Crypto.RNG+import Effectful+import Effectful.Dispatch.Dynamic+import qualified System.Random.Stateful as R++import Effectful.Crypto.RNG.Effect++-- | Generate cryptographically secure random numbers.+runCryptoRNG :: IOE :> es => CryptoRNGState -> Eff (RNG : es) a -> Eff es a+runCryptoRNG rng = interpret $ \_ -> \case+ RandomBytes n -> liftIO $ randomBytesIO n rng+ Random -> liftIO $ R.uniformM rng+ RandomR bounds -> liftIO $ R.uniformRM bounds rng
+ src/Effectful/Crypto/RNG/Effect.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -Wno-orphans #-}+module Effectful.Crypto.RNG.Effect where++import Data.ByteString (ByteString)+import Effectful+import Effectful.Dispatch.Dynamic+import System.Random+import Crypto.RNG.Class++-- | Provide the ability to generate random numbers.+data RNG :: Effect where+ RandomBytes :: Int -> RNG m ByteString+ Random :: Uniform a => RNG m a+ RandomR :: UniformRange a => (a, a) -> RNG m a++type instance DispatchOf RNG = 'Dynamic++instance RNG :> es => CryptoRNG (Eff es) where+ randomBytes = send . RandomBytes+ random = send Random+ randomR = send . RandomR
+ src/Effectful/Crypto/RNG/Unsafe.hs view
@@ -0,0 +1,30 @@+-- | Generation of random numbers via "Crypto.RNG.Unsafe".+module Effectful.Crypto.RNG.Unsafe+ ( -- * Effect+ RNG(..)+ , CryptoRNG(..)++ -- ** Handlers+ , runRNG++ -- * Instantiation of the initial RNG state+ , RNGState+ , newRNGState+ ) where++import Crypto.RNG.Unsafe+import Effectful+import Effectful.Dispatch.Dynamic+import qualified System.Random as R++import Effectful.Crypto.RNG.Effect++-- | Generate random numbers, starting with a given initial 'RNGState'.+--+-- /Note:/ random numbers generated by this interpreter are not+-- cryptographically secure and should only be used for testing purposes.+runRNG :: IOE :> es => RNGState -> Eff (RNG : es) a -> Eff es a+runRNG rng = interpret $ \_ -> \case+ RandomBytes n -> withRNG rng $ \g -> R.genByteString n g+ Random -> withRNG rng $ \g -> R.uniform g+ RandomR bounds -> withRNG rng $ \g -> R.uniformR bounds g
+ tests/Main.hs view
@@ -0,0 +1,45 @@+module Main where++import Control.Monad+import Crypto.RNG+import Data.ByteString+import Effectful+import Effectful.Reader.Static+import Test.Tasty+import Test.Tasty.HUnit++import Effectful.Crypto.RNG++main :: IO ()+main = do+ defaultMain $ testGroup "Crypto-RNG Bindings"+ [ testCase "Genering random bytes wrapped in a newtype" testRandomBytes+ , testCase "Generating a random number within a range from Reader" testRandomNumber+ ]++testRandomNumber :: Assertion+testRandomNumber = runEff $ do+ cryptoState <- newCryptoRNGState+ void . runCryptoRNG cryptoState+ . runReader ((10, 20) :: (Int, Int))+ $ generatingRandomNumber++generatingRandomNumber :: (RNG :> es, Reader (Int, Int) :> es) => Eff es Int+generatingRandomNumber = do+ bounds <- ask+ randomR bounds++---++testRandomBytes :: Assertion+testRandomBytes = runEff $ do+ cryptoState <- newCryptoRNGState+ void $ runCryptoRNG cryptoState generateUID++newtype UID = UID ByteString+ deriving newtype (Show, Eq, Ord)++generateUID :: RNG :> es => Eff es UID+generateUID = do+ bytes <- randomBytes 8+ pure $ UID bytes
+ tests/Utils.hs view
@@ -0,0 +1,24 @@+module Utils+ ( assertBool+ , assertEqual+ , assertFailure+ ) where++import GHC.Stack+import qualified Test.Tasty.HUnit as T++import Effectful++assertBool :: (HasCallStack, IOE :> es) => String -> Bool -> Eff es ()+assertBool msg p = liftIO $ T.assertBool msg p++assertEqual+ :: (HasCallStack, Eq a, Show a, IOE :> es)+ => String+ -> a+ -> a+ -> Eff es ()+assertEqual msg expected given = liftIO $ T.assertEqual msg expected given++assertFailure :: (HasCallStack, IOE :> es) => String -> Eff es a+assertFailure msg = liftIO $ T.assertFailure msg