Safe Haskell | Safe |
---|---|
Language | Haskell2010 |
Examples of how to use cryptonite
.
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