crypton 1.0.6 → 1.1.0
raw patch · 10 files changed
+158/−141 lines, 10 filesdep +base16dep +primitivedep +ramdep −basementdep −memoryPVP ok
version bump matches the API change (PVP)
Dependencies added: base16, primitive, ram, text
Dependencies removed: basement, memory
API changes (from Hackage documentation)
Files
- CHANGELOG.md +4/−0
- Crypto/Error/Types.hs +0/−5
- Crypto/Hash.hs +11/−19
- Crypto/Hash/IO.hs +5/−2
- Crypto/Hash/Types.hs +28/−21
- Crypto/Internal/ByteArray.hs +18/−1
- Crypto/KDF/BCryptPBKDF.hs +77/−84
- Crypto/MAC/KMAC.hs +3/−2
- Crypto/PubKey/ECDSA.hs +2/−1
- crypton.cabal +10/−6
CHANGELOG.md view
@@ -1,5 +1,9 @@ # CHANGELOG for crypton +## 1.0.7++ Stop depending on basement, use upstream dependencies instead++ Stop transitively depending on basement by depending on ram.+ ## 1.0.6 * Fix test failures on less common 64-bit arches.
Crypto/Error/Types.hs view
@@ -22,7 +22,6 @@ import qualified Control.Exception as E import Data.Data -import Basement.Monad (MonadFailure (..)) -- | Enumeration of all possible errors that can be found in this library data CryptoError@@ -86,10 +85,6 @@ case m1 of CryptoPassed a -> m2 a CryptoFailed e -> CryptoFailed e--instance MonadFailure CryptoFailable where- type Failure CryptoFailable = CryptoError- mFail = CryptoFailed -- | Throw an CryptoError as exception on CryptoFailed result, -- otherwise return the computed value
Crypto/Hash.hs view
@@ -47,18 +47,14 @@ module Crypto.Hash.Algorithms, ) where -import Basement.Block (Block, unsafeFreeze)-import Basement.Block.Mutable (copyFromPtr, new)-import Basement.Types.OffsetSize (CountOf (..)) import Crypto.Hash.Algorithms import Crypto.Hash.Types-import Crypto.Internal.ByteArray (ByteArrayAccess)+import Crypto.Internal.ByteArray (ByteArrayAccess, allocAndFreezePrim) import qualified Crypto.Internal.ByteArray as B-import Crypto.Internal.Compat (unsafeDoIO) import qualified Data.ByteString.Lazy as L import Data.Int (Int32)-import Data.Word (Word8)-import Foreign.Ptr (Ptr, plusPtr)+import qualified Foreign.Marshal.Utils as FMU+import Foreign.Ptr (Ptr, castPtr, plusPtr) -- | Hash a strict bytestring into a digest. hash :: (ByteArrayAccess ba, HashAlgorithm a) => ba -> Digest a@@ -117,8 +113,8 @@ . HashAlgorithm a => Context a -> Digest a-hashFinalize !c =- Digest $ B.allocAndFreeze (hashDigestSize (undefined :: a)) $ \(dig :: Ptr (Digest a)) -> do+hashFinalize !c = Digest $ allocAndFreezePrim (hashDigestSize (undefined :: a)) $+ \(dig :: Ptr (Digest a)) -> do ((!_) :: B.Bytes) <- B.copy c $ \(ctx :: Ptr (Context a)) -> hashInternalFinalize ctx dig return () @@ -135,8 +131,8 @@ -> ba -> Int -> Digest a-hashFinalizePrefix !c b len =- Digest $ B.allocAndFreeze (hashDigestSize (undefined :: a)) $ \(dig :: Ptr (Digest a)) -> do+hashFinalizePrefix !c b len = Digest $ allocAndFreezePrim (hashDigestSize (undefined :: a)) $+ \(dig :: Ptr (Digest a)) -> do ((!_) :: B.Bytes) <- B.copy c $ \(ctx :: Ptr (Context a)) -> B.withByteArray b $ \d -> hashInternalFinalizePrefix@@ -171,13 +167,9 @@ from :: a -> ba -> Maybe (Digest a) from alg bs | B.length bs == (hashDigestSize alg) =- Just $ Digest $ unsafeDoIO $ copyBytes bs+ Just $ Digest $ copyByteArray bs | otherwise = Nothing - copyBytes :: ba -> IO (Block Word8)- copyBytes ba = do- muArray <- new count- B.withByteArray ba $ \ptr -> copyFromPtr ptr muArray 0 count- unsafeFreeze muArray- where- count = CountOf (B.length ba)+ copyByteArray ba = allocAndFreezePrim (B.length ba) $ \dst ->+ B.withByteArray ba $ \src ->+ FMU.copyBytes dst (castPtr src) (B.length ba)
Crypto/Hash/IO.hs view
@@ -20,6 +20,7 @@ ) where import Crypto.Hash.Types+import Crypto.Internal.ByteArray (allocAndFreezePrimIO) import qualified Crypto.Internal.ByteArray as B import Foreign.Ptr @@ -66,8 +67,10 @@ hashMutableFinalize :: forall a. HashAlgorithm a => MutableContext a -> IO (Digest a) hashMutableFinalize mc = do- b <- B.alloc (hashDigestSize (undefined :: a)) $ \dig -> B.withByteArray mc $ \(ctx :: Ptr (Context a)) -> hashInternalFinalize ctx dig- return $ Digest b+ ba <- allocAndFreezePrimIO (hashDigestSize (undefined :: a)) $+ \(dig :: Ptr (Digest a)) ->+ B.withByteArray mc $ \(ctx :: Ptr (Context a)) -> hashInternalFinalize ctx dig+ return (Digest ba) -- | Reset the mutable context to the initial state of the hash hashMutableReset :: HashAlgorithm a => MutableContext a -> IO ()
Crypto/Hash/Types.hs view
@@ -20,18 +20,21 @@ Digest (..), ) where -import Basement.Block (Block, unsafeFreeze)-import Basement.Block.Mutable (MutableBlock, new, unsafeWrite)-import Basement.NormalForm (deepseq)-import Basement.Types.OffsetSize (CountOf (..), Offset (..))+import Data.Primitive.ByteArray (ByteArray, MutableByteArray, writeByteArray, newPinnedByteArray, sizeofByteArray, unsafeFreezeByteArray, withByteArrayContents)+import Control.Monad.Primitive (PrimMonad (..))+import Control.DeepSeq (deepseq) import Control.Monad.ST-import Crypto.Internal.ByteArray (ByteArrayAccess, Bytes)+import Crypto.Internal.ByteArray (ByteArrayAccess (..), Bytes) import qualified Crypto.Internal.ByteArray as B import Crypto.Internal.Imports import Data.Char (digitToInt, isHexDigit) import Data.Data (Data)-import Foreign.Ptr (Ptr)+import Foreign.Ptr (Ptr, castPtr) import GHC.TypeLits (Nat)+import Data.Base16.Types (extractBase16)+import Data.ByteString (ByteString)+import Data.ByteString.Base16 (encodeBase16)+import qualified Data.Text as Text -- | Class representing hashing algorithms. --@@ -104,34 +107,38 @@ -- -- Creating a digest from a bytearray is also possible with function -- 'Crypto.Hash.digestFromByteString'.-newtype Digest a = Digest (Block Word8)- deriving (Eq, Ord, ByteArrayAccess, Data)+newtype Digest a = Digest ByteArray+ deriving (Eq, Ord, Data) type role Digest nominal instance NFData (Digest a) where rnf (Digest u) = u `deepseq` () +instance ByteArrayAccess (Digest a) where+ length (Digest ba) = sizeofByteArray ba+ withByteArray (Digest ba) f = withByteArrayContents ba (f . castPtr)+ instance Show (Digest a) where- show (Digest bs) =- map (toEnum . fromIntegral) $- B.unpack (B.convertToBase B.Base16 bs :: Bytes)+ show d =+ Text.unpack (extractBase16 $ encodeBase16 (B.convert d :: ByteString)) instance HashAlgorithm a => Read (Digest a) where readsPrec _ str = runST $ do- mut <- new (CountOf len)- loop mut len str+ mut <- newPinnedByteArray len+ loop len mut len str where len = hashDigestSize (undefined :: a) - loop :: MutableBlock Word8 s -> Int -> String -> ST s [(Digest a, String)]- loop mut 0 cs = (\b -> [(Digest b, cs)]) <$> unsafeFreeze mut- loop _ _ [] = return []- loop _ _ [_] = return []- loop mut n (c : (d : ds))+loop :: Int -> MutableByteArray (PrimState (ST s)) -> Int -> String -> ST s [(Digest a, String)]+loop _ mut 0 cs = (\b -> [(Digest b, cs)]) <$> unsafeFreezeByteArray mut+loop _ _ _ [] = return []+loop _ _ _ [_] = return []+loop len mut n (c : (d : ds)) | not (isHexDigit c) = return [] | not (isHexDigit d) = return [] | otherwise = do- let w8 = fromIntegral $ digitToInt c * 16 + digitToInt d- unsafeWrite mut (Offset $ len - n) w8- loop mut (n - 1) ds+ let w8 :: Word8+ w8 = fromIntegral $ digitToInt c * 16 + digitToInt d+ writeByteArray mut (len - n) w8+ loop len mut (n - 1) ds
Crypto/Internal/ByteArray.hs view
@@ -14,6 +14,8 @@ module Data.ByteArray.Mapping, module Data.ByteArray.Encoding, constAllZero,+ allocAndFreezePrimIO,+ allocAndFreezePrim, ) where import Data.ByteArray@@ -22,10 +24,25 @@ import Data.Bits ((.|.)) import Data.Word (Word8)-import Foreign.Ptr (Ptr)+import Foreign.Ptr (Ptr, castPtr) import Foreign.Storable (peekByteOff)+import qualified Data.Primitive.ByteArray as Prim import Crypto.Internal.Compat (unsafeDoIO)++-- | Allocate a pinned 'Prim.ByteArray' of the given size, populate it via a+-- 'Ptr', then freeze and return it. The pointer must not be retained after+-- the action returns.+allocAndFreezePrimIO :: Int -> (Ptr p -> IO ()) -> IO Prim.ByteArray+allocAndFreezePrimIO n f = do+ mba <- Prim.newPinnedByteArray n+ f (castPtr (Prim.mutableByteArrayContents mba))+ Prim.unsafeFreezeByteArray mba++-- | The allocation is strictly local,+-- the computation is deterministic, and no IO effects escape.+allocAndFreezePrim :: Int -> (Ptr p -> IO ()) -> Prim.ByteArray+allocAndFreezePrim n = unsafeDoIO . allocAndFreezePrimIO n constAllZero :: ByteArrayAccess ba => ba -> Bool constAllZero b = unsafeDoIO $ withByteArray b $ \p -> loop p 0 0
Crypto/KDF/BCryptPBKDF.hs view
@@ -13,11 +13,6 @@ ) where -import Basement.Block (MutableBlock)-import qualified Basement.Block as Block-import qualified Basement.Block.Mutable as Block-import Basement.Monad (PrimState)-import Basement.Types.OffsetSize (CountOf (..), Offset (..)) import Control.Exception (finally) import Control.Monad (when) import qualified Crypto.Cipher.Blowfish.Box as Blowfish@@ -34,9 +29,11 @@ import Crypto.Internal.Compat (unsafeDoIO) import Data.Bits import qualified Data.ByteArray as B+import qualified Data.ByteString.Internal as BSI import Data.Foldable (forM_) import Data.Memory.PtrMethods (memCopy, memSet, memXor) import Data.Word+import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrBytes, withForeignPtr) import Foreign.Ptr (Ptr, castPtr) import Foreign.Storable (peekByteOff, pokeByteOff) @@ -76,70 +73,70 @@ deriveKey :: Ptr Word8 -> IO () deriveKey keyPtr = do- -- Allocate all necessary memory. The algorihm shall not allocate- -- any more dynamic memory after this point. Blocks need to be pinned- -- as pointers to them are passed to the SHA512 implementation.- ksClean <- Blowfish.createKeySchedule- ksDirty <- Blowfish.createKeySchedule- ctxMBlock <- Block.newPinned (CountOf ctxLen :: CountOf Word8)- outMBlock <- Block.newPinned (CountOf outLen :: CountOf Word8)- tmpMBlock <- Block.newPinned (CountOf tmpLen :: CountOf Word8)- blkMBlock <- Block.newPinned (CountOf blkLen :: CountOf Word8)- passHashMBlock <- Block.newPinned (CountOf hashLen :: CountOf Word8)- saltHashMBlock <- Block.newPinned (CountOf hashLen :: CountOf Word8)+ -- Allocate all necessary memory. The algorithm shall not allocate+ -- any more dynamic memory after this point. ForeignPtrs allocate+ -- pinned memory, so raw pointers to them are stable.+ ksClean <- Blowfish.createKeySchedule+ ksDirty <- Blowfish.createKeySchedule+ ctxFP <- mallocForeignPtrBytes ctxLen :: IO (ForeignPtr Word8)+ outFP <- mallocForeignPtrBytes outLen :: IO (ForeignPtr Word8)+ tmpFP <- mallocForeignPtrBytes tmpLen :: IO (ForeignPtr Word8)+ blkFP <- mallocForeignPtrBytes blkLen :: IO (ForeignPtr Word8)+ passHashFP <- mallocForeignPtrBytes hashLen :: IO (ForeignPtr Word8)+ saltHashFP <- mallocForeignPtrBytes hashLen :: IO (ForeignPtr Word8) -- Finally erase all memory areas that contain information from -- which the derived key could be reconstructed.- -- As all MutableBlocks are pinned it shall be guaranteed that- -- no temporary trampoline buffers are allocated.- finallyErase outMBlock $- finallyErase passHashMBlock $+ finallyErase outFP outLen $+ finallyErase passHashFP hashLen $ B.withByteArray pass $ \passPtr -> B.withByteArray salt $ \saltPtr ->- Block.withMutablePtr ctxMBlock $ \ctxPtr ->- Block.withMutablePtr outMBlock $ \outPtr ->- Block.withMutablePtr tmpMBlock $ \tmpPtr ->- Block.withMutablePtr blkMBlock $ \blkPtr ->- Block.withMutablePtr passHashMBlock $ \passHashPtr ->- Block.withMutablePtr saltHashMBlock $ \saltHashPtr -> do- -- Hash the password.- let shaPtr = castPtr ctxPtr :: Ptr (Context SHA512)- hashInternalInit shaPtr- hashInternalUpdate shaPtr passPtr (fromIntegral passLen)- hashInternalFinalize shaPtr (castPtr passHashPtr)- passHashBlock <- Block.unsafeFreeze passHashMBlock- forM_ [1 .. blocks] $ \block -> do- -- Poke the increased block counter.- Block.unsafeWrite blkMBlock 0 (fromIntegral $ block `shiftR` 24)- Block.unsafeWrite blkMBlock 1 (fromIntegral $ block `shiftR` 16)- Block.unsafeWrite blkMBlock 2 (fromIntegral $ block `shiftR` 8)- Block.unsafeWrite blkMBlock 3 (fromIntegral $ block `shiftR` 0)- -- First round (slightly different).- hashInternalInit shaPtr- hashInternalUpdate shaPtr saltPtr (fromIntegral saltLen)- hashInternalUpdate shaPtr blkPtr (fromIntegral blkLen)- hashInternalFinalize shaPtr (castPtr saltHashPtr)- Block.unsafeFreeze saltHashMBlock >>= \x -> do- Blowfish.copyKeySchedule ksDirty ksClean- hashInternalMutable ksDirty passHashBlock x tmpMBlock- memCopy outPtr tmpPtr outLen- -- Remaining rounds.- forM_ [2 .. iterCounts params] $ const $ do- hashInternalInit shaPtr- hashInternalUpdate shaPtr tmpPtr (fromIntegral tmpLen)- hashInternalFinalize shaPtr (castPtr saltHashPtr)- Block.unsafeFreeze saltHashMBlock >>= \x -> do- Blowfish.copyKeySchedule ksDirty ksClean- hashInternalMutable ksDirty passHashBlock x tmpMBlock- memXor outPtr outPtr tmpPtr outLen- -- Spread the current out buffer evenly over the key buffer.- -- After both loops have run every byte of the key buffer- -- will have been written to exactly once and every byte- -- of the output will have been used.- forM_ [0 .. outLen - 1] $ \outIdx -> do- let keyIdx = outIdx * blocks + block - 1- when (keyIdx < keyLen) $ do- w8 <- peekByteOff outPtr outIdx :: IO Word8- pokeByteOff keyPtr keyIdx w8+ withForeignPtr ctxFP $ \ctxPtr' ->+ withForeignPtr outFP $ \outPtr ->+ withForeignPtr tmpFP $ \tmpPtr ->+ withForeignPtr blkFP $ \blkPtr ->+ withForeignPtr passHashFP $ \passHashPtr ->+ withForeignPtr saltHashFP $ \saltHashPtr -> do+ -- Hash the password.+ let shaPtr = castPtr ctxPtr' :: Ptr (Context SHA512)+ hashInternalInit shaPtr+ hashInternalUpdate shaPtr passPtr (fromIntegral passLen)+ hashInternalFinalize shaPtr (castPtr passHashPtr)+ -- Create a stable ByteString view of the password hash+ -- (passHashFP is not modified after this point).+ let passHashBS = BSI.fromForeignPtr passHashFP 0 hashLen+ forM_ [1 .. blocks] $ \block -> do+ -- Poke the increased block counter.+ pokeByteOff blkPtr 0 (fromIntegral (block `shiftR` 24) :: Word8)+ pokeByteOff blkPtr 1 (fromIntegral (block `shiftR` 16) :: Word8)+ pokeByteOff blkPtr 2 (fromIntegral (block `shiftR` 8) :: Word8)+ pokeByteOff blkPtr 3 (fromIntegral (block `shiftR` 0 :: Int) :: Word8)+ -- First round (slightly different).+ hashInternalInit shaPtr+ hashInternalUpdate shaPtr saltPtr (fromIntegral saltLen)+ hashInternalUpdate shaPtr blkPtr (fromIntegral blkLen)+ hashInternalFinalize shaPtr (castPtr saltHashPtr)+ let saltHashBS = BSI.fromForeignPtr saltHashFP 0 hashLen+ Blowfish.copyKeySchedule ksDirty ksClean+ hashInternalMutable ksDirty passHashBS saltHashBS tmpPtr+ memCopy outPtr tmpPtr outLen+ -- Remaining rounds.+ forM_ [2 .. iterCounts params] $ const $ do+ hashInternalInit shaPtr+ hashInternalUpdate shaPtr tmpPtr (fromIntegral tmpLen)+ hashInternalFinalize shaPtr (castPtr saltHashPtr)+ let saltHashBS2 = BSI.fromForeignPtr saltHashFP 0 hashLen+ Blowfish.copyKeySchedule ksDirty ksClean+ hashInternalMutable ksDirty passHashBS saltHashBS2 tmpPtr+ memXor outPtr outPtr tmpPtr outLen+ -- Spread the current out buffer evenly over the key buffer.+ -- After both loops have run every byte of the key buffer+ -- will have been written to exactly once and every byte+ -- of the output will have been used.+ forM_ [0 .. outLen - 1] $ \outIdx -> do+ let keyIdx = outIdx * blocks + block - 1+ when (keyIdx < keyLen) $ do+ w8 <- peekByteOff outPtr outIdx :: IO Word8+ pokeByteOff keyPtr keyIdx w8 -- | Internal hash function used by `generate`. --@@ -154,18 +151,16 @@ | B.length saltHash /= 64 = error "saltHash must be 512 bits" | otherwise = unsafeDoIO $ do ks0 <- Blowfish.createKeySchedule- outMBlock <- Block.newPinned 32- hashInternalMutable ks0 passHash saltHash outMBlock- B.convert `fmap` Block.freeze outMBlock+ B.alloc 32 $ \outPtr -> hashInternalMutable ks0 passHash saltHash outPtr hashInternalMutable :: (B.ByteArrayAccess pass, B.ByteArrayAccess salt) => Blowfish.KeySchedule -> pass -> salt- -> MutableBlock Word8 (PrimState IO)+ -> Ptr Word8 -> IO ()-hashInternalMutable bfks passHash saltHash outMBlock = do+hashInternalMutable bfks passHash saltHash outPtr = do Blowfish.expandKeyWithSalt bfks passHash saltHash forM_ [0 .. 63 :: Int] $ const $ do Blowfish.expandKey bfks saltHash@@ -176,22 +171,20 @@ store 16 =<< cipher 64 0x6669736853776174 store 24 =<< cipher 64 0x44796e616d697465 where- store :: Offset Word8 -> Word64 -> IO ()+ store :: Int -> Word64 -> IO () store o w64 = do- Block.unsafeWrite outMBlock (o + 0) (fromIntegral $ w64 `shiftR` 32)- Block.unsafeWrite outMBlock (o + 1) (fromIntegral $ w64 `shiftR` 40)- Block.unsafeWrite outMBlock (o + 2) (fromIntegral $ w64 `shiftR` 48)- Block.unsafeWrite outMBlock (o + 3) (fromIntegral $ w64 `shiftR` 56)- Block.unsafeWrite outMBlock (o + 4) (fromIntegral $ w64 `shiftR` 0)- Block.unsafeWrite outMBlock (o + 5) (fromIntegral $ w64 `shiftR` 8)- Block.unsafeWrite outMBlock (o + 6) (fromIntegral $ w64 `shiftR` 16)- Block.unsafeWrite outMBlock (o + 7) (fromIntegral $ w64 `shiftR` 24)+ pokeByteOff outPtr (o + 0) (fromIntegral (w64 `shiftR` 32) :: Word8)+ pokeByteOff outPtr (o + 1) (fromIntegral (w64 `shiftR` 40) :: Word8)+ pokeByteOff outPtr (o + 2) (fromIntegral (w64 `shiftR` 48) :: Word8)+ pokeByteOff outPtr (o + 3) (fromIntegral (w64 `shiftR` 56) :: Word8)+ pokeByteOff outPtr (o + 4) (fromIntegral (w64 `shiftR` 0) :: Word8)+ pokeByteOff outPtr (o + 5) (fromIntegral (w64 `shiftR` 8) :: Word8)+ pokeByteOff outPtr (o + 6) (fromIntegral (w64 `shiftR` 16) :: Word8)+ pokeByteOff outPtr (o + 7) (fromIntegral (w64 `shiftR` 24) :: Word8) cipher :: Int -> Word64 -> IO Word64 cipher 0 block = return block cipher i block = Blowfish.cipherBlockMutable bfks block >>= cipher (i - 1) -finallyErase :: MutableBlock Word8 (PrimState IO) -> IO () -> IO ()-finallyErase mblock action =- action `finally` Block.withMutablePtr mblock (\ptr -> memSet ptr 0 len)- where- CountOf len = Block.mutableLengthBytes mblock+finallyErase :: ForeignPtr Word8 -> Int -> IO () -> IO ()+finallyErase fp len action =+ action `finally` withForeignPtr fp (\ptr -> memSet ptr 0 len)
Crypto/MAC/KMAC.hs view
@@ -29,6 +29,7 @@ import Crypto.Hash.Types (Digest (..), HashAlgorithm (..)) import qualified Crypto.Hash.Types as H import Crypto.Internal.Builder+import Crypto.Internal.ByteArray (allocAndFreezePrim) import Crypto.Internal.Imports import Data.Bits (shiftR) import Data.ByteArray (ByteArrayAccess)@@ -69,8 +70,8 @@ :: forall a suffix . (HashSHAKE a, ByteArrayAccess suffix) => H.Context a -> suffix -> Digest a-cshakeFinalize !c s =- Digest $ B.allocAndFreeze (hashDigestSize (undefined :: a)) $ \dig -> do+cshakeFinalize !c s = Digest $ allocAndFreezePrim (hashDigestSize (undefined :: a)) $+ \(dig :: Ptr (Digest a)) -> do ((!_) :: B.Bytes) <- B.copy c $ \(ctx :: Ptr (H.Context a)) -> do B.withByteArray s $ \d -> hashInternalUpdate ctx d (fromIntegral $ B.length s)
Crypto/PubKey/ECDSA.hs view
@@ -261,8 +261,9 @@ tHashDigest :: (EllipticCurveECDSA curve, HashAlgorithm hash) => proxy curve -> Digest hash -> Scalar curve-tHashDigest prx (Digest digest) = throwCryptoError $ decodeScalar prx encoded+tHashDigest prx dig = throwCryptoError $ decodeScalar prx encoded where+ digest = B.convert dig :: B.Bytes m = curveOrderBits prx d = m - B.length digest * 8 (n, r) = m `divMod` 8
crypton.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.18 name: crypton-version: 1.0.6+version: 1.1.0 license: BSD3 license-file: LICENSE copyright: Vincent Hanquez <vincent@snarc.org> maintainer: Kazu Yamamoto <kazu@iij.ad.jp> author: Vincent Hanquez <vincent@snarc.org> stability: experimental-tested-with: GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.2+tested-with: GHC ==9.2.8 || ==9.4.8 || ==9.6.7 || ==9.8.4 || ==9.10.1 || ==9.12.1 homepage: https://github.com/kazu-yamamoto/crypton bug-reports: https://github.com/kazu-yamamoto/crypton/issues synopsis: Cryptography Primitives sink@@ -303,9 +303,13 @@ ghc-options: -Wall -fwarn-tabs -optc-O3 build-depends: base >=4.13 && <5- , basement >=0.0.6 , bytestring- , memory >=0.14.18+ , primitive >=0.9+ , deepseq+ , base16 >=1.0+ , bytestring+ , text+ , ram >=0.20.1 && < 0.22 if flag(old_toolchain_inliner) cc-options: -fgnu89-inline@@ -502,7 +506,7 @@ base >=4.13 && <5 , bytestring , crypton- , memory+ , ram , tasty , tasty-hunit , tasty-kat@@ -521,7 +525,7 @@ , crypton , deepseq , gauge- , memory+ , ram , random -- cabal-fmt: indent 4