Skip to content

Commit

Permalink
[ADP-3327] Small revisions to AES256CBC. (#4529)
Browse files Browse the repository at this point in the history
## Issue

ADP-3327

## Description

This PR makes a number of small revisions to the `AES256CBC` module:
- Use pattern guards instead of `when`.
- Use general functions from `Data.Bifunctor` (in `base`) instead of the
`Either`-specific combinators from`Data.Either.Combinators` (from the
`either` library).
  • Loading branch information
jonathanknowles authored Apr 10, 2024
2 parents 6077a5e + 0fa5fa4 commit 6432402
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 48 deletions.
1 change: 0 additions & 1 deletion lib/crypto-primitives/crypto-primitives.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ library
, base >= 4.14.3 && < 4.19
, bytestring >= 0.10.12 && < 0.13
, cryptonite ^>=0.30
, either
, extra
, memory ^>=0.18
, monoid-subclasses
Expand Down
92 changes: 45 additions & 47 deletions lib/crypto-primitives/src/Cryptography/Cipher/AES256CBC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,12 @@ import Cryptography.Core
( CryptoError (CryptoError_IvSizeInvalid)
, CryptoFailable (CryptoFailed, CryptoPassed)
)
import Data.Bifunctor
( Bifunctor (bimap, first, second)
)
import Data.ByteString
( ByteString
)
import Data.Either.Combinators
( mapBoth
, mapLeft
, mapRight
, maybeToRight
)
import Data.Either.Extra
( maybeToEither
)
Expand Down Expand Up @@ -108,29 +105,28 @@ encrypt
-> ByteString
-- ^ Payload: must be a multiple of a block size, ie., 16 bytes.
-> Either CipherError ByteString
encrypt mode key iv saltM msg = do
when (any ((/= 8) . BS.length) saltM) $
Left WrongSaltSize
when (mode == WithoutPadding && BS.length msg `mod` 16 /= 0) $
Left WrongPayloadSize
initedIV <- mapLeft FromCryptonite (createIV iv)
let msgM = case mode of
WithoutPadding -> Just msg
WithPadding -> padPKCS7 msg
msg' <- maybeToRight EmptyPayload msgM
case saltM of
Nothing ->
mapBoth FromCryptonite
(\c -> cbcEncrypt c initedIV msg') (initCipher key)
Just salt ->
mapRight (\c -> addSalt salt <> c) $
mapBoth FromCryptonite
(\c -> cbcEncrypt c initedIV msg') (initCipher key)
where
addSalt salt = saltPrefix <> salt
padPKCS7 payload
| BS.null payload = Nothing
| otherwise = Just (PKCS7.pad payload)
encrypt mode keyBytes ivBytes saltM msg
| any ((/= 8) . BS.length) saltM =
Left WrongSaltSize
| mode == WithoutPadding && BS.length msg `mod` 16 /= 0 =
Left WrongPayloadSize
| BS.null msg =
Left EmptyPayload
| otherwise = do
iv <- first FromCryptonite (createIV ivBytes)
cypher <- first FromCryptonite (initCipher keyBytes)
pure $ maybeAddSalt $ cbcEncrypt cypher iv $ maybePad msg
where
maybeAddSalt :: ByteString -> ByteString
maybeAddSalt =
case saltM of
Nothing -> id
Just salt -> \c -> saltPrefix <> salt <> c
maybePad :: ByteString -> ByteString
maybePad =
case mode of
WithoutPadding -> id
WithPadding -> PKCS7.pad

saltPrefix :: ByteString
saltPrefix = "Salted__"
Expand All @@ -147,21 +143,23 @@ decrypt
-> Either CipherError (ByteString, Maybe ByteString)
-- ^ Decrypted payload and optionally salt that was used for encryption.
decrypt mode key iv msg = do
when (mode == WithoutPadding && BS.length msg `mod` 16 /= 0) $
Left WrongPayloadSize
initedIV <- mapLeft FromCryptonite (createIV iv)
let (prefix,rest) = BS.splitAt 8 msg
let saltDetected = prefix == saltPrefix
let unpadding p = case mode of
WithoutPadding -> Right p
WithPadding -> maybeToRight EmptyPayload (PKCS7.unpad p)
if saltDetected then
mapRight (, Just $ BS.take 8 rest) $
mapBoth FromCryptonite
(\c -> cbcDecrypt c initedIV (BS.drop 8 rest)) (initCipher key) >>=
unpadding
else
mapRight (, Nothing) $
mapBoth FromCryptonite
(\c -> cbcDecrypt c initedIV msg) (initCipher key) >>=
unpadding
when (mode == WithoutPadding && BS.length msg `mod` 16 /= 0) $
Left WrongPayloadSize
initedIV <- first FromCryptonite (createIV iv)
let (prefix,rest) = BS.splitAt 8 msg
let saltDetected = prefix == saltPrefix
if saltDetected then
second (, Just $ BS.take 8 rest) $
bimap FromCryptonite
(\c -> cbcDecrypt c initedIV (BS.drop 8 rest)) (initCipher key) >>=
unpad
else
second (, Nothing) $
bimap FromCryptonite
(\c -> cbcDecrypt c initedIV msg) (initCipher key) >>=
unpad
where
unpad :: ByteString -> Either CipherError ByteString
unpad p = case mode of
WithoutPadding -> Right p
WithPadding -> maybeToEither EmptyPayload (PKCS7.unpad p)

0 comments on commit 6432402

Please sign in to comment.