-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | TripleSec is a simple, triple-paranoid, symmetric encryption library -- -- Additional details about this protocol can be found at the official -- website: https://keybase.io/triplesec -- -- A tutorial for how to use this library can be found in -- Crypto.TripleSec.Tutorial @package triplesec @version 0.1.2.0 -- | TripleSec is a simple, triple-paranoid, symmetric encryption library. -- -- https://keybase.io/triplesec/ -- -- A tutorial for how to use this library can be found in -- Crypto.TripleSec.Tutorial module Crypto.TripleSec -- | TripleSec cipher used for encryption and decryption. -- -- Dealing with this type is only necessary if you wish to use the -- somewhat lower-level API consisting of encryptWithCipher and -- decryptWithCipher. -- -- You can create a TripleSec cipher with newCipher or -- newCipherWithSalt. data TripleSec ba -- | Represents the action of encrypting and decrypting with the TripleSec -- protocol. -- -- Fully implemented with default functions. Any instances must provide a -- source of randomness and be an instance of CanTripleSecDecrypt. class (CanTripleSecDecrypt m, MonadRandom m) => CanTripleSec m where encrypt pass plaintext = do { cipher <- newCipher pass; encryptWithCipher cipher plaintext } encryptWithCipher cipher plaintext = do { when (length plaintext == 0) $ throwError $ EncryptionException ZeroLengthPlaintext; let prefix = packedMagicBytes <> packedVersionBytes <> passwordSalt cipher; ivs <- getRandomBytes totalIvLen; let (aesIv, lessAesIv) = splitAt ivLen ivs; let (twoFishIv, xSalsaIv) = splitAt ivLen lessAesIv; let xSalsaCipher = initialize 20 (xSalsa cipher) xSalsaIv; let xSalsaEncrypted = xSalsaIv <> xSalsaCombine xSalsaCipher plaintext; let twoFishEncrypted = twoFishIv <> ctrCombine (twoFish cipher) (fromJust $ makeIV twoFishIv) xSalsaEncrypted; let aesEncrypted = aesIv <> ctrCombine (aes cipher) (fromJust $ makeIV aesIv) twoFishEncrypted; let sha3HMACed = hmacKeccak512 cipher $ prefix <> aesEncrypted; let sha512HMACed = hmacSHA512 cipher $ prefix <> aesEncrypted; return $ prefix <> sha512HMACed <> sha3HMACed <> aesEncrypted } newCipher pass = do { salt <- getRandomBytes saltLen; newCipherWithSalt pass salt } -- | Encrypt a plaintext with a passphrase. -- --
-- encrypt passphrase plaintext --encrypt :: (CanTripleSec m, ByteArray ba) => ba -> ba -> m ba -- | Encrypt a plaintext with a TripleSec cipher. -- -- This function allows encrypting multiple plaintexts without -- continually paying for the expensive key-derivation process. Please -- consider your use case and any risks that come from repeated usage of -- the same salt for encrypting different pieces of information. -- -- For a simpler alternative, please see encrypt. encryptWithCipher :: (CanTripleSec m, ByteArray ba) => TripleSec ba -> ba -> m ba -- | Create a new TripleSec cipher. newCipher :: (CanTripleSec m, ByteArray ba) => ba -> m (TripleSec ba) -- | Represents the action of decrypting with the TripleSec protocol. -- -- Fully implemented with default functions. Any instances must provide a -- way to represent failure with a TripleSecException. class (MonadError TripleSecException m) => CanTripleSecDecrypt m where decrypt pass cipherText = do { (prefix, providedSalt, lessPrefix) <- checkPrefix cipherText; decryptor <- newCipherWithSalt pass providedSalt; decryptCommon decryptor prefix lessPrefix } decryptWithCipher cipher cipherText = do { (prefix, providedSalt, lessPrefix) <- checkPrefix cipherText; checkCipher cipher providedSalt; decryptCommon cipher prefix lessPrefix } newCipherWithSalt pass salt = do { checkSalt salt; when (length pass == 0) $ throwError $ CipherInitException ZeroLengthPassword; let dk = generate paramsScrypt pass salt; let macKeys = take (macKeyLen * 2) dk; let sha512Key = take macKeyLen macKeys; let keccak512Key = drop macKeyLen macKeys; let cipherKeys = drop (macKeyLen * 2) dk; let aesKey = take cipherKeyLen cipherKeys; let twoFishKey = take cipherKeyLen $ drop cipherKeyLen cipherKeys; let xSalsaKey = drop (cipherKeyLen * 2) cipherKeys; let twoFishCipher = trustedCipherInit twoFishKey; let aesCipher = trustedCipherInit aesKey; return (TripleSec {passwordSalt = salt, hmacKeccak512 = convert . (hmac keccak512Key :: ByteArray ba => ba -> HMAC Keccak_512), hmacSHA512 = convert . (hmac sha512Key :: ByteArray ba => ba -> HMAC SHA512), aes = aesCipher, twoFish = twoFishCipher, xSalsa = xSalsaKey}) } -- | Decrypt a ciphertext with a passphrase. -- --
-- decrypt passphrase ciphertext --decrypt :: (CanTripleSecDecrypt m, ByteArray ba) => ba -> ba -> m ba -- | Decrypt a ciphertext with a TripleSec cipher. -- -- This function allows decrypting multiple ciphertexts without -- continually paying for the expensive key-derivation process. This -- function will only work if the given cipher's salt matches that of the -- ciphertext, otherwise it throws a MisMatchedCipherSalt. -- -- For a simpler alternative, please see decrypt. decryptWithCipher :: (CanTripleSecDecrypt m, ByteArray ba) => TripleSec ba -> ba -> m ba -- | Create a new TripleSec cipher with a provided salt. -- -- Creating a cipher with a specific salt is useful if you know you have -- several ciphertexts to decrypt, all of which were encrypted with the -- same cipher (salt + passphrase). Creating the cipher once up front -- allows you to save time, cpu, and memory by avoiding the expensive -- key-derivation on subsequent decryptions. -- --
-- newCipherWithSalt passphrase salt --newCipherWithSalt :: (CanTripleSecDecrypt m, ByteArray ba) => ba -> ba -> m (TripleSec ba) -- | Exceptions thrown by this library. data TripleSecException CipherInitException :: CipherInitFailure -> TripleSecException EncryptionException :: EncryptionFailure -> TripleSecException DecryptionException :: DecryptionFailure -> TripleSecException -- | Possible cipher initialization failures data CipherInitFailure ZeroLengthPassword :: CipherInitFailure InvalidSaltLength :: CipherInitFailure -- | Possible encryption failures data EncryptionFailure ZeroLengthPlaintext :: EncryptionFailure -- | Possible decryption Failures data DecryptionFailure InvalidCipherTextLength :: DecryptionFailure InvalidMagicBytes :: DecryptionFailure InvalidVersion :: DecryptionFailure InvalidSha512Hmac :: DecryptionFailure InvalidKeccakHmac :: DecryptionFailure MisMatchedCipherSalt :: DecryptionFailure -- | encrypt specialized to IO. Throws instead of returning a -- TripleSecException. encryptIO :: (ByteArray ba) => ba -> ba -> IO ba -- | decrypt specialized to IO. Throws instead of returning a -- TripleSecException. decryptIO :: ByteArray ba => ba -> ba -> IO ba -- | newCipher specialized to IO. Throws instead of returning -- a TripleSecException. newCipherIO :: ByteArray ba => ba -> IO (TripleSec ba) -- | newCipherWithSalt specialized to IO. Throws instead of -- returning a TripleSecException. newCipherWithSaltIO :: ByteArray ba => ba -> ba -> IO (TripleSec ba) -- | encryptWithCipher specialized to IO. Throws instead of -- returning a TripleSecException. encryptWithCipherIO :: ByteArray ba => TripleSec ba -> ba -> IO ba -- | decryptWithCipher specialized to IO. Throws instead of -- returning a TripleSecException. decryptWithCipherIO :: ByteArray ba => TripleSec ba -> ba -> IO ba -- | Monad that works "out of the box" for encrypting/decrypting. -- -- Does not throw exceptions (returns Either TripleSecException -- ba). Use with runTripleSecIO. type TripleSecIOM = TripleSecIOT IO -- | Monad transformer for use with any IO based monad stack. -- -- Does not throw exceptions (returns Either TripleSecException -- a). Use with runTripleSecIO. data TripleSecIOT m a -- | Evaluate a TripleSecIOT computation. runTripleSecIO :: TripleSecIOT m a -> m (Either TripleSecException a) -- | Monad that works "out of the box" for pure encrypting/decrypting. -- -- Use with runTripleSecM or evalTripleSecM. -- SystemDRG can be obtained with getSystemDRG. type TripleSecM = TripleSecT Identity -- | Monad transformer for use with any non-IO based monad stack (See -- TripleSecIOT for IO based stacks). -- -- Use with runTripleSecT or evalTripleSecT. -- SystemDRG can be obtained with getSystemDRG. data TripleSecT m a -- | A referentially transparent System representation of the random -- evaluated out of the system. -- -- Holding onto a specific DRG means that all the already evaluated bytes -- will be consistently replayed. -- -- There's no need to reseed this DRG, as only pure entropy is -- represented here. data SystemDRG :: * -- | Grab one instance of the System DRG getSystemDRG :: IO SystemDRG -- | Evaluate a TripleSecM computation. -- -- If you have no use for the output SystemDRG. See -- evalTripleSecM. runTripleSecM :: TripleSecM a -> SystemDRG -> (Either TripleSecException a, SystemDRG) -- | Evaluate a TripleSecM computation. -- -- Do NOT re-use the input SystemDRG (very bad!). See -- runTripleSecM for an output SystemDRG that's safe to use -- elsewhere. evalTripleSecM :: TripleSecM a -> SystemDRG -> Either TripleSecException a -- | Evaluate a TripleSecT computation. -- -- If you have no use for the output SystemDRG. See -- evalTripleSecT. runTripleSecT :: TripleSecT m a -> SystemDRG -> m (Either TripleSecException a, SystemDRG) -- | Evaluate a TripleSecT computation. -- -- Do NOT re-use the input SystemDRG (very bad!). See -- runTripleSecT for an output SystemDRG that's safe to use -- elsewhere. evalTripleSecT :: Functor m => TripleSecT m a -> SystemDRG -> m (Either TripleSecException a) -- | Monad that works "out of the box" for pure decrypting only. -- -- Use with runTripleSecDecryptM. Useful as it does not require a -- source of randomness. type TripleSecDecryptM = TripleSecDecryptT Identity -- | Monad transformer for decryption only with any non-IO based monad -- stack (See TripleSecIOT for IO based stacks as it's -- more powerful and just as easy to use). -- -- Use with runTripleSecDecryptT. Useful as it does not require a -- source of randomness. data TripleSecDecryptT m a -- | Evaluate a TripleSecDecryptM computation. runTripleSecDecryptM :: TripleSecDecryptM a -> Either TripleSecException a -- | Evaluate a TripleSecDecryptT computation. runTripleSecDecryptT :: TripleSecDecryptT m a -> m (Either TripleSecException a) -- | Utility function to check that ciphertext is structurally valid and -- encrypted with a supported TripleSec version. -- -- This function can be used for extracting the salt from a ciphertext to -- build a cipher with newCipherWithSalt. If you know you've -- encrypted many things with the same cipher this lets you decrypt them -- all without continually paying for the expensive key-derivation. -- -- The only potentially useful output as a consumer of this library is -- the salt. checkPrefix :: (ByteArray ba, MonadError TripleSecException m) => ba -> m (ba, ba, ba) -- | Utility function to check salt length. checkSalt :: (ByteArray ba, MonadError TripleSecException m) => ba -> m () -- | Utility function to check that the provided TripleSec was built -- with the provided salt. -- -- This function does not confirm anything about the passphrase -- provided when the TripleSec cipher was created or the -- passphrase used to encrypt a ciphertext where the salt came from. checkCipher :: (ByteArray ba, MonadError TripleSecException m) => TripleSec ba -> ba -> m () module Crypto.TripleSec.Tutorial