### Install Crypton via Stack Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Install the Crypton package using the Stack build tool. ```bash stack install crypton ``` -------------------------------- ### Hash a File Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Consult api-reference/hash-functions.md for examples demonstrating streaming patterns for hashing files. ```haskell -- See api-reference/hash-functions.md (Streaming Patterns) ``` -------------------------------- ### Install Crypton via Hackage Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Update the Cabal package index and install Crypton from Hackage. ```bash cabal update cabal install crypton ``` -------------------------------- ### Install Crypton via Cabal Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Install the Crypton package using the Cabal package manager. ```bash cabal install crypton ``` -------------------------------- ### BCrypt Example Usage Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/key-derivation.md Demonstrates how to generate a BCrypt hash for a password and then validate it. Ensure the salt is 16 bytes. ```haskell import Crypto.KDF.BCrypt import qualified Data.ByteString as BS let password = "my-password" :: ByteString let salt = BS.replicate 16 0x42 let params = Parameters { bcryptRounds = 12, -- 2^12 iterations bcryptSaltLen = 16 } let hash = generate params password salt :: ByteString -- Check password let isValid = validatePassword password hash ``` -------------------------------- ### Encrypt and Authenticate Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Refer to the AES-GCM section in api-reference/cipher-implementations.md for encryption and authentication examples using Poly1305. ```haskell -- See api-reference/cipher-implementations.md (AES-GCM section) -- and api-reference/mac-functions.md (Poly1305 section) ``` -------------------------------- ### Incremental Hashing Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/hash-functions.md Demonstrates incremental hashing using `hashInit`, `hashUpdate`, and `hashFinalize`. Shows how to update the context with multiple byte strings and retrieve the final digest. ```haskell import Crypto.Hash import qualified Data.ByteString as BS -- Incremental hashing let ctx0 = hashInit :: Context SHA256 let ctx1 = hashUpdate ctx0 (BS.pack [1..10]) let ctx2 = hashUpdate ctx1 (BS.pack [11..20]) let digest = hashFinalize ctx2 :: Digest SHA256 -- Get digest size let size = hashDigestSize ctx0 -- 32 for SHA256 ``` -------------------------------- ### Derive Key from Password Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Refer to api-reference/key-derivation.md for examples on deriving keys from passwords using Argon2 or Scrypt. ```haskell -- See api-reference/key-derivation.md (Argon2 or Scrypt) ``` -------------------------------- ### Install Crypton with Disabled AESNI Source: https://github.com/kazu-yamamoto/crypton/blob/main/README.md Use this command to install crypton while explicitly disabling the support_aesni flag. This ensures that AESNI features are not included in the installation. ```bash cabal install --constraint="crypton -support_aesni" ``` -------------------------------- ### ECDSA Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/asymmetric-crypto.md An example demonstrating how to use ECDSA for signing and verifying messages with the NIST P-256 curve. ```APIDOC ## ECDSA Example ### Usage ```haskell import Crypto.PubKey.ECDSA import Crypto.PubKey.ECC.Types (curveName, secp256r1) import Crypto.Hash (SHA256, Digest) import Crypto.Random -- Sign with NIST P-256 curve let curve = secp256r1 seed <- seedNew :: IO Seed let drg = drgNew seed -- Generate key let (pubKey, privKey, _) = withDRG drg (generate curve) -- Sign message let (sig, _) = withDRG drg (sign privKey message) -- Verify if verify pubKey sig message then putStrLn "Signature valid" else putStrLn "Invalid" ``` ``` -------------------------------- ### AES Encryption Example (ECB Mode) Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-implementations.md Demonstrates initializing AES128 with a key and performing ECB encryption on a plaintext. Ensure the key size matches the AES variant. ```haskell import Crypto.Cipher.AES import qualified Data.ByteString as BS -- Initialize AES128 let key = BS.replicate 16 0xFF let ctx = cipherInit key :: CryptoFailable AES128 case ctx of CryptoPassed cipher -> do -- ECB mode let plaintext = BS.replicate 32 0x42 let ciphertext = ecbEncrypt cipher plaintext return ciphertext CryptoFailed err -> error (show err) ``` -------------------------------- ### ECDSA Signing and Verification Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/asymmetric-crypto.md Demonstrates how to generate an ECDSA key pair, sign a message using the NIST P-256 curve, and verify the signature. ```haskell import Crypto.PubKey.ECDSA import Crypto.PubKey.ECC.Types (curveName, secp256r1) import Crypto.Hash (SHA256, Digest) import Crypto.Random -- Sign with NIST P-256 curve let curve = secp256r1 seed <- seedNew :: IO Seed let drg = drgNew seed -- Generate key let (pubKey, privKey, _) = withDRG drg (generate curve) -- Sign message let (sig, _) = withDRG drg (sign privKey message) -- Verify if verify pubKey sig message then putStrLn "Signature valid" else putStrLn "Invalid" ``` -------------------------------- ### RSA Key Generation Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/asymmetric-crypto.md Demonstrates generating a 2048-bit RSA key pair using a random number generator. Also shows how to generate keys directly from provided prime numbers. ```haskell import Crypto.PubKey.RSA import Crypto.Random -- Generate 2048-bit RSA key pair seed <- seedNew :: IO Seed let drg = drgNew seed let (pubKey, privKey, _) = withDRG drg (generate 256 0x10001) -- 256 bytes = 2048 bits -- 0x10001 = 65537 (standard choice) putStrLn ("Public n: " ++ show (public_n pubKey)) putStrLn ("Private d: " ++ show (private_d privKey)) -- Or provide primes directly let p = 61 -- small primes for example let q = 53 case generateWith (p, q) 8 0x10001 of Just (pub, priv) -> putStrLn "Keys generated" Nothing -> putStrLn "Invalid e for these primes" ``` -------------------------------- ### HKDF Extract and Expand Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/key-derivation.md Demonstrates how to use HKDF for key derivation, both in a single step and by separating the extract and expand operations. Requires importing necessary modules and defining input parameters like IKM, salt, info, and output length. ```haskell import Crypto.KDF.HKDF import Crypto.Hash (SHA256) import qualified Data.ByteString as BS -- Extract + Expand in one step let ikm = BS.replicate 32 0xFF -- input key material let salt = BS.replicate 16 0x00 -- optional salt let info = "application-info" -- context info let outputLen = 32 -- bytes to derive let derivedKey = extractAndExpand SHA256 salt ikm info outputLen :: ByteString -- Or step-by-step let prk = extract SHA256 salt ikm -- concentrated key let key1 = expand SHA256 prk (Just "key1") 32 :: ByteString let key2 = expand SHA256 prk (Just "key2") 32 :: ByteString ``` -------------------------------- ### BCryptPBKDF Example Usage Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/key-derivation.md Example of generating a derived key using BCryptPBKDF. The key length is determined by the 'ba' type, and 16 rounds are used. ```haskell import Crypto.KDF.BCryptPBKDF let password = "password" :: ByteString let salt = BS.replicate 16 0x01 let key = generate 16 password salt :: ByteString -- 16 rounds ``` -------------------------------- ### AES Encryption Example (GCM Mode) Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-implementations.md Shows how to initialize AES for GCM mode, append authenticated data, encrypt plaintext, and finalize the tag. Requires a valid IV and cipher initialization. ```haskell -- GCM mode case ctx of CryptoPassed cipher -> do let iv = makeIV (BS.replicate 12 0) case (iv, aeadInit AEAD_GCM cipher (BS.replicate 12 0)) of (Just iv', CryptoPassed aead) -> do let aead2 = aeadAppendHeader aead aad let (ct, aead3) = aeadEncrypt aead2 plaintext let tag = aeadFinalize aead3 return (ct, tag) _ -> error "Init failed" _ -> error "Cipher init failed" ``` -------------------------------- ### Derive Key using fastPBKDF2_SHA256 Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/key-derivation.md Example of deriving a 32-byte key using the fastPBKDF2_SHA256 function with specified parameters and a salt. This is the recommended approach for most use cases. ```haskell import Crypto.KDF.PBKDF2 import qualified Data.ByteString as BS -- Derive key from password let password = "my-password" :: ByteString let salt = BS.replicate 16 0x42 -- 16 random bytes let params = Parameters { iterCounts = 100000 -- higher is slower but more secure , outputLength = 32 -- 32 bytes output } let derivedKey = fastPBKDF2_SHA256 params password salt :: ByteString -- derivedKey: 32 bytes of derived key material ``` -------------------------------- ### Prefix-hashing (Constant-time) Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Example of prefix-hashing, which is designed to operate in constant time. ```haskell hashPrefix :: Hash -> ByteArray -> Digest hashPrefix = hashPrefix ``` -------------------------------- ### Example Usage of IV Functions Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-types.md Illustrates how to create an IV from byte strings using `makeIV`, use a null IV with `nullIV`, and increment an IV for use in counter mode operations like CTR with `ivAdd`. ```haskell import Crypto.Cipher.Types -- Create IV from bytes let iv = makeIV (BS.replicate 16 0) :: Maybe (IV AES128) -- Use null IV let iv0 = nullIV :: IV AES128 -- Increment IV for CTR mode case iv of Just iv' -> let iv'' = ivAdd iv' (1 :: Word64) in ... Nothing -> error "IV size mismatch" ``` -------------------------------- ### Key Agreement Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Find examples for key agreement using Curve25519 in the asymmetric crypto section of api-reference/asymmetric-crypto.md. ```haskell -- See api-reference/asymmetric-crypto.md (Curve25519 section) ``` -------------------------------- ### Cabal Configure for Portability Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Use these flags with 'cabal configure' to prioritize portability over maximum speed. This example shows how to enable specific features while maintaining broader compatibility. ```bash cabal configure --flag='-support_aesni' \ --flag='-support_rdrand' ``` -------------------------------- ### Retry AES Initialization with Valid Key Size Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/errors.md Demonstrates how to retry AES initialization by padding the key if it's initially invalid. This is for example purposes and may be dangerous in production. ```haskell import Crypto.Cipher.AES import qualified Data.ByteString as BS -- Auto-pad key to valid size (dangerous! for example only) padToValidSize :: ByteString -> ByteString padToValidSize bs | BS.length bs >= 16 = BS.take 16 bs | otherwise = bs <> BS.replicate (16 - BS.length bs) 0 initWithFallback :: ByteString -> CryptoFailable AES128 initWithFallback key = case cipherInit key of CryptoFailed CryptoError_KeySizeInvalid -> cipherInit (padToValidSize key) result -> result ``` -------------------------------- ### DH Key Agreement Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/asymmetric-crypto.md Demonstrates a typical Diffie-Hellman key exchange scenario between two parties, Alice and Bob, ensuring the computed shared secrets match. ```haskell import Crypto.PubKey.DH -- Alice generates key pair let params = Params { params_p = largePrime, params_g = 2 } (alicePub, alicePriv) <- generate params -- Bob generates key pair (bobPub, bobPriv) <- generate params -- Compute shared secrets let aliceShared = getShared alicePriv bobPub let bobShared = getShared bobPriv alicePub assert (aliceShared == bobShared) ``` -------------------------------- ### PBKDF2 Key Derivation Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/key-derivation.md Demonstrates how to use the PBKDF2 functions to derive key material from a password and salt. Includes examples for both fast variants and custom PRF usage. ```APIDOC ## PBKDF2 Key Derivation ### Description Derives key material from a password using the PBKDF2 algorithm. Supports optimized SHA1, SHA256, and SHA512 variants, as well as a generic function for custom Pseudo-Random Functions (PRF). ### Functions - `fastPBKDF2_SHA1` - `fastPBKDF2_SHA256` - `fastPBKDF2_SHA512` - `generate` (with custom PRF) ### Parameters #### PBKDF2 Parameters - **iterCounts** (`Int`) - Required - Number of iterations (4000+ recommended, 100,000+ for modern hardware). - **outputLength** (`Int`) - Required - Derived key length in bytes (32+ bytes recommended). #### Input Parameters - **password** (`ba`) - Required - The password to derive the key from. - **salt** (`ba`) - Required - Random salt (16+ bytes recommended). #### PRF (for `generate` function) - **prf** (`PRF password`) - Required - A function that takes a password and a seed and returns pseudo-random bytes. ### Request Example ```haskell import Crypto.KDF.PBKDF2 import qualified Data.ByteString as BS -- Derive key using fastPBKDF2_SHA256 let password = "my-password" :: ByteString let salt = BS.replicate 16 0x42 -- 16 random bytes let params = Parameters { iterCounts = 100000 , outputLength = 32 } let derivedKey = fastPBKDF2_SHA256 params password salt :: ByteString -- derivedKey will be 32 bytes of derived key material -- Derive key using a custom PRF (HMAC-SHA512) let prf = prfHMAC SHA512 let key = generate prf params password salt :: ByteString ``` ### Response - **derivedKey** (`ByteString`) - The derived key material of the specified `outputLength`. ``` -------------------------------- ### State-based Hashing Update Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Demonstrates the state-based hashing pattern: initialize context, update with data, and finalize to get the digest. ```haskell update :: Hash -> ByteArray -> Hash update = update ``` -------------------------------- ### AEAD Encryption Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Example of using AEAD encryption, including header appending and finalization. ```haskell aeadEncrypt :: AEAD -> ByteArray -> ByteArray -> AEAD aeadEncrypt aead header plaintext = aeadEncrypt aead header plaintext ``` -------------------------------- ### ChaCha20 Stream Cipher Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-implementations.md An example of using the ChaCha20 stream cipher to generate a keystream from a given key and plaintext. It handles potential initialization failures. ```haskell import Crypto.Cipher.ChaCha let key = BS.replicate 32 0xAB let ctx = cipherInit key :: CryptoFailable ChaCha20 case ctx of CryptoPassed cipher -> do let (keystream, cipher') = streamCombine cipher plaintext return keystream _ -> error "Failed" ``` -------------------------------- ### Ed25519 Digital Signature Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/asymmetric-crypto.md Demonstrates generating an Ed25519 key pair, signing a message, and verifying the signature. Requires a 32-byte private key. ```haskell import Crypto.PubKey.Ed25519 import qualified Data.ByteString as BS -- Generate key pair (32-byte seed = private key) let privKey = BS.replicate 32 0xFF :: PrivateKey let pubKey = toPublic privKey :: PublicKey -- Sign let message = "Sign this message" let sig = sign privKey message :: Signature -- Verify if verify pubKey sig message then putStrLn "Signature valid" else putStrLn "Invalid" ``` -------------------------------- ### CMAC with AES Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/mac-functions.md Shows how to compute a CMAC tag using AES encryption. Includes examples for both direct computation and incremental updates, handling potential failures. ```haskell import Crypto.MAC.CMAC import Crypto.Cipher.AES import qualified Data.ByteString as BS -- CMAC with AES let key = BS.replicate 16 0x55 let message = "data to authenticate" case cmac cipherInit key message :: CryptoFailable AuthTag of CryptoPassed tag -> putStrLn (show tag) CryptoFailed err -> putStrLn (show err) -- Incremental case cipherInit key :: CryptoFailable AES128 of CryptoPassed cipher -> do let ctx0 = initialize cipher let ctx1 = update ctx0 "chunk1" let ctx2 = update ctx1 "chunk2" let tag = finalize ctx2 return tag CryptoFailed err -> error (show err) ``` -------------------------------- ### AEAD Encryption Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-types.md Demonstrates AEAD encryption with authentication using AES128 in GCM mode. It shows how to initialize the AEAD state, append authenticated data (AAD), encrypt plaintext, and finalize with an authentication tag. ```haskell -- AEAD encryption with authentication let aead0 = aeadInit AEAD_GCM cipher iv :: CryptoFailable (AEAD AES128) case aead0 of CryptoPassed aead1 -> do let aead2 = aeadAppendHeader aead1 aad -- add AAD let (ciphertext, aead3) = aeadEncrypt aead2 plaintext let authTag = aeadFinalize aead3 return (ciphertext, authTag) CryptoFailed err -> error (show err) ``` -------------------------------- ### Poly1305 Incremental Authentication Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/mac-functions.md Demonstrates the incremental update process for Poly1305 authentication. Initialize with key and nonce, update with message chunks, and finalize to get the authentication tag. ```haskell import Crypto.MAC.Poly1305 import qualified Data.ByteString as BS let key = Poly1305.Key (BS.replicate 32 0xAA) let nonce = Poly1305.Nonce (BS.replicate 16 0xBB) let message = "message" -- Incremental let ctx0 = initialize key nonce let ctx1 = update ctx0 "chunk1" let ctx2 = update ctx1 "chunk2" let tag2 = finalize ctx2 ``` -------------------------------- ### Key Derivation Functions Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Documents various key derivation functions (KDFs) such as PBKDF2, Scrypt, Argon2, BCrypt, and HKDF. Includes details on parameters, usage examples, and recommendations. ```APIDOC ## Key Derivation Functions (KDFs) ### Description Details the implementation and usage of various key derivation functions, including password-based KDFs and HMAC-based extract-expand functions. ### Module `key-derivation.md` ### Supported KDFs - **PBKDF2**: RFC 2898 compliant, with custom PRF support. - **Scrypt**: Memory-hard password hashing. - **Argon2**: Modern ASIC/GPU-resistant password hashing. - **BCrypt**: Blowfish-based adaptive hashing. - **HKDF**: HMAC-based extract-expand key derivation. ### Usage - Parameters for each KDF. - Examples demonstrating KDF usage. - Recommendations for parameter selection. ``` -------------------------------- ### MonadRandom Example with StateT Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/random-generation.md Demonstrates using the MonadRandom typeclass within a StateT monad transformer, seeded with a ChaChaDRG. This allows for generating multiple sequences of random bytes within a single monadic action. ```haskell import Crypto.Random -- Use in StateT monad action :: MonadRandom m => m ByteString action = do bytes1 <- getRandomBytes 16 bytes2 <- getRandomBytes 32 return (bytes1 <> bytes2) -- Execute with DRG let seed = seedFromInteger 42 let (result, _) = runState (withDRG (drgNew seed)) action ``` -------------------------------- ### ChaCha20-Poly1305 Encryption and Decryption Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-implementations.md Demonstrates AEAD encryption and decryption using ChaCha20-Poly1305. It shows how to encrypt plaintext with additional authenticated data (AAD) and then decrypt it, verifying the authentication tag. ```haskell import Crypto.Cipher.ChaChaPoly1305 let key = BS.replicate 32 0xFF let nonce = BS.replicate 12 0x00 let aad = "additional data" let plaintext = "secret message" case encrypt key nonce aad plaintext of (ct, tag) -> do -- Transmit ct and tag case decrypt key nonce aad ct tag of Just pt -> assert (pt == plaintext) Nothing -> putStrLn "Auth failed" _ -> error "Init failed" ``` -------------------------------- ### Curve25519 Key Agreement Example Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/asymmetric-crypto.md Illustrates generating key pairs for Alice and Bob using Curve25519 and computing a shared secret using Diffie-Hellman. Requires a MonadRandom instance for key generation. ```haskell import Crypto.PubKey.Curve25519 import Crypto.Random -- Alice generates key pair aliceSecret <- generateSecretKey :: IO SecretKey let alicePub = toPublic aliceSecret -- Bob generates key pair bobSecret <- generateSecretKey :: IO SecretKey let bobPub = toPublic bobSecret -- Shared secret (both compute same value) let aliceShared = dh aliceSecret bobPub let bobShared = dh bobSecret alicePub assert (aliceShared == bobShared) ``` -------------------------------- ### Use GMP Library for Large Integer Operations Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Configure the build to use the GMP library for large integer operations. This optional optimization may improve performance for RSA and ECC operations, but requires the GMP library to be installed on the system. ```bash cabal configure --flag=integer-gmp ``` -------------------------------- ### AES Instantiation and Usage Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-implementations.md Demonstrates how to instantiate AES ciphers with different key sizes and use them in ECB and GCM modes. ```APIDOC ## AES Instantiation and Usage ### Description This section shows how to initialize AES ciphers with specific key sizes (AES128, AES192, AES256) and provides examples for using them in both block cipher mode (ECB) and Authenticated Encryption with Associated Data (AEAD) mode (GCM). ### Key Types ```haskell newtype AES128 = AES128 AES newtype AES192 = AES192 AES newtype AES256 = AES256 AES ``` ### Instantiation ```haskell instance Cipher AES128 where cipherName _ = "AES128" cipherKeySize _ = KeySizeFixed 16 instance Cipher AES192 where cipherName _ = "AES192" cipherKeySize _ = KeySizeFixed 24 instance Cipher AES256 where cipherName _ = "AES256" cipherKeySize _ = KeySizeFixed 32 instance BlockCipher AES128 instance BlockCipher AES192 instance BlockCipher AES256 instance BlockCipher128 AES128 instance BlockCipher128 AES192 instance BlockCipher128 AES256 ``` ### Supported Modes - **Block modes:** ECB, CBC, CFB, CTR - **AEAD modes:** GCM, OCB, CCM - **Disk modes:** XTS ### Example Usage ```haskell import Crypto.Cipher.AES import qualified Data.ByteString as BS -- Initialize AES128 let key = BS.replicate 16 0xFF let ctx = cipherInit key :: CryptoFailable AES128 case ctx of CryptoPassed cipher -> do -- ECB mode let plaintext = BS.replicate 32 0x42 let ciphertext = ecbEncrypt cipher plaintext return ciphertext CryptoFailed err -> error (show err) -- GCM mode case ctx of CryptoPassed cipher -> do let iv = makeIV (BS.replicate 12 0) case (iv, aeadInit AEAD_GCM cipher (BS.replicate 12 0)) of (Just iv', CryptoPassed aead) -> do let aead2 = aeadAppendHeader aead aad let (ct, aead3) = aeadEncrypt aead2 plaintext let tag = aeadFinalize aead3 return (ct, tag) _ -> error "Init failed" _ -> error "Cipher init failed" ``` ### Constants | Key Size | Variant | Block Size | |------------|---------|-----------| | 16 bytes | AES128 | 16 bytes | | 24 bytes | AES192 | 16 bytes | | 32 bytes | AES256 | 16 bytes | ``` -------------------------------- ### Initialize Cipher with ByteArray Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Demonstrates initializing a cipher using a ByteArray for key material. Ensure the key size is appropriate for the chosen cipher. ```haskell cipherInit :: Cipher -> KeySize -> ByteArray -> CipherInit cipherInit cipher keySize key = cipherInit cipher keySize (toCipherInit key) ``` -------------------------------- ### Create Seed from Binary Data Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Shows how to create a seed from a ByteArray. ```haskell seedFromBinary :: ByteArray -> Seed seedFromBinary ba = seedFromBinary (toSeed ba) ``` -------------------------------- ### Build Configuration and Compilation Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Explains the build configuration options, including Cabal build flags (e.g., `support_aesni`), platform-specific behavior, tested compiler versions, and dependencies. ```APIDOC ## Build Configuration and Compilation ### Description Provides information on how to configure and compile the crypton library, including build flags, platform support, and dependencies. ### Module `configuration.md` ### Cabal Build Flags - Examples: `support_aesni`, `support_rdrand`, `support_sse`. ### Platform Support - Behavior specific to Linux, Windows, macOS, iOS. ### Compiler Support - Tested GHC versions (e.g., 9.2-9.12). ### Dependencies - Required and optional dependencies. ### Performance Tuning - Recommendations for optimizing build configurations. ``` -------------------------------- ### Use DRG within MonadRandom Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Example of using a DRG within the MonadRandom typeclass for random operations. ```haskell withDRG :: DRG -> MonadRandom m => m a -> m a withDRG drg m = withDRG drg m ``` -------------------------------- ### Parametric Prefix-hashing Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Shows how to use hashPrefixWith for prefix-hashing with custom configurations. ```haskell hashPrefixWith :: Hash -> ByteArray -> Digest hashPrefixWith = hashPrefixWith ``` -------------------------------- ### Get System DRG for Production Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Illustrates obtaining a non-deterministic random number generator from the system, suitable for production environments. ```haskell getSystemDRG :: IO DRG getSystemDRG = getSystemDRG ``` -------------------------------- ### Catching Crypton Exceptions Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/errors.md Use Control.Exception.try to catch exceptions thrown by Crypton functions. This example demonstrates catching a specific CryptoError_KeySizeInvalid. ```haskell import Control.Exception as E import Crypto.Error main :: IO () main = do result <- E.try (throwCryptoErrorIO (cipherInit key)) case result of Right cipher -> putStrLn "Success" Left err@CryptoError_KeySizeInvalid -> putStrLn "Bad key" Left err -> putStrLn ("Error: " ++ show err) ``` -------------------------------- ### Portable Build Configuration Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Configure a portable build for all platforms using default C implementations. This is the standard build without any special flags. ```bash cabal configure cabal build ``` -------------------------------- ### Scrypt Parameters and Generation Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/key-derivation.md Defines the parameters for Scrypt and demonstrates how to generate a derived key. Ensure salt is random and output length is sufficient. ```haskell data Parameters = Parameters { scryptN :: Int -- ^ CPU/memory cost (2^N) , scryptR :: Int -- ^ block size , scryptP :: Int -- ^ parallelization , scryptSaltLen :: Int -- ^ salt length in bytes , scryptOutputLen :: Int -- ^ output length in bytes } ``` ```haskell generate :: (ByteArrayAccess password, ByteArrayAccess salt, ByteArray ba) => Parameters -> password -> salt -> ba ``` ```haskell import Crypto.KDF.Scrypt import qualified Data.ByteString as BS let password = "password" :: ByteString let salt = BS.replicate 32 0x01 -- 32 random bytes let params = Parameters { scryptN = 14 -- 2^14 = 16384 cost , scryptR = 8 , scryptP = 1 , scryptSaltLen = 32 , scryptOutputLen = 64 -- 64 bytes output } let derivedKey = generate params password salt :: ByteString ``` -------------------------------- ### RSA OAEP Encryption and Decryption Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/asymmetric-crypto.md Example of encrypting a message using RSA with OAEP padding and decrypting it with the corresponding private key. Requires a random seed for both operations. ```haskell import Crypto.PubKey.RSA.OAEP import Crypto.Hash (SHA256) import Crypto.Random -- Encrypt seed <- getRandomBytes 32 let ciphertext = encrypt pubKey plaintext seed :: ByteString -- Decrypt case decrypt privKey ciphertext seed of Right plaintext -> putStrLn "Decrypted" Left err -> putStrLn err ``` -------------------------------- ### Initializing AEAD GCM Mode Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-types.md Demonstrates the process of initializing a cipher context and then setting up an AEAD mode, specifically GCM, for use in authenticated encryption or decryption. Handles potential initialization failures. ```haskell import Crypto.Cipher.Types -- Initialize GCM mode let cipher = cipherInit key :: CryptoFailable AES128 case cipher of CryptoPassed ctx -> do let aead = aeadInit AEAD_GCM ctx iv case aead of CryptoPassed state -> ... -- use GCM CryptoFailed err -> error (show err) _ -> error "Cipher init failed" ``` -------------------------------- ### Initialize AES128 Cipher Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-types.md Demonstrates initializing an AES128 cipher context using a 16-byte key and checking its name. Requires importing AES and Types modules. ```haskell import Crypto.Cipher.AES import Crypto.Cipher.Types import Data.ByteString (pack) -- Initialize AES128 with 16-byte key let keyBytes = pack [0x00..0x0F] :: ByteString cipher = cipherInit keyBytes :: CryptoFailable AES128 -- Check cipher name case cipher of CryptoPassed ctx -> putStrLn (cipherName ctx) -- prints "AES128" CryptoFailed err -> error (show err) ``` -------------------------------- ### Initialize AES with Key Validation Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/errors.md Demonstrates initializing an AES cipher with a key and handling potential validation errors, such as an invalid key size. Use this pattern when you need to ensure the key meets the cipher's requirements before proceeding. ```haskell import Crypto.Cipher.AES import Crypto.Error initAES :: ByteString -> Either CryptoError AES128 initAES key = let result = cipherInit key :: CryptoFailable AES128 in eitherCryptoError result -- Usage case initAES myKey of Right cipher -> encryptData cipher plaintext Left CryptoError_KeySizeInvalid -> putStrLn "Key must be 16 bytes" Left err -> putStrLn ("Unexpected: " ++ show err) ``` -------------------------------- ### Flexible Key Derivation Output Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Highlights that key derivation supports outputs of any size. ```haskell deriveKey :: Parameters -> ByteArray -> ByteArray -> Int -> ByteArray deriveKey = deriveKey ``` -------------------------------- ### Authenticate and Encrypt Data Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/mac-functions.md Example of authenticating plaintext with HMAC and then encrypting it using AES. This pattern ensures both data integrity and confidentiality. Note the placeholder for cipher and IV handling. ```haskell import Crypto.MAC.HMAC import Crypto.Cipher.AES import Crypto.Hash (SHA256) import qualified Data.ByteString as BS authenticateAndEncrypt :: ByteString -> ByteString -> IO (ByteString, ByteString) authenticateAndEncrypt key plaintext = do -- Encrypt let cipher = cipherInit key :: CryptoFailable AES128 let iv = makeIV (BS.replicate 16 0) :: Maybe (IV AES128) -- Case would go here for unpacking cipher and iv -- Authenticate let mac = hmac SHA256 key plaintext :: HMAC SHA256 return (ciphertext, show mac) ``` -------------------------------- ### High-Performance x86_64 Linux/BSD Build Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Configure a high-performance build for x86_64 Linux/BSD systems by enabling CPU-specific optimizations like AES-NI, RDRAND, PCLMULQDQ, and SSE. This requires compatible hardware. ```bash cabal configure \ --flag=support_aesni \ --flag=support_rdrand \ --flag=support_pclmuldq \ --flag=support_sse cabal build ``` -------------------------------- ### Get Random Bytes from System Entropy Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/random-generation.md Use this pattern to quickly obtain random bytes from the system's entropy source for general-purpose use. Requires importing Crypto.Random. ```haskell import Crypto.Random -- Get random bytes from system entropy main :: IO () main = do bytes <- withDRG <$> getSystemDRG <*> pure (getRandomBytes 32) print bytes ``` -------------------------------- ### Get and Use SystemDRG Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/random-generation.md Obtain a thread-safe, non-deterministic SystemDRG wrapper around system entropy. This generator can be used directly within the IO monad to produce random bytes. ```haskell import Crypto.Random -- Get system RNG sdrg <- getSystemDRG -- Use in IO bytes <- withDRG sdrg (getRandomBytes 32) ``` -------------------------------- ### Context Data Type and Functions Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/hash-functions.md Represents a mutable hash computation context. Use `hashInit` to create a context, `hashUpdate` or `hashUpdates` to process data, and `hashFinalize` to get the digest. ```haskell data Context a hashInit :: HashAlgorithm a => Context a hashUpdate :: (ByteArrayAccess ba, HashAlgorithm a) => Context a -> ba -> Context a hashUpdates :: (ByteArrayAccess ba, HashAlgorithm a) => Context a -> [ba] -> Context a hashFinalize :: HashAlgorithm a => Context a -> Digest a hashBlockSize :: HashAlgorithm a => Context a -> Int hashDigestSize :: HashAlgorithm a => Context a -> Int ``` -------------------------------- ### Cabal Configure for Speed Optimizations Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Use these flags with 'cabal configure' to enable optimizations for maximum speed. This includes enabling specific hardware acceleration features. ```bash cabal configure --enable-optimizations \ --flag=support_aesni \ --flag=support_rdrand \ --flag=support_pclmuldq \ --flag=support_sse ``` -------------------------------- ### Parametric Hashing Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Demonstrates using hashWith for custom hashing configurations. ```haskell hashWith :: Hash -> ByteArray -> Digest hashWith = hashWith ``` -------------------------------- ### MonadPseudoRandom Stack Operations Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/random-generation.md Utilize `MonadPseudoRandom` (an alias for `StateT DRG IO`) for random computations within a monad stack. This example shows generating and combining random byte sequences. ```haskell import Control.Monad.State import Crypto.Random action :: MonadPseudoRandom ChaChaDRG ByteString action = do bytes1 <- getRandomBytes 16 bytes2 <- getRandomBytes 16 return (bytes1 <> bytes2) main :: IO () main = do seed <- seedNew let drg = drgNew seed (result, _) <- runStateT action drg return result ``` -------------------------------- ### Create Seed from Integer Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Illustrates creating a seed from an Integer. ```haskell seedFromInteger :: Integer -> Seed seedFromInteger i = seedFromInteger (toSeed i) ``` -------------------------------- ### PBKDF2 Parameters for Key Derivation Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/types.md Defines parameters for PBKDF2, including iteration counts and output length. Higher iteration counts increase security but also computation time. ```haskell data Parameters = Parameters { iterCounts :: Int -- ^ iterations (e.g., 100000) , outputLength :: Int -- ^ output bytes (e.g., 32) } ``` -------------------------------- ### Import EntropyPool Module Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/random-generation.md Import the EntropyPool module from Crypto.Random.EntropyPool for applications needing continuous entropy mixing, fallback entropy sources, or multi-channel entropy. ```haskell import Crypto.Random.EntropyPool ``` -------------------------------- ### ChaCha20 Instantiation Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-implementations.md Demonstrates how to instantiate the ChaCha20 cipher with a given key. This snippet shows the type signature and the instance declarations for the Cipher and StreamCipher typeclasses. ```haskell instance Cipher ChaCha20 where cipherName _ = "ChaCha20" cipherKeySize _ = KeySizeFixed 32 instance StreamCipher ChaCha20 ``` -------------------------------- ### Run Benchmarks Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Execute the benchmark suite for Crypton using the 'gauge' library. This command runs benchmarks for various cryptographic algorithms and operations. ```bash cabal bench ``` -------------------------------- ### Create New Seed Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Demonstrates creating a new seed for random number generation. ```haskell seedNew :: IO Seed seedNew = seedNew ``` -------------------------------- ### Entropy-based Key Derivation (HKDF) Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/README.md Shows the HKDF extract-expand pattern for deriving keys from entropy sources. ```haskell hkdfExtractExpand :: Hash -> ByteArray -> ByteArray -> ByteArray -> ByteArray hkdfExtractExpand = hkdfExtractExpand ``` -------------------------------- ### Handle Invalid Key Initialization Error Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/errors.md Demonstrates how to catch a specific `CryptoFailed` error during AES initialization and provide a more informative error message. ```haskell case cipherInit key of CryptoFailed err -> error ("AES init with 32-byte key: " ++ show err) CryptoPassed cipher -> use cipher ``` -------------------------------- ### Seed from File for Random Generation Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/random-generation.md This pattern demonstrates how to load a random seed from a file for persistent storage or reproducible random sequences. It handles potential errors during seed loading. ```haskell import Crypto.Random import qualified Data.ByteString as BS -- Load seed from persistent storage loadSeed :: FilePath -> IO Seed loadSeed path = do bytes <- BS.readFile path case seedFromBinary bytes of CryptoPassed s -> return s CryptoFailed e -> error (show e) -- Save seed saveSeed :: FilePath -> Seed -> IO () saveSeed path seed = BS.writeFile path (BA.convert seed) ``` -------------------------------- ### Enable SSE Optimizations for BLAKE2 and Argon2 Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Enable SSE optimizations (SSE2/SSE4 SIMD instructions) for BLAKE2 and Argon2 hash and KDF functions. This flag primarily benefits x86_64 platforms. ```bash cabal configure --flag=support_sse ``` -------------------------------- ### Parametric Interface Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/hash-functions.md This interface allows for selecting the hashing algorithm at runtime. It provides functions to initialize a hash context, hash a bytestring with a specified algorithm, and hash a prefix of a bytestring with a specified algorithm. ```APIDOC ## Parametric Interface Allows selecting algorithm at runtime. ### `hashInitWith` - **Type Signature**: `HashAlgorithm alg => alg -> Context alg` - **Description**: Initializes a hash context with the specified algorithm. ### `hashWith` - **Type Signature**: `(ByteArrayAccess ba, HashAlgorithm alg) => alg -> ba -> Digest alg` - **Description**: Hashes a bytestring using the specified algorithm. ### `hashPrefixWith` - **Type Signature**: `(ByteArrayAccess ba, HashAlgorithmPrefix alg) => alg -> ba -> Int -> Digest alg` - **Description**: Hashes the first N bytes of a bytestring using the specified algorithm (constant-time). ### Example Usage ```haskell -- Runtime algorithm selection data MyAlgorithm = UseSHA256 | UseSHA512 selectHash :: MyAlgorithm -> BS.ByteString -> String selectHash UseSHA256 input = show (hashWith SHA256 input :: Digest SHA256) selectHash UseSHA512 input = show (hashWith SHA512 input :: Digest SHA512) ``` ``` -------------------------------- ### Module Imports for Hashing Algorithms Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/hash-functions.md Imports necessary modules for using various hashing algorithms provided by the Crypton library. `Crypto.Hash.Algorithms` provides access to all algorithm types like SHA1, SHA256, Blake2b_256, etc. ```haskell import Crypto.Hash import Crypto.Hash.Algorithms -- All algorithm types: SHA1, SHA256, Blake2b_256, etc. ``` -------------------------------- ### KeyedBlake2 Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/mac-functions.md KeyedBlake2 provides a MAC functionality using the BLAKE2 hash algorithm with key material. It offers advantages like speed on some platforms, variable-length output, and a NIST-approved design. ```APIDOC ## KeyedBlake2 **Module:** `Crypto.MAC.KeyedBlake2` BLAKE2 hash with key material (acts as MAC). ### Functions ```haskell -- Initialize with key hashInitWith :: ByteArrayAccess key => key -> Context a update :: ByteArrayAccess ba => Context a -> ba -> Context a updates :: ByteArrayAccess ba => Context a -> [ba] -> Context a finalize :: Context a -> Digest a -- One-shot hmac :: (ByteArrayAccess key, ByteArrayAccess ba, HashAlgorithm a) => a -> key -> ba -> Digest a ``` **Example:** ```haskell import Crypto.MAC.KeyedBlake2 import Crypto.Hash (Blake2b_256) import qualified Data.ByteString as BS let key = BS.replicate 32 0x77 let message = "data" -- One-shot let tag = hmac Blake2b_256 key message :: Digest Blake2b_256 -- Incremental let ctx0 = hashInitWith key :: Context Blake2b_256 let ctx1 = update ctx0 "part1" let ctx2 = update ctx1 "part2" let result = finalize ctx2 ``` **Advantages:** - Faster than HMAC on some platforms - Variable-length output (Blake2 digest size) - NIST-approved design --- ``` -------------------------------- ### Checking Key Size Validity Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-types.md Demonstrates how to check if a given key size conforms to the specification defined by a KeySizeSpecifier. This is useful for validating user-provided key lengths before cryptographic operations. ```haskell -- Check if a key size is valid let keySpec = cipherKeySize (undefined :: AES256) -- KeySizeFixed 32 case keySpec of KeySizeFixed n -> putStrLn ("Requires exactly " ++ show n ++ " bytes") KeySizeRange a b -> putStrLn ("Accepts " ++ show a ++ "-" ++ show b ++ " bytes") KeySizeEnum sizes -> putStrLn ("Accepts: " ++ show sizes) ``` -------------------------------- ### AES-OCB Initialization Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-implementations.md Initializes AES in Offset Codebook Mode (OCB). Requires a cipher and an initialization vector (nonce). ```haskell case aeadInit AEAD_OCB cipher (BS.replicate 15 0) of CryptoPassed aead -> ... _ -> error "Not supported" ``` -------------------------------- ### Run Test Suite Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/configuration.md Execute the test suite for Crypton. This command runs Known Answer Tests (KAT) and other tests for all implemented cryptographic algorithms and modes. ```bash cabal test ``` -------------------------------- ### AES-GCM Initialization Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-implementations.md Initializes AES in Galois/Counter Mode (GCM). Requires a key and an initialization vector (nonce). Handles potential initialization failures. ```haskell let ctx = cipherInit key :: CryptoFailable AES128 case ctx of CryptoPassed cipher -> case aeadInit AEAD_GCM cipher (BS.replicate 12 0) of CryptoPassed aead -> ... -- use aead CryptoFailed err -> error (show err) _ -> error "Failed" ``` -------------------------------- ### Scrypt Parameters for Key Derivation Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/types.md Defines parameters for Scrypt key derivation, including CPU cost (N), block size (r), parallelization (p), salt length, and output length. ```haskell data Parameters = Parameters { scryptN :: Int -- ^ CPU cost (2^N) , scryptR :: Int -- ^ block size , scryptP :: Int -- ^ parallelization , scryptSaltLen :: Int -- ^ salt bytes , scryptOutputLen :: Int -- ^ output bytes } ``` -------------------------------- ### Quick Hash Functions Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/hash-functions.md These functions provide one-shot hashing without requiring manual context management. They are suitable for hashing entire bytestrings, lazy bytestrings, or a prefix of a bytestring in a constant-time manner. ```APIDOC ## Quick Hash Functions One-shot hashing without manual context management. ### `hash` - **Type Signature**: `(ByteArrayAccess ba, HashAlgorithm a) => ba -> Digest a` - **Description**: Hash entire bytestring. ### `hashlazy` - **Type Signature**: `HashAlgorithm a => L.ByteString -> Digest a` - **Description**: Hash lazy bytestring. ### `hashPrefix` - **Type Signature**: `(ByteArrayAccess ba, HashAlgorithmPrefix a) => ba -> Int -> Digest a` - **Description**: Hash first N bytes (constant-time). ### Example Usage ```haskell import Crypto.Hash import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL -- Quick SHA256 let d1 = hash ("hello" :: BS.ByteString) :: Digest SHA256 -- From lazy bytestring let lazyData = BSL.pack [1..1000] let d2 = hashlazy lazyData :: Digest SHA256 -- Partial hash (first 100 bytes only, constant-time) let d3 = hashPrefix ("secret" :: BS.ByteString) 100 :: Digest SHA512 ``` ``` -------------------------------- ### PBKDF2 Parameters Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/types.md Parameters for the PBKDF2 key derivation function, specifying the number of iterations and the desired output length in bytes. ```APIDOC ## PBKDF2 Parameters ### Description Defines the configuration for the PBKDF2 key derivation function, controlling the computational cost and the size of the derived key. ### Module `Crypto.KDF.PBKDF2` ### Type Definition ```haskell data Parameters = Parameters { iterCounts :: Int -- ^ iterations (e.g., 100000) , outputLength :: Int -- ^ output bytes (e.g., 32) } ``` ### Fields | Field | Type | Range | Notes | |-------|------|-------|-------| | `iterCounts` | `Int` | 4000+ | More = slower, safer | | `outputLength` | `Int` | 16+ | Output bytes | ``` -------------------------------- ### CAST5 Cipher Instantiation Source: https://github.com/kazu-yamamoto/crypton/blob/main/_autodocs/api-reference/cipher-implementations.md Provides the Cipher instance for CAST5, specifying its key size range (5-16 bytes). ```haskell instance Cipher CAST5 where cipherKeySize _ = KeySizeRange 5 16 instance BlockCipher CAST5 ```