diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,2 @@
+# crypto-rng-effectful-1.0.0.0 (2022-07-16)
+* Initial release.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+# crypto-rng-effectful
+
+[![Build Status](https://github.com/haskell-effectful/crypto-rng-effectful/workflows/Haskell-CI/badge.svg?branch=master)](https://github.com/haskell-effectful/crypto-rng-effectful/actions?query=branch%3Amaster)
+[![Hackage](https://img.shields.io/hackage/v/crypto-rng-effectful.svg)](https://hackage.haskell.org/package/crypto-rng-effectful)
+[![Dependencies](https://img.shields.io/hackage-deps/v/crypto-rng-effectful.svg)](https://packdeps.haskellers.com/feed?needle=andrzej@rybczak.net)
+[![Stackage LTS](https://www.stackage.org/package/crypto-rng-effectful/badge/lts)](https://www.stackage.org/lts/package/resource-teffectful)
+[![Stackage Nightly](https://www.stackage.org/package/crypto-rng-effectful/badge/nightly)](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.
diff --git a/crypto-rng-effectful.cabal b/crypto-rng-effectful.cabal
new file mode 100644
--- /dev/null
+++ b/crypto-rng-effectful.cabal
@@ -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
diff --git a/src/Effectful/Crypto/RNG.hs b/src/Effectful/Crypto/RNG.hs
new file mode 100644
--- /dev/null
+++ b/src/Effectful/Crypto/RNG.hs
@@ -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
diff --git a/src/Effectful/Crypto/RNG/Effect.hs b/src/Effectful/Crypto/RNG/Effect.hs
new file mode 100644
--- /dev/null
+++ b/src/Effectful/Crypto/RNG/Effect.hs
@@ -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
diff --git a/src/Effectful/Crypto/RNG/Unsafe.hs b/src/Effectful/Crypto/RNG/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/Effectful/Crypto/RNG/Unsafe.hs
@@ -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
diff --git a/tests/Main.hs b/tests/Main.hs
new file mode 100644
--- /dev/null
+++ b/tests/Main.hs
@@ -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
diff --git a/tests/Utils.hs b/tests/Utils.hs
new file mode 100644
--- /dev/null
+++ b/tests/Utils.hs
@@ -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
