Fix padding
This commit is contained in:
parent
55f1382401
commit
2518872872
@ -1,3 +1,7 @@
|
||||
# 0.3.0.0
|
||||
- Better exception type (does no longer leak private information)
|
||||
- 'Data.CryptoID.Poly' now supports padding the plaintext to a certain length before encryption
|
||||
|
||||
# 0.2.0.0
|
||||
- Rename 'Data.CryptoID.Poly' to 'Data.CryptoID.ByteString'
|
||||
- Introduce 'Data.CryptoID.Poly' doing actual serialization
|
||||
@ -12,3 +16,4 @@
|
||||
# 0.0.0
|
||||
|
||||
First published version
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
name: cryptoids
|
||||
version: 0.2.0.0
|
||||
version: 0.3.0.0
|
||||
synopsis: Reversable and secure encoding of object ids as a bytestring
|
||||
license: BSD3
|
||||
license-file: LICENSE
|
||||
|
||||
@ -29,6 +29,7 @@ import Data.Binary.Put
|
||||
import Data.Binary.Get
|
||||
|
||||
import Data.ByteString (ByteString)
|
||||
import qualified Data.ByteString as ByteString
|
||||
import qualified Data.ByteString.Char8 as ByteString.Char
|
||||
|
||||
import qualified Data.ByteString.Lazy as Lazy (ByteString)
|
||||
@ -100,10 +101,19 @@ instance Binary CryptoIDKey where
|
||||
|
||||
|
||||
-- | Error cases that can be encountered during 'encrypt' and 'decrypt'
|
||||
--
|
||||
-- Care has been taken to ensure that presenting values of 'CryptoIDError' to an
|
||||
-- attacker leaks no plaintext (it does leak information about the length of the
|
||||
-- plaintext).
|
||||
data CryptoIDError
|
||||
= AlgorithmError CryptoError
|
||||
-- ^ One of the underlying cryptographic algorithms
|
||||
-- ('CryptoHash' or 'CryptoCipher') failed.
|
||||
| PlaintextIsWrongLength Int
|
||||
-- ^ The length of the plaintext is not a multiple of the block size of
|
||||
-- 'CryptoCipher'
|
||||
--
|
||||
-- The length of the offending plaintext is included.
|
||||
| NamespaceHashIsWrongLength ByteString
|
||||
-- ^ The length of the digest produced by 'CryptoHash' does
|
||||
-- not match the block size of 'CryptoCipher'.
|
||||
@ -112,10 +122,12 @@ data CryptoIDError
|
||||
--
|
||||
-- This error should not occur and is included primarily
|
||||
-- for sake of totality.
|
||||
| CiphertextConversionFailed
|
||||
-- ^ The produced 'ByteString' is the wrong length for conversion into a
|
||||
-- ciphertext.
|
||||
| DeserializationError (Lazy.ByteString, ByteOffset, String)
|
||||
| CiphertextConversionFailed ByteString
|
||||
-- ^ The produced 'ByteString' is the wrong length for deserialization into
|
||||
-- a ciphertext.
|
||||
--
|
||||
-- The offending 'ByteString' is included.
|
||||
| DeserializationError
|
||||
-- ^ The plaintext obtained by decrypting a ciphertext with the given
|
||||
-- 'CryptoIDKey' in the context of the @namespace@ could not be
|
||||
-- deserialized into a value of the expected @payload@-type.
|
||||
@ -183,8 +195,8 @@ encrypt :: forall m namespace.
|
||||
encrypt (keyMaterial -> key) plaintext = do
|
||||
cipher <- cryptoFailable (cipherInit key :: CryptoFailable CryptoCipher)
|
||||
namespace <- namespace' (Proxy :: Proxy namespace)
|
||||
when (ByteArray.length plaintext `mod` blockSize cipher /= 0) $
|
||||
throwM CiphertextConversionFailed
|
||||
when (ByteString.length plaintext `mod` blockSize cipher /= 0) $
|
||||
throwM . PlaintextIsWrongLength $ ByteString.length plaintext
|
||||
return . CryptoID $ cbcEncrypt cipher namespace plaintext
|
||||
|
||||
|
||||
|
||||
@ -33,11 +33,15 @@ import qualified Data.CryptoID.ByteString as ByteString (encrypt, decrypt)
|
||||
|
||||
import Data.Binary
|
||||
|
||||
import Data.Monoid
|
||||
|
||||
import Data.ByteString (ByteString)
|
||||
import qualified Data.ByteString as ByteString
|
||||
import qualified Data.ByteString.Lazy as Lazy.ByteString
|
||||
|
||||
import GHC.TypeLits
|
||||
|
||||
import Control.Monad
|
||||
import Control.Monad.Catch (MonadThrow(..))
|
||||
|
||||
|
||||
@ -50,10 +54,22 @@ encrypt :: forall a m c namespace.
|
||||
( KnownSymbol namespace
|
||||
, MonadThrow m
|
||||
, Binary a
|
||||
) => (ByteString -> m c) -> CryptoIDKey -> a -> m (CryptoID namespace c)
|
||||
encrypt encode' key plaintext = do
|
||||
cID <- ByteString.encrypt key . Lazy.ByteString.toStrict $ encode plaintext
|
||||
) => Maybe Int -- ^ Ensure the resulting ciphertext is of this size (needs to be a multiple of the block size of 'CryptoCipher' in bytes, otherwise an exception will be thrown at runtime)
|
||||
-> (ByteString -> m c)
|
||||
-> CryptoIDKey
|
||||
-> a
|
||||
-> m (CryptoID namespace c)
|
||||
encrypt pLength encode' key plaintext = do
|
||||
cID <- ByteString.encrypt key <=< pad . Lazy.ByteString.toStrict $ encode plaintext
|
||||
_ciphertext encode' cID
|
||||
where
|
||||
pad str
|
||||
| Just l <- pLength
|
||||
, l' <= l = return $ str <> ByteString.replicate (l - l') 0
|
||||
| Just _ <- pLength = throwM $ CiphertextConversionFailed str
|
||||
| otherwise = return str
|
||||
where
|
||||
l' = ByteString.length str
|
||||
|
||||
|
||||
-- | Decrypt a serialized value
|
||||
@ -67,7 +83,7 @@ decrypt decode key cID = do
|
||||
plaintext <- Lazy.ByteString.fromStrict <$> ByteString.decrypt key cID'
|
||||
|
||||
case decodeOrFail plaintext of
|
||||
Left err -> throwM $ DeserializationError err
|
||||
Left _ -> throwM DeserializationError
|
||||
Right (rem, _, res)
|
||||
| Lazy.ByteString.all (== 0) rem -> return res
|
||||
| otherwise -> throwM InvalidNamespaceDetected
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
# 1.2.0.0
|
||||
- Pad plaintext before encryption, allowing encryption of payloads shorter than 128 bits
|
||||
|
||||
# 1.1.1.0
|
||||
- Switch to using the new 'Data.CryptoID.Poly'
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ encrypt :: forall a m namespace.
|
||||
, Binary a
|
||||
, MonadThrow m
|
||||
) => CryptoIDKey -> a -> m (CryptoUUID namespace)
|
||||
encrypt = Poly.encrypt $ maybe (throwM CiphertextConversionFailed) return . fromByteString . Lazy.ByteString.fromStrict
|
||||
encrypt = Poly.encrypt (Just 16) $ \str -> maybe (throwM $ CiphertextConversionFailed str) return . fromByteString $ Lazy.ByteString.fromStrict str
|
||||
|
||||
|
||||
-- | Decrypt an arbitrary serializable value
|
||||
@ -68,7 +68,7 @@ decrypt :: forall a m namespace.
|
||||
) => CryptoIDKey -> CryptoUUID namespace -> m a
|
||||
decrypt = Poly.decrypt $ check . decodeOrFail . toByteString
|
||||
where
|
||||
check (Left err) = throwM $ DeserializationError err
|
||||
check (Left _) = throwM DeserializationError
|
||||
check (Right (rem, _, res))
|
||||
| Lazy.ByteString.all (== 0) rem = return res
|
||||
| otherwise = throwM InvalidNamespaceDetected
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
name: uuid-crypto
|
||||
version: 1.1.1.0
|
||||
version: 1.2.0.0
|
||||
synopsis: Reversable and secure encoding of object ids as uuids
|
||||
license: BSD3
|
||||
license-file: LICENSE
|
||||
@ -28,7 +28,7 @@ library
|
||||
other-extensions: ScopedTypeVariables
|
||||
build-depends: base >=4.9 && <4.11
|
||||
, cryptoids-types ==0.0.0
|
||||
, cryptoids ==0.2.0.*
|
||||
, cryptoids ==0.3.0.*
|
||||
, uuid >=1.3.13 && <1.4
|
||||
, binary >=0.8.3.0 && <0.9
|
||||
, bytestring >=0.10.8.1 && <0.11
|
||||
|
||||
Loading…
Reference in New Issue
Block a user