packages feed

raaz 0.0.1 → 0.0.2

raw patch · 20 files changed

+594/−165 lines, 20 filesdep ~raaz

Dependency ranges changed: raaz

Files

Raaz.hs view
@@ -2,18 +2,18 @@ -- By importing this module you get a rather high-level access to the -- primitives provided by the library. module Raaz-       ( version-       , module Raaz.Cipher+       ( module Raaz.Cipher        , module Raaz.Core        , module Raaz.Hash+       , version        ) where  import           Data.Version  (Version) import qualified Paths_raaz as P -import Raaz.Core-import Raaz.Hash-import Raaz.Cipher+import           Raaz.Core+import           Raaz.Hash+import           Raaz.Cipher   -- | Raaz library version number.
Raaz/Cipher/AES/CBC/Implementation/CPortable.hs view
@@ -70,11 +70,11 @@ ------------------- 128-bit CBC Implementation ----------------  -- | Implementation of 128-bit AES in CBC mode using Portable C.-aes128cbcI :: Implementation (AES 128 CBC)+aes128cbcI :: Implementation (AES 128 'CBC) aes128cbcI = SomeCipherI cbc128CPortable  -- | 128-bit AES in CBC mode using Portable C.-cbc128CPortable :: CipherI (AES 128 CBC) M128 M128+cbc128CPortable :: CipherI (AES 128 'CBC) M128 M128 cbc128CPortable =   CipherI { cipherIName = "aes128cbc-cportable"           , cipherIDescription =@@ -84,14 +84,14 @@           }  -- | The encryption action.-cbc128Encrypt :: Pointer -> BLOCKS (AES 128 CBC) -> MT M128 ()+cbc128Encrypt :: Pointer -> BLOCKS (AES 128 'CBC) -> MT M128 () cbc128Encrypt buf nBlocks =   do eKeyPtr <- liftSubMT m128ekey getMemoryPointer      ivPtr   <- liftSubMT m128iv   getMemoryPointer      liftIO $ c_aes_cbc_e buf (fromEnum nBlocks) 10 eKeyPtr ivPtr  -- | The decryption action.-cbc128Decrypt :: Pointer -> BLOCKS (AES 128 CBC) -> MT M128 ()+cbc128Decrypt :: Pointer -> BLOCKS (AES 128 'CBC) -> MT M128 () cbc128Decrypt buf nBlocks =   do eKeyPtr <- liftSubMT m128ekey getMemoryPointer      ivPtr   <- liftSubMT m128iv   getMemoryPointer@@ -102,11 +102,11 @@ ------------------- 192-bit CBC Implementation ----------------  -- | Implementation of 192-bit AES in CBC mode using Portable C.-aes192cbcI :: Implementation (AES 192 CBC)+aes192cbcI :: Implementation (AES 192 'CBC) aes192cbcI = SomeCipherI cbc192CPortable  -- | 192-bit AES in CBC mode using Portable C.-cbc192CPortable :: CipherI (AES 192 CBC) M192 M192+cbc192CPortable :: CipherI (AES 192 'CBC) M192 M192 cbc192CPortable =   CipherI { cipherIName = "aes192cbc-cportable"           , cipherIDescription =@@ -116,14 +116,14 @@           }  -- | The encryption action.-cbc192Encrypt :: Pointer -> BLOCKS (AES 192 CBC) -> MT M192 ()+cbc192Encrypt :: Pointer -> BLOCKS (AES 192 'CBC) -> MT M192 () cbc192Encrypt buf nBlocks =   do eKeyPtr <- liftSubMT m192ekey getMemoryPointer      ivPtr   <- liftSubMT m192iv   getMemoryPointer      liftIO $ c_aes_cbc_e buf (fromEnum nBlocks) 12 eKeyPtr ivPtr  -- | The decryption action.-cbc192Decrypt :: Pointer -> BLOCKS (AES 192 CBC) -> MT M192 ()+cbc192Decrypt :: Pointer -> BLOCKS (AES 192 'CBC) -> MT M192 () cbc192Decrypt buf nBlocks =   do eKeyPtr <- liftSubMT m192ekey getMemoryPointer      ivPtr   <- liftSubMT m192iv   getMemoryPointer@@ -132,11 +132,11 @@ ------------------- 256-bit CBC Implementation ----------------  -- | Implementation of 256-bit AES in CBC mode using Portable C.-aes256cbcI :: Implementation (AES 256 CBC)+aes256cbcI :: Implementation (AES 256 'CBC) aes256cbcI = SomeCipherI cbc256CPortable  -- | 256-bit AES in CBC mode using Portable C.-cbc256CPortable :: CipherI (AES 256 CBC) M256 M256+cbc256CPortable :: CipherI (AES 256 'CBC) M256 M256 cbc256CPortable =   CipherI { cipherIName = "aes256cbc-cportable"           , cipherIDescription =@@ -146,14 +146,14 @@           }  -- | The encryption action.-cbc256Encrypt :: Pointer -> BLOCKS (AES 256 CBC) -> MT M256 ()+cbc256Encrypt :: Pointer -> BLOCKS (AES 256 'CBC) -> MT M256 () cbc256Encrypt buf nBlocks =   do eKeyPtr <- liftSubMT m256ekey getMemoryPointer      ivPtr   <- liftSubMT m256iv   getMemoryPointer      liftIO $ c_aes_cbc_e buf (fromEnum nBlocks) 14 eKeyPtr ivPtr  -- | The decryption action.-cbc256Decrypt :: Pointer -> BLOCKS (AES 256 CBC) -> MT M256 ()+cbc256Decrypt :: Pointer -> BLOCKS (AES 256 'CBC) -> MT M256 () cbc256Decrypt buf nBlocks =   do eKeyPtr <- liftSubMT m256ekey getMemoryPointer      ivPtr   <- liftSubMT m256iv   getMemoryPointer
Raaz/Cipher/AES/Internal.hs view
@@ -102,59 +102,59 @@ ----------------- AES 128 CBC ------------------------------  -- | 128-bit aes cipher in `CBC` mode.-aes128cbc :: AES 128 CBC+aes128cbc :: AES 128 'CBC aes128cbc = AES  -- | The 128-bit aes cipher in cbc mode.-instance Primitive (AES 128 CBC) where+instance Primitive (AES 128 'CBC) where   blockSize _ = BYTES 16-  type Implementation (AES 128 CBC) = SomeCipherI (AES 128 CBC)+  type Implementation (AES 128 'CBC) = SomeCipherI (AES 128 'CBC)  -- | Key is @(`KEY128`,`IV`)@ pair.-instance Symmetric (AES 128 CBC) where-  type Key (AES 128 CBC) = (KEY128,IV)+instance Symmetric (AES 128 'CBC) where+  type Key (AES 128 'CBC) = (KEY128,IV) -instance Cipher (AES 128 CBC)+instance Cipher (AES 128 'CBC)  ----------------- AES 192 CBC --------------------------------  -- | 128-bit aes cipher in `CBC` mode.-aes192cbc :: AES 192 CBC+aes192cbc :: AES 192 'CBC aes192cbc = AES  -- | The 192-bit aes cipher in cbc mode.-instance Primitive (AES 192 CBC) where+instance Primitive (AES 192 'CBC) where   blockSize _ = BYTES 16-  type Implementation (AES 192 CBC) = SomeCipherI (AES 192 CBC)+  type Implementation (AES 192 'CBC) = SomeCipherI (AES 192 'CBC)  -- | Key is @(`KEY192`,`IV`)@ pair.-instance Symmetric (AES 192 CBC) where-  type Key (AES 192 CBC) = (KEY192,IV)+instance Symmetric (AES 192 'CBC) where+  type Key (AES 192 'CBC) = (KEY192,IV) -instance Cipher (AES 192 CBC)+instance Cipher (AES 192 'CBC)  ------------------- AES 256 CBC -----------------------------  -- | 128-bit aes cipher in `CBC` mode.-aes256cbc :: AES 256 CBC+aes256cbc :: AES 256 'CBC aes256cbc = AES  -- | The 256-bit aes cipher in cbc mode.-instance Primitive (AES 256 CBC) where+instance Primitive (AES 256 'CBC) where   blockSize _ = BYTES 16-  type Implementation (AES 256 CBC) = SomeCipherI (AES 256 CBC)+  type Implementation (AES 256 'CBC) = SomeCipherI (AES 256 'CBC)  -- | Key is @(`KEY256`,`IV`)@ pair.-instance Symmetric (AES 256 CBC) where-  type Key (AES 256 CBC) = (KEY256,IV)+instance Symmetric (AES 256 'CBC) where+  type Key (AES 256 'CBC) = (KEY256,IV) -instance Cipher (AES 256 CBC)+instance Cipher (AES 256 'CBC)   ------------------- AES CTR mode ---------------------------  -- | Smart constructors for AES 128 ctr.-aes128ctr :: AES 128 CTR+aes128ctr :: AES 128 'CTR aes128ctr = AES  --------------  Memory for storing extended keys ---------
Raaz/Core/ByteSource.hs view
@@ -2,10 +2,12 @@ {-# LANGUAGE DefaultSignatures #-} -- | Module define byte sources. module Raaz.Core.ByteSource-       ( ByteSource(..), fill, processChunks-       , InfiniteSource(..), slurp-       , PureByteSource+       ( -- * Byte sources.+         -- $bytesource$+         InfiniteSource(..)+       , ByteSource(..), PureByteSource        , FillResult(..)+       , fill, slurp, processChunks        , withFillResult        ) where @@ -26,6 +28,23 @@                                           ) import           Raaz.Core.Types.Pointer  (hFillBuf) +-- $bytesource$+--+-- Cryptographic input come from various sources; they can come from+-- network sockets or might be just a string in the Haskell. To give a+-- uniform interfaces for all such inputs, we define the abstract+-- concept of a /byte source/. Essentially a byte source is one from+-- which we can fill a buffer with bytes. Depending on the nature of+-- the source we have two classes: `ByteSource` which captures bounded+-- sources and `InfiniteSource` that captures never ending source of+-- bytes.+--+-- Among instances of `ByteSource`, some like for example+-- `B.ByteString` are /pure/ in the sense filling a buffer with bytes+-- from such a source has no other side-effects. This is in contrast+-- to a source like a sockets. The type class `PureByteSource`+-- captures such byte sources.+--  -- | This type captures the result of a fill operation. data FillResult a = Remaining a           -- ^ the buffer is filled completely@@ -77,6 +96,7 @@ fill = fillBytes . inBytes {-# INLINE fill #-} +-- | A version of slurp that takes type safe lengths as input. slurp :: ( LengthUnit len          , InfiniteSource src          )
Raaz/Core/Encode.hs view
@@ -1,40 +1,55 @@--- module Raaz.Core.Encode-       ( -- * The encodable type+       ( -- * Encoding of binary data.          -- $encodable$          Encodable(..)-       -- * Encoding formats-       -- $encodingformat$        , Format(..)-       , encode, decode, unsafeDecode-       -- ** The base 16 encoding fromat-       , Base16, fromBase16, showBase16+       , encode, decode, translate, unsafeDecode+       -- ** The base 16 encoding format+       , Base16+       , fromBase16, showBase16+       -- ** Other binary formats.+       , Base64        ) where  import Raaz.Core.Encode.Internal import Raaz.Core.Encode.Base16+import Raaz.Core.Encode.Base64  -- $encodable$ ----- Many types like cryptographic hashes, secret keys etc can be--- encoded into bytes. This module gives an interface to such objects--- using the `Encodable` type class. To ease their printing most types--- of this class have a `Show` instances. Similarly, to make it easy--- to defines constants of these types in source code, they often are--- instances of `Data.String.IsString`. Typically for cryptographic--- types like hashes, secret keys etc the `Show` and--- `Data.String.IsString` instances correspond to the base-16 encoding--- of these types.+-- Often one wants to represent cryptographic hashes, secret keys or+-- just binary data into various enocoding formats like base64,+-- hexadecimal etc. This module gives a generic interface for all such+-- operations. There are two main classes that capture the essence of+-- encoding.+--+-- [`Format`] Each encoding supported by this module is an instance of+--     this class. For printing and for easy inclusion in source code+--     appropriate instances of `Show` and `Data.String.IsString` is+--     provided for these types.+--+-- [`Encodable`] Instances of this class are those that can be encoded+--    into any of the available formats. Actual encoding and decoding+--    of elements of this class can be done by the combinators+--    `encode` and `decode`+--+-- The raaz library exposes many instances of `Format` which are all+-- some form of encoding of binary data.+-- +-- | Encode in a given format.+encode :: (Encodable a, Format fmt) => a -> fmt+encode = encodeByteString . toByteString +-- | Decode from a given format. It results in Nothing if there is a+-- parse error.+decode :: (Format fmt, Encodable a) => fmt -> Maybe a+decode = fromByteString . decodeFormat +-- | The unsafe version of `decode`.+unsafeDecode :: (Format fmt, Encodable a) => fmt -> a+unsafeDecode = unsafeFromByteString . decodeFormat --- $encodingformat$------ We also give facilities to encode any instance of `Encodable` into--- multiple formats. For type safety, encoding formats are--- distinguished by their types. All such formats have to be members--- of the `Format` type class and this allows encoding and decoding--- any type that is an instance of `Encodable` into any of the desired--- format.---+-- | Translate from one format to another.+translate :: (Format fmt1, Format fmt2) => fmt1 -> fmt2+translate = encodeByteString . decodeFormat
Raaz/Core/Encode/Base16.hs view
@@ -1,6 +1,9 @@ -- | Base 16 or hexadecimal encoding of objects. {-# LANGUAGE GeneralizedNewtypeDeriving #-}-module Raaz.Core.Encode.Base16( Base16, fromBase16, showBase16 ) where+module Raaz.Core.Encode.Base16+       ( Base16+       , fromBase16, showBase16+       ) where  import Data.Char import Data.Bits@@ -15,7 +18,12 @@ import Data.Word import Raaz.Core.Encode.Internal --- | The base16 type.+-- | The type corresponding to base-16 or hexadecimal encoding. The+-- `Base16` encoding has a special place in this library: most+-- cryptographic types use `Base16` encoding for their `Show` and+-- `IsString` instance. The combinators `fromBase16` and `showBase16`+-- are exposed mainly to make these definitions easy.+-- newtype Base16 = Base16 {unBase16 :: ByteString} deriving (Eq, Monoid)  -- Developers note: Internally base16 just stores the bytestring as@@ -29,7 +37,7 @@     | odd (B.length bs) = Nothing     | badCharacter bs   = Nothing     | otherwise         = Just $ Base16 $ unsafeFromHex bs-    where badCharacter  = C8.all (not . isHexDigit)+    where badCharacter  = C8.any (not . isHexDigit)    unsafeFromByteString  = Base16 . unsafeFromHex @@ -66,8 +74,9 @@   unsafeFromHex :: ByteString -> ByteString-unsafeFromHex bs | odd (B.length bs) = error "base16 encoding is always of even size"-                 | otherwise         = fst $ B.unfoldrN len gen 0+unsafeFromHex bs+  | odd (B.length bs) = error "base16 encoding is always of even size"+  | otherwise         = fst $ B.unfoldrN len gen 0   where len   = B.length bs `quot` 2         gen i = Just (shiftL w0 4 .|. w1, i + 1)           where w0 = fromHexWord $ unsafeIndex bs (2 * i)@@ -83,8 +92,8 @@ -- `IsString` instances as well as in cases where the default -- `IsString` instance does not parse from a base16 encoding. fromBase16 :: Encodable a => String -> a-fromBase16 str = unsafeDecode (fromString str :: Base16)+fromBase16 = unsafeFromByteString . unBase16 . fromString  -- | Base16 variant of `show`. showBase16 :: Encodable a => a -> String-showBase16 a = show (encode a :: Base16)+showBase16 = show . Base16 . toByteString
+ Raaz/Core/Encode/Base64.hs view
@@ -0,0 +1,171 @@+-- | Base 64 encoding of objects.+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Raaz.Core.Encode.Base64( Base64 ) where++import Data.Char+import Data.Bits+import Data.String++import Data.ByteString as B+import Data.ByteString.Char8 as C8+import Data.ByteString.Internal (c2w, w2c)++import Data.ByteString.Unsafe(unsafeIndex)+import Data.Monoid+import Data.Word+import Raaz.Core.Encode.Internal+++-- | The type corresponding to the standard padded base-64 binary+-- encoding.+newtype Base64 = Base64 {unBase64 :: ByteString} deriving (Eq, Monoid)++-- Developers note: Internally base16 just stores the bytestring as+-- is. The conversion happens when we do an encode and decode of+-- actual base16.++instance Encodable Base64 where+  toByteString          = toB64 . unBase64++  fromByteString bs+    | B.null bs                = Just $ Base64 B.empty+    | B.length bs `rem` 4 /= 0 = Nothing+    | badCharacter bs'         = Nothing+    | not (isB64OrPad pl)      = Nothing+    | not (isB64OrPad pf)      = Nothing+    | otherwise                = Just $ Base64 $ unsafeFromB64 bs+    where pl           = C8.last bs+          pf           = C8.last $ C8.init bs+          bs'          = C8.init $ C8.init bs+          badCharacter = C8.any (not . isB64Char)+          isB64Char c  = isAlpha c || isDigit c || c == '+' || c == '/'+          isB64OrPad c = isB64Char c || c == '='++  unsafeFromByteString bs | B.null bs = Base64 B.empty+                          | otherwise = Base64 $ unsafeFromB64 bs+++instance Show Base64 where+  show = C8.unpack . toByteString++instance IsString Base64 where+  fromString = unsafeFromByteString . fromString+++instance Format Base64 where+  encodeByteString = Base64+  {-# INLINE encodeByteString #-}++  decodeFormat     = unBase64+  {-# INLINE decodeFormat #-}++++------------- Base 64 encoding -------------------------++-- NOTE: The topN functions ensure that the top N bits of a word are present+-- in the least N significant bits. The botN ensures that there++top6 :: Word8 -> Word8; bot2 :: Word8 -> Word8+top4 :: Word8 -> Word8; bot4 :: Word8 -> Word8+top2 :: Word8 -> Word8; bot6 :: Word8 -> Word8++top6 w = w `shiftR` 2; bot2 w = w .&. 0x03+top4 w = w `shiftR` 4; bot4 w = w .&. 0x0F+top2 w = w `shiftR` 6; bot6 w = w .&. 0x3F++--------------- Combining bytes -----------------------------------++byte0 :: Word8 -> Word8+byte1 :: Word8 -> Word8 -> Word8+byte2 :: Word8 -> Word8 -> Word8+byte3 :: Word8 -> Word8+pad   :: Word8+++byte0     = b64 . top6+byte1 t p = b64 $ shiftL (bot2 p) 4 .|. top4 t+byte2 t p = b64 $ shiftL (bot4 p) 2 .|. top2 t+byte3     = b64 . bot6+pad       = c2w '='++-- | Encoding word.+b64 :: Word8 -> Word8+b64 w | 0  <= w  && w <= 25 = c2w 'A' + w+      | 26 <= w  && w <= 51 = c2w 'a' + w - 26+      | 52 <= w  && w <= 61 = c2w '0' + w - 52+      | w == 62             = c2w '+'+      | w == 63             = c2w '/'+      | otherwise           = error "oops: b64"+++unB64 :: Word8 -> Word8+unB64 w | c2w 'A' <= w && w <= c2w 'Z' = w - c2w 'A'+        | c2w 'a' <= w && w <= c2w 'z' = w - c2w 'a' + 26+        | c2w '0' <= w && w <= c2w '9' = w - c2w '0' + 52+        | w == c2w '+'                 = 62+        | w == c2w '/'                 = 63+        | otherwise                    = error $ "oops unB64:" ++ [w2c w]+++-- TODO: Since the encoding to base16 is usually used for user interaction+-- we can afford to be slower here.+toB64 :: ByteString -> ByteString+toB64 bs = fst (B.unfoldrN (4*n) gen 0) <> padding+    where gen i    = Just (byte i, i + 1)+          at blk i = unsafeIndex bs $ 3 * blk + i++          byte i = case r of+            0 -> byte0          $ at q 0+            1 -> byte1 (at q 1) $ at q 0+            2 -> byte2 (at q 2) $ at q 1+            3 -> byte3          $ at q 2+            _ -> error "base64 bad index"+            where (q, r) = quotRem i 4++          (n,p) = B.length bs `quotRem` 3++          padding = case p of+            0 -> mempty+            1 -> B.pack [ byte0   $ at n 0+                        , byte1 0 $ at n 0+                        , pad, pad+                        ]+            2 -> B.pack [ byte0          $ at n 0+                        , byte1 (at n 1) $ at n 0+                        , byte2 0        $ at n 1+                        , pad+                        ]+            _ -> error "base64 pad bad index"++-- Notes: Merge is used to convert from base64 digits, which are+-- words of 6-bits.+merg0 :: Word8 -> Word8 -> Word8+merg1 :: Word8 -> Word8 -> Word8+merg2 :: Word8 -> Word8 -> Word8+merg0 a b = (unB64 a `shiftL` 2) .|. top4 (unB64 b)+merg1 a b = (unB64 a `shiftL` 4) .|. top6 (unB64 b)+merg2 a b = (unB64 a `shiftL` 6) .|. unB64 b++unsafeFromB64 :: ByteString -> ByteString+unsafeFromB64 bs = fst (B.unfoldrN (3*n) gen 0) <> unPad+  where n         = B.length bs `quot` 4 - 1+        gen i     = Just (byte i, i + 1)+        at blk i  = unsafeIndex bs $ 4 * blk + i++        byte i    = case r of+          0 -> merg0 (at q 0) $ at q 1+          1 -> merg1 (at q 1) $ at q 2+          2 -> merg2 (at q 2) $ at q 3+          _ -> error "base64 bad index"+          where (q, r) = quotRem i 3++        unPad+          | at n 2 == c2w '=' = B.singleton $ merg0 (at n 0) $ at n 1+          | at n 3 == c2w '=' = B.pack [ merg0 (at n 0) $ at n 1+                                       , merg1 (at n 1) $ at n 2+                                       ]+          | otherwise         = B.pack [ merg0 (at n 0) $ at n 1+                                       , merg1 (at n 1) $ at n 2+                                       , merg2 (at n 2) $ at n 3+                                       ]
Raaz/Core/Encode/Internal.hs view
@@ -5,10 +5,8 @@ -- | Internal module that has the encode class and some utility functions. module Raaz.Core.Encode.Internal        ( Encodable(..), Format(..)-       , encode, decode, unsafeDecode        ) where - import Data.Maybe  import Data.ByteString              (ByteString)@@ -25,7 +23,21 @@ import Raaz.Core.Util.ByteString(length, withByteString)  --- | The type class `Encodable` captures all the types can be encoding into `ByteString`.+-- | The type class `Encodable` captures all the types that can be+-- encoded into a stream of bytes. By making a type say @Foo@ an+-- instance of the `Encodable` class, we get for free methods to+-- encode it in any of the supported formats (i.e. instances of the+-- class `Format`).+--+-- Minimum complete definition for this class is `toByteString` and+-- `fromByteString`. Instances of `EndianStore` have default+-- definitions for both these functions and hence a trivial instance+-- declaration is sufficient for such types.+--+-- >+-- > instance Encodable Foo+-- >+-- class Encodable a where   -- | Convert stuff to bytestring   toByteString          :: a           -> ByteString@@ -75,12 +87,39 @@   unsafeFromByteString  = BYTES      . unsafeFromByteString  --- | A binary encoding format is something for which there is a 1:1--- correspondence with bytestrings. We also insist that it is an--- instance of `IsString`, so that it can be easily included in source--- code, and `Show`, so that it can be easily printed out.++-- | A binary format is a representation of binary data often in+-- printable form. We distinguish between various binary formats at+-- the type level and each supported format corresponds to an instance+-- of the the class `Format`. The `encodeByteString` and+-- `decodeFormat` are required to satisfy the laws+--+-- > decodeFormat . encodeByteString = id+--+-- For type safety, the formats themselves are opaque types and hence+-- it is not possible to obtain the underlying binary data directly.+-- We require binary formats to be instances of the class `Encodable`,+-- with the combinators `toByteString` and `fromByteString` of the+-- `Encodable` class performing the actual encoding and decoding.+--+-- Instances of `Format` are required to be instances of `Show` and so+-- that the encoded format can be easily printed. They are also+-- required to be instances of `IsString` so that they can be easily+-- represented in Haskell source using the @OverloadedStrings@+-- extension.  However, be careful when using this due to the fact+-- that invalid encodings can lead to runtime errors.+-- class (IsString fmt, Show fmt, Encodable fmt) => Format fmt where++  -- | Encode binary data into the format. The return type gurantees+  -- that any binary data can indeed be encoded into a format.   encodeByteString :: ByteString -> fmt++  -- | Decode the format to its associated binary+  -- representation. Notice that this function always succeeds: we+  -- assume that elements of the type `fmt` are valid encodings and+  -- hence the return type is `ByteString` instead of @`Maybe`+  -- ByteString@.   decodeFormat     :: fmt        -> ByteString  -- | Bytestring itself is an encoding format (namely binary format).@@ -89,17 +128,3 @@   {-# INLINE encodeByteString #-}   decodeFormat     = id   {-# INLINE decodeFormat     #-}----- | Encode in a given format.-encode :: (Encodable a, Format fmt) => a -> fmt-encode = encodeByteString . toByteString---- | Decode from a given format. It results in Nothing if there is a--- parse error.-decode :: (Format fmt, Encodable a) => fmt -> Maybe a-decode = fromByteString . decodeFormat---- | The unsafe version of `decode`.-unsafeDecode :: (Format fmt, Encodable a) => fmt -> a-unsafeDecode = unsafeFromByteString . decodeFormat
Raaz/Core/Memory.hs view
@@ -13,21 +13,22 @@  module Raaz.Core.Memory        (-       -- * The Memory subsystem+       -- * The Memory subsystem.        -- $memorysubsystem$--       -- ** Memory monads-         MonadMemory(..)-       , MT, execute, getMemory, liftSubMT-       , MemoryM, runMT-       -- *** Some low level functions.+       -- ** Memory elements+         Memory(..), copyMemory+       -- *** A basic memory cell.+       , MemoryCell+       -- *** Initialising and extracting.+       , Initialisable(..), Extractable(..)+       -- *** Actions on memory elements.+       , MT,  execute, getMemory, liftSubMT, modify+       -- **** Some low level `MT` actions.        , getMemoryPointer, withPointer        , allocate-       -- ** Memory elements.-       , Memory(..), copyMemory-       , Initialisable(..), Extractable(..), modify-       -- *** Some basic memory elements.-       , MemoryCell+       -- ** Generic memory monads.+       , MonadMemory(..)+       , MemoryM, runMT        -- ** Memory allocation        ,  Alloc, pointerAlloc        ) where@@ -44,10 +45,33 @@ -- -- The memory subsystem consists of two main components. ----- 1. Abstract elements captured by the `Memory` type class.+-- [The `Memory` type class] A memory element is some type that holds+-- an internal buffer inside it. The operations that are allowed on+-- the element is controlled by the associated type. Certain memory+-- element have a default way in which it can be initialised by values+-- of type @a@. An instance declaration @`Initialisable` mem a@ for+-- the memory type @mem@ is done in such case. Similary, if values of+-- type @b@ can be extracted out of a memory element @mem@, we can+-- indicate it with an instance of @`Extractable` mem a@. ----- 2. Abstract memory actions captured by the type class `MonadMemory`.+-- [The `Alloc` type and memory allocation] The most important and+-- often error prone operation while using low level memory buffers is+-- its allocation. The `Alloc` types gives the allocation strategy for+-- a memory element keeping track of the necessary book keeping+-- involved in it.  The `Alloc` type is an instance of `Applicative`+-- which helps build the allocation strategy for a compound memory+-- type from its components in a modular fashion without any explicit+-- size calculation or offset computation. --+-- [The `MonadMemory` class] Instances of these classes are actions+-- that use some kind of memory elements, i.e. instances of the class+-- `Memory`, inside it. Any such monad can either be run using the+-- combinator `securely` or the combinator `insecurely`. If one use+-- the combinator `securely`, then all allocations done during the run+-- is from a locked memory pool which is wiped clean before+-- de-allocation. The types `MT` and `MemoryM` are two instances that+-- we expose from this library.+--  -- | A class that captures monads that use an internal memory element. --@@ -338,7 +362,7 @@ -- essentially a limitation of the bracket which is used internally. withSecureMemory :: Memory m => (m -> IO a) -> IO a withSecureMemory = withSM memoryAlloc-  where withSM :: Memory m => Alloc m -> (m -> IO a) -> IO a+  where -- withSM :: Memory m => Alloc m -> (m -> IO a) -> IO a         withSM alctr action = allocaSecure sz $ action . getM           where sz     = getSum $ twistMonoidValue alctr                 getM   = computeField $ twistFunctorValue alctr@@ -356,7 +380,14 @@ withCell fp  = execute $ fp . unMemoryCell {-# INLINE withCell #-} --- | Apply the given function to the value in the cell.+-- | Apply the given function to the value in the cell. For a function @f :: b -> a@,+-- the action @modify f@ first extracts a value of type @b@ from the+-- memory element, applies @f@ to it and puts the result back into the+-- memory.+--+-- > modify f = do b          <- extract+-- >               initialise $  f b+-- modify :: (Initialisable m a, Extractable m b) =>  (b -> a) -> MT m () modify f = extract >>= initialise . f 
Raaz/Core/Primitives.hs view
@@ -91,5 +91,5 @@ -- | The expression @n `blocksOf` p@ specifies the message lengths in -- units of the block length of the primitive @p@. This expression is -- sometimes required to make the type checker happy.-blocksOf :: Primitive p =>  Int -> p -> BLOCKS p+blocksOf :: Int -> p -> BLOCKS p blocksOf n _ = BLOCKS n
Raaz/Core/Types.hs view
@@ -3,38 +3,16 @@ -- use the type safety of Haskell to catch some common bugs at compile -- time. As of now we address three kinds of errors ----- [Timing safe equality:] We need a consistent way to build timing---     safe equality comparisons. The type class `Equality` plays the---     role of `Eq` for us. The comparison result is of type `Result`---     and not `Bool` so as to avoid timing attacks due to---     short-circuting of the AND-operation. Instance for basic word---     types are given here and users are expected to build the---     `Equality` instances of compound types by combine the results---     of comparisons using the monoid instance of `Result`. We also---     give timing safe equality comparisons for `Vector` types using---     the `eqVector` and `oftenCorrectEqVector` functions.  Once an---     instance for `Equality` is defined for a cryptographically---     sensitive data type, we define the `Eq` for it indirectly using---     the `Equality` instance and the operation `===`.------ [Endianness aware types:] When serialising data, we need to be---     careful about the endianness of the machine. Instance of the---     `EndianStore` type class correctly stores and loads data from---     memory, irrespective of the endianness of the machine. We---     define endian aware variants of `Word32` and `Word64` here and---     expect other cryptographic types to use such endian explicit---     types in their definition.------ [Pointer and Length units:] We have the generic pointer type---     `Pointer` and distinguish between different length units at the---     type level. This helps in to avoid a lot of length conversion---     errors.+ module Raaz.Core.Types        ( -- * Timing safe equality checking.+         -- $timingSafeEquality$          module Raaz.Core.Types.Equality          -- * Endianess aware types.+         -- $endianness$        , module Raaz.Core.Types.Endian          -- * The pointer type and Length offsets.+         -- $typesafeLength$        , module Raaz.Core.Types.Pointer          -- * Tuples with length encoded in their types.        , module Raaz.Core.Types.Tuple@@ -46,5 +24,54 @@ import Raaz.Core.Types.Endian import Raaz.Core.Types.Pointer import Raaz.Core.Types.Tuple++-- $timingSafeEquality$+--+-- We need a consistent way to build timing safe equality+-- comparisons. The type class `Equality` plays the role of `Eq` for+-- us. The comparison result is of type `Result` and not `Bool` so as+-- to avoid timing attacks due to short-circuting of the+-- AND-operation.+--+-- The `Result` type is an opaque type to avoid the user from+-- compromising the equality comparisons by pattern matching on it. To+-- combine the results of two comparisons one can use the monoid+-- instance of `Result`, i.e. if @r1@ and @r2@ are the results of two+-- comparisons then @r1 `mappend` r2@ essentially takes the AND of+-- these results but this and is not short-circuited and is timing+-- independent.+--+-- Instance for basic word types are provided by the library and users+-- are expected to build the `Equality` instances of compound types by+-- combine the results of comparisons using the monoid instance of+-- `Result`. We also give timing safe equality comparisons for+-- `Vector` types using the `eqVector` and `oftenCorrectEqVector`+-- functions.  Once an instance for `Equality` is defined for a+-- cryptographically sensitive data type, we define the `Eq` for it+-- indirectly using the `Equality` instance and the operation `===`.+++-- $endianness$+--+-- Cryptographic primitives often consider their input as an array of+-- words of a particular endianness. Endianness is only relevant when+-- the data is being read or written to. It makes sense therefore to+-- keep track of the endianness in the type and perform necessary+-- transformations depending on the endianness of the+-- machine. Such types are captured by the type class `EndianStore`. They+-- support the `load` and `store` combinators that automatically compensates+-- for the endianness of the machine.+--+-- This libraray exposes endian aware variants of `Word32` and+-- `Word64` here and expect other cryptographic types to use such+-- endian explicit types in their definition.+++-- $typesafeLength$+--+-- We have the generic pointer type `Pointer` and distinguish between+-- different length units at the type level. This helps in to avoid a+-- lot of length conversion errors.+  {-# ANN module "HLint: ignore Use import/export shortcut" #-}
Raaz/Core/Types/Endian.hs view
@@ -86,7 +86,7 @@               -> IO w {-# INLINE loadFromIndex #-} loadFromIndex cptr index = loadP undefined-   where loadP ::  (EndianStore w, Storable w) => w -> IO w+   where loadP ::  EndianStore w => w -> IO w          loadP w = loadFrom cptr offset            where offset = toEnum index * byteSize w 
Raaz/Core/Types/Equality.hs view
@@ -5,7 +5,7 @@ module Raaz.Core.Types.Equality        ( Equality(..), (===)        -- ** The result of comparion.-       , Result, isSuccessful+       , Result        -- ** Comparing vectors.        , oftenCorrectEqVector, eqVector        ) where@@ -22,17 +22,13 @@ import           Data.Vector.Unboxed         ( MVector(..), Vector, Unbox ) import           Data.Word --- | An opaque type that captures the result of a comparison. The monoid--- instances allows us to combine the results of two equality comparisons--- in a timing independent manner. We have the following properties.------ > isSuccessful mempty            = True--- > isSuccessful (r `mappend` s)   = isSuccessful r && isSuccessful s---+-- | The result of a comparison. This is an opaque type and the monoid instance essentially takes+-- AND of two comparisons in a timing safe way. newtype Result =  Result { unResult :: Word }  -- | Checks whether a given equality comparison is successful. isSuccessful :: Result -> Bool+{-# INLINE isSuccessful #-} isSuccessful = (==0) . unResult  instance Monoid Result where@@ -99,7 +95,7 @@   --- | In a cryptographic setting, naive equality checking+-- | In a cryptographic setting, naive equality checking is -- dangerous. This class is the timing safe way of doing equality -- checking. The recommended method of defining equality checking for -- cryptographically sensitive data is as follows.@@ -155,6 +151,76 @@ #else   eq w1 w2 = Result $ fromIntegral $ xor w1 w2 #endif++-- Now comes the boring instances for tuples.++instance ( Equality a+         , Equality b+         ) => Equality (a , b) where+  eq (a1,a2) (b1,b2) = eq a1 b1 `mappend` eq a2 b2+++instance ( Equality a+         , Equality b+         , Equality c+         ) => Equality (a , b, c) where+  eq (a1,a2,a3) (b1,b2,b3) = eq a1 b1 `mappend`+                             eq a2 b2 `mappend`+                             eq a3 b3+++instance ( Equality a+         , Equality b+         , Equality c+         , Equality d+         ) => Equality (a , b, c, d) where+  eq (a1,a2,a3,a4) (b1,b2,b3,b4) = eq a1 b1 `mappend`+                                   eq a2 b2 `mappend`+                                   eq a3 b3 `mappend`+                                   eq a4 b4++instance ( Equality a+         , Equality b+         , Equality c+         , Equality d+         , Equality e+         ) => Equality (a , b, c, d, e) where+  eq (a1,a2,a3,a4,a5) (b1,b2,b3,b4,b5) = eq a1 b1 `mappend`+                                         eq a2 b2 `mappend`+                                         eq a3 b3 `mappend`+                                         eq a4 b4 `mappend`+                                         eq a5 b5+++instance ( Equality a+         , Equality b+         , Equality c+         , Equality d+         , Equality e+         , Equality f+         ) => Equality (a , b, c, d, e, f) where+  eq (a1,a2,a3,a4,a5,a6) (b1,b2,b3,b4,b5,b6) = eq a1 b1 `mappend`+                                               eq a2 b2 `mappend`+                                               eq a3 b3 `mappend`+                                               eq a4 b4 `mappend`+                                               eq a5 b5 `mappend`+                                               eq a6 b6++instance ( Equality a+         , Equality b+         , Equality c+         , Equality d+         , Equality e+         , Equality f+         , Equality g+         ) => Equality (a , b, c, d, e, f, g) where+  eq (a1,a2,a3,a4,a5,a6,a7) (b1,b2,b3,b4,b5,b6,b7) = eq a1 b1 `mappend`+                                                     eq a2 b2 `mappend`+                                                     eq a3 b3 `mappend`+                                                     eq a4 b4 `mappend`+                                                     eq a5 b5 `mappend`+                                                     eq a6 b6 `mappend`+                                                     eq a7 b7   -- | Timing independent equality checks for vector of values. /Do not/
Raaz/Hash/Internal/HMAC.hs view
@@ -80,13 +80,13 @@         theHash     :: HMACKey h -> h         theHash  _  = undefined -instance (Hash h, Recommendation h, Encodable h) => EndianStore (HMACKey h) where+instance (Hash h, Recommendation h) => EndianStore (HMACKey h) where   store = poke . castPtr   load  = peek . castPtr -instance (Hash h, Recommendation h, Encodable h) => Random (HMACKey h)+instance (Hash h, Recommendation h) => Random (HMACKey h) -instance (Hash h, Recommendation h, Encodable h) => Encodable (HMACKey h)+instance (Hash h, Recommendation h) => Encodable (HMACKey h)  -- | Base16 representation of the string. instance IsString (HMACKey h) where
raaz.cabal view
@@ -1,5 +1,5 @@ name:    raaz-version: 0.0.1+version: 0.0.2  synopsis: The raaz cryptographic library. @@ -103,6 +103,7 @@   other-modules: Raaz.Core.Constants                , Raaz.Core.Encode.Internal                , Raaz.Core.Encode.Base16+               , Raaz.Core.Encode.Base64                , Raaz.Core.Util.ByteString                , Raaz.Core.Types.Pointer                , Raaz.Core.Types.Tuple@@ -173,7 +174,7 @@   hs-source-dirs: bin   main-is: checksum.lhs   build-depends: base     >= 4.5 && < 5.0-               , raaz     == 0.0.1+               , raaz     == 0.0.2  test-Suite spec   type: exitcode-stdio-1.0@@ -183,11 +184,13 @@   other-modules: Common                , Common.Cipher                , Common.Hash+               , Common.Imports                , Common.Instances                , Common.Utils                , Raaz.Cipher.AESSpec-               , Raaz.Core.Encode.Base16Spec+               , Raaz.Core.EncodeSpec                , Raaz.Core.MemorySpec+               , Raaz.Core.SystemPRGSpec                , Raaz.Core.Types.WordSpec                , Raaz.Core.Util.ByteStringSpec                , Raaz.Hash.Sha1Spec@@ -204,7 +207,7 @@                , QuickCheck                     >= 2.4                , hspec                , transformers-               , raaz                           == 0.0.1+               , raaz                           == 0.0.2                , vector  benchmark blaze-vs-write
+ spec/Common/Imports.hs view
@@ -0,0 +1,19 @@+-- Common imports.+module Common.Imports( module E ) where+import Control.Applicative     as E+import Data.ByteString         as E (ByteString, pack)+import Data.ByteString.Char8        () -- import IsString instance for+                                       -- byte string.+import Data.String             as E+import Data.Monoid             as E+import Data.Word               as E+import Foreign.Storable        as E (Storable(..))+import Test.Hspec              as E+import Test.Hspec.QuickCheck   as E+import Test.QuickCheck         as E+import Test.QuickCheck.Monadic as E++import Raaz.Core               as E hiding ((===), Result)+import Raaz.Hash               as E+import Raaz.Cipher             as E+import Raaz.Cipher.Internal    as E ( Cipher, unsafeEncrypt, unsafeDecrypt )
spec/Common/Instances.hs view
@@ -51,6 +51,9 @@ instance Arbitrary Base16 where   arbitrary =  (encodeByteString . pack) <$> listOf arbitrary +instance Arbitrary Base64 where+  arbitrary =  (encodeByteString . pack) <$> listOf arbitrary+ ------------------ Arbitrary instances for Keys ---------------  instance Arbitrary AES.KEY128 where
− spec/Raaz/Core/Encode/Base16Spec.hs
@@ -1,13 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE OverloadedStrings   #-}-module Raaz.Core.Encode.Base16Spec where--import Common--spec :: Spec-spec = do-  prop "unsafeFromByteString . toByteString = id" $ \ (x :: Base16) ->-    unsafeFromByteString (toByteString x) `shouldBe` x-  prop "correctly encodes a 64-bit big endian word." $ \ (w :: Word64) ->-    (read $ "0x" ++ showBase16 (bigEndian w))  == w
+ spec/Raaz/Core/EncodeSpec.hs view
@@ -0,0 +1,41 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings   #-}+module Raaz.Core.EncodeSpec where++import           Common+import qualified Data.ByteString as B++shouldBeAMultipleOf :: Int -> Int -> Bool+shouldBeAMultipleOf m x = m `rem` x == 0++shouldEncodeTo :: (Format fmt, Eq fmt) => ByteString -> fmt -> Spec+shouldEncodeTo bs e = it msg $ encodeByteString bs `shouldBe` e+  where msg = show bs ++ " should encode to " ++ show e++spec :: Spec+spec = do+  describe "Base16" $ do+    prop "encoded string is always of even length" $ \ (x :: Base16) ->+      B.length (toByteString x) `shouldBeAMultipleOf` 2++    prop "unsafeFromByteString . toByteString = id" $ \ (x :: Base16) ->+      unsafeFromByteString (toByteString x) `shouldBe` x++    prop "correctly encodes a 64-bit big endian word." $ \ (w :: Word64) ->+      (read $ "0x" ++ showBase16 (bigEndian w))  == w+++  describe "Base64" $ do+    prop "encoded string is always divisible by 4" $ \ (x :: Base64) ->+      B.length (toByteString x) `shouldBeAMultipleOf` 4++    prop "unsafeFromByteString . toByteString = id" $ \ (x :: Base16) ->+      unsafeFromByteString (toByteString x) `shouldBe` x++    describe "examples" $ do+      "pleasure." `shouldEncodeTo` ("cGxlYXN1cmUu" :: Base64)+      "leasure."  `shouldEncodeTo` ("bGVhc3VyZS4=" :: Base64)+      "easure."   `shouldEncodeTo` ("ZWFzdXJlLg==" :: Base64)+      "asure." 	  `shouldEncodeTo` ("YXN1cmUu"     :: Base64)+      "sure." 	  `shouldEncodeTo` ("c3VyZS4="     :: Base64)
+ spec/Raaz/Core/SystemPRGSpec.hs view
@@ -0,0 +1,12 @@+module Raaz.Core.SystemPRGSpec where++import Common++spec :: Spec+spec = it "system prg should return different words on distinct calls"+       $ compareWords `shouldReturn` False+  where randomWord :: SystemPRG -> IO Word+        randomWord  = random+        compareWords = do systemPRG <- newPRG ()+                          (==) <$> randomWord systemPRG+                               <*> randomWord systemPRG