    -- Cryptonite.hs: shim for cryptonite
    -- Copyright © 2016  Clint Adams
    -- This software is released under the terms of the Expat license.
    -- (See the LICENSE file).
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE PackageImports #-}
    {-# LANGUAGE UndecidableInstances #-}

    module Codec.Encryption.OpenPGP.Internal.Cryptonite
      ( HOWrappedCCT(..)
      ) where

    import Control.Error.Util (note)
    import qualified "cryptonite" Crypto.Cipher.Types as CCT
    import qualified Crypto.Error as CE
    import Data.Bifunctor (bimap)
    import qualified Data.ByteString as B

    import Codec.Encryption.OpenPGP.Internal.HOBlockCipher

    newtype HOWrappedCCT a =
      HWCCT a

    instance CCT.BlockCipher cipher => HOBlockCipher (HOWrappedCCT cipher) where
      cipherInit = bimap show HWCCT . CE.eitherCryptoError . CCT.cipherInit
      cipherName (HWCCT c) = CCT.cipherName c
      cipherKeySize (HWCCT c) = CCT.cipherKeySize c
      blockSize (HWCCT c) = CCT.blockSize c
      cfbEncrypt (HWCCT c) iv bs =
        hammerIV iv >>= \i -> return (CCT.cfbEncrypt c i bs)
      cfbDecrypt (HWCCT c) iv bs =
        hammerIV iv >>= \i -> return (CCT.cfbDecrypt c i bs)

    hammerIV ::
         CCT.BlockCipher cipher => B.ByteString -> Either String (CCT.IV cipher)
    hammerIV = note "cryptonite bad IV" . CCT.makeIV