Blame Crypto/Data/Padding.hs

Packit 141393
-- |
Packit 141393
-- Module      : Crypto.Data.Padding
Packit 141393
-- License     : BSD-style
Packit 141393
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
Packit 141393
-- Stability   : experimental
Packit 141393
-- Portability : unknown
Packit 141393
--
Packit 141393
-- Various cryptographic padding commonly used for block ciphers
Packit 141393
-- or assymetric systems.
Packit 141393
--
Packit 141393
module Crypto.Data.Padding
Packit 141393
    ( Format(..)
Packit 141393
    , pad
Packit 141393
    , unpad
Packit 141393
    ) where
Packit 141393
Packit 141393
import           Data.ByteArray (ByteArray, Bytes)
Packit 141393
import qualified Data.ByteArray as B
Packit 141393
Packit 141393
-- | Format of padding
Packit 141393
data Format =
Packit 141393
      PKCS5     -- ^ PKCS5: PKCS7 with hardcoded size of 8
Packit 141393
    | PKCS7 Int -- ^ PKCS7 with padding size between 1 and 255
Packit 141393
    | ZERO Int  -- ^ zero padding with block size
Packit 141393
    deriving (Show, Eq)
Packit 141393
Packit 141393
-- | Apply some pad to a bytearray
Packit 141393
pad :: ByteArray byteArray => Format -> byteArray -> byteArray
Packit 141393
pad  PKCS5     bin = pad (PKCS7 8) bin
Packit 141393
pad (PKCS7 sz) bin = bin `B.append` paddingString
Packit 141393
  where
Packit 141393
    paddingString = B.replicate paddingByte (fromIntegral paddingByte)
Packit 141393
    paddingByte   = sz - (B.length bin `mod` sz)
Packit 141393
pad (ZERO sz)  bin = bin `B.append` paddingString
Packit 141393
  where
Packit 141393
    paddingString = B.replicate paddingSz 0
Packit 141393
    paddingSz
Packit 141393
      | len == 0   =  sz
Packit 141393
      | m == 0     =  0
Packit 141393
      | otherwise  =  sz - m
Packit 141393
    m = len `mod` sz
Packit 141393
    len = B.length bin
Packit 141393
Packit 141393
-- | Try to remove some padding from a bytearray.
Packit 141393
unpad :: ByteArray byteArray => Format -> byteArray -> Maybe byteArray
Packit 141393
unpad  PKCS5     bin = unpad (PKCS7 8) bin
Packit 141393
unpad (PKCS7 sz) bin
Packit 141393
    | len == 0                           = Nothing
Packit 141393
    | (len `mod` sz) /= 0                = Nothing
Packit 141393
    | paddingSz < 1 || paddingSz > len   = Nothing
Packit 141393
    | paddingWitness `B.constEq` padding = Just content
Packit 141393
    | otherwise                          = Nothing
Packit 141393
  where
Packit 141393
    len         = B.length bin
Packit 141393
    paddingByte = B.index bin (len - 1)
Packit 141393
    paddingSz   = fromIntegral paddingByte
Packit 141393
    (content, padding) = B.splitAt (len - paddingSz) bin
Packit 141393
    paddingWitness     = B.replicate paddingSz paddingByte :: Bytes
Packit 141393
unpad (ZERO sz)  bin
Packit 141393
    | len == 0                           = Nothing
Packit 141393
    | (len `mod` sz) /= 0                = Nothing
Packit 141393
    | B.index bin (len - 1) /= 0         = Just bin
Packit 141393
    | otherwise                          = Nothing
Packit 141393
  where
Packit 141393
    len         = B.length bin