diff --git a/Crypto/Cipher/ChaCha.hs b/Crypto/Cipher/ChaCha.hs index 3a0f0b6..5e85b7b 100644 --- a/Crypto/Cipher/ChaCha.hs +++ b/Crypto/Cipher/ChaCha.hs @@ -54,11 +54,13 @@ initialize nbRounds key nonce nonceLen = B.length nonce -- | Initialize simple ChaCha State -initializeSimple :: ByteArray seed +-- +-- The seed need to be at least 40 bytes long +initializeSimple :: ByteArrayAccess seed => seed -- ^ a 40 bytes long seed -> StateSimple initializeSimple seed - | sLen /= 40 = error "ChaCha Random: seed length should be 40 bytes" + | sLen < 40 = error "ChaCha Random: seed length should be 40 bytes" | otherwise = unsafeDoIO $ do stPtr <- B.alloc 64 $ \stPtr -> B.withByteArray seed $ \seedPtr -> diff --git a/Crypto/Error/Types.hs b/Crypto/Error/Types.hs index 8cce985..e2831bf 100644 --- a/Crypto/Error/Types.hs +++ b/Crypto/Error/Types.hs @@ -28,6 +28,7 @@ data CryptoError = -- symmetric cipher errors CryptoError_KeySizeInvalid | CryptoError_IvSizeInvalid + | CryptoError_SeedSizeInvalid | CryptoError_AEADModeNotSupported -- public key cryptography error | CryptoError_SecretKeySizeInvalid diff --git a/Crypto/Random.hs b/Crypto/Random.hs index abc08a4..37d4124 100644 --- a/Crypto/Random.hs +++ b/Crypto/Random.hs @@ -16,6 +16,7 @@ module Crypto.Random , seedNew , seedFromInteger , seedToInteger + , seedFromBinary -- * Deterministic Random class , getSystemDRG , drgNew @@ -29,10 +30,12 @@ module Crypto.Random , MonadPseudoRandom ) where +import Crypto.Error import Crypto.Random.Types import Crypto.Random.ChaChaDRG import Crypto.Random.SystemDRG import Data.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes) +import qualified Data.ByteArray as B import Crypto.Internal.Imports import qualified Crypto.Number.Serialize as Serialize @@ -56,6 +59,12 @@ seedToInteger (Seed b) = Serialize.os2ip b seedFromInteger :: Integer -> Seed seedFromInteger i = Seed $ Serialize.i2ospOf_ seedLength (i `mod` 2^(seedLength * 8)) +-- | Convert a binary to a seed +seedFromBinary :: ByteArrayAccess b => b -> CryptoFailable Seed +seedFromBinary b + | B.length b /= 40 = CryptoFailed (CryptoError_SeedSizeInvalid) + | otherwise = CryptoPassed $ Seed $ B.convert b + -- | Create a new DRG from system entropy drgNew :: MonadRandom randomly => randomly ChaChaDRG drgNew = drgNewSeed `fmap` seedNew diff --git a/Crypto/Random/ChaChaDRG.hs b/Crypto/Random/ChaChaDRG.hs index 4c6629d..e23a444 100644 --- a/Crypto/Random/ChaChaDRG.hs +++ b/Crypto/Random/ChaChaDRG.hs @@ -14,7 +14,7 @@ module Crypto.Random.ChaChaDRG import Crypto.Random.Types import Crypto.Internal.Imports -import Crypto.Internal.ByteArray (ByteArray, ScrubbedBytes) +import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes) import qualified Crypto.Internal.ByteArray as B import Foreign.Storable (pokeElemOff) @@ -29,7 +29,7 @@ newtype ChaChaDRG = ChaChaDRG C.StateSimple -- | Initialize a new ChaCha context with the number of rounds, -- the key and the nonce associated. -initialize :: ByteArray seed +initialize :: B.ByteArrayAccess seed => seed -- ^ 40 bytes of seed -> ChaChaDRG -- ^ the initial ChaCha state initialize seed = ChaChaDRG $ C.initializeSimple seed