Need to use ordinary comments instead of nested comments because LANGUAGE pragmas were removed otherwise. Also adds a table of contents. We may have other examples in the future.
67 lines
2.7 KiB
Haskell
67 lines
2.7 KiB
Haskell
-- | Examples of how to use @cryptonite@.
|
|
module Crypto.Tutorial
|
|
( -- * Symmetric block ciphers
|
|
-- $symmetric_block_ciphers
|
|
) where
|
|
|
|
-- $symmetric_block_ciphers
|
|
--
|
|
-- > {-# LANGUAGE OverloadedStrings #-}
|
|
-- > {-# LANGUAGE ScopedTypeVariables #-}
|
|
-- > {-# LANGUAGE GADTs #-}
|
|
-- >
|
|
-- > import Crypto.Cipher.AES (AES256)
|
|
-- > import Crypto.Cipher.Types (BlockCipher(..), Cipher(..), nullIV, KeySizeSpecifier(..), IV, makeIV)
|
|
-- > import Crypto.Error (CryptoFailable(..), CryptoError(..))
|
|
-- >
|
|
-- > import qualified Crypto.Random.Types as CRT
|
|
-- >
|
|
-- > import Data.ByteArray (ByteArray)
|
|
-- > import Data.ByteString (ByteString)
|
|
-- >
|
|
-- > -- | Not required, but most general implementation
|
|
-- > data Key c a where
|
|
-- > Key :: (BlockCipher c, ByteArray a) => a -> Key c a
|
|
-- >
|
|
-- > -- | Generates a string of bytes (key) of a specific length for a given block cipher
|
|
-- > genSecretKey :: forall m c a. (CRT.MonadRandom m, BlockCipher c, ByteArray a) => c -> Int -> m (Key c a)
|
|
-- > genSecretKey _ = fmap Key . CRT.getRandomBytes
|
|
-- >
|
|
-- > -- | Generate a random initialization vector for a given block cipher
|
|
-- > genRandomIV :: forall m c. (CRT.MonadRandom m, BlockCipher c) => c -> m (Maybe (IV c))
|
|
-- > genRandomIV _ = do
|
|
-- > bytes :: ByteString <- CRT.getRandomBytes $ blockSize (undefined :: c)
|
|
-- > return $ makeIV bytes
|
|
-- >
|
|
-- > -- | Initialize a block cipher
|
|
-- > initCipher :: (BlockCipher c, ByteArray a) => Key c a -> Either CryptoError c
|
|
-- > initCipher (Key k) = case cipherInit k of
|
|
-- > CryptoFailed e -> Left e
|
|
-- > CryptoPassed a -> Right a
|
|
-- >
|
|
-- > encrypt :: (BlockCipher c, ByteArray a) => Key c a -> IV c -> a -> Either CryptoError a
|
|
-- > encrypt secretKey initIV msg =
|
|
-- > case initCipher secretKey of
|
|
-- > Left e -> Left e
|
|
-- > Right c -> Right $ ctrCombine c initIV msg
|
|
-- >
|
|
-- > decrypt :: (BlockCipher c, ByteArray a) => Key c a -> IV c -> a -> Either CryptoError a
|
|
-- > decrypt = encrypt
|
|
-- >
|
|
-- > exampleAES256 :: ByteString -> IO ()
|
|
-- > exampleAES256 msg = do
|
|
-- > -- secret key needs 256 bits (32 * 8)
|
|
-- > secretKey <- genSecretKey (undefined :: AES256) 32
|
|
-- > mInitIV <- genRandomIV (undefined :: AES256)
|
|
-- > case mInitIV of
|
|
-- > Nothing -> error "Failed to generate and initialization vector."
|
|
-- > Just initIV -> do
|
|
-- > let encryptedMsg = encrypt secretKey initIV msg
|
|
-- > decryptedMsg = decrypt secretKey initIV =<< encryptedMsg
|
|
-- > case (,) <$> encryptedMsg <*> decryptedMsg of
|
|
-- > Left err -> error $ show err
|
|
-- > Right (eMsg, dMsg) -> do
|
|
-- > putStrLn $ "Original Message: " ++ show msg
|
|
-- > putStrLn $ "Message after encryption: " ++ show eMsg
|
|
-- > putStrLn $ "Message after decryption: " ++ show dMsg
|