Advertisement
Taraxacum

NonPaddingCipher

Nov 6th, 2019
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.24 KB | None | 0 0
  1. from Crypto.Cipher import AES
  2. from Crypto.Random import get_random_bytes
  3.  
  4.  
  5. def zero_padding(data: bytes, block_size: int) -> bytes:
  6.     padding_length = block_size - (len(data) % block_size)
  7.  
  8.     return data + b'\x00' * (padding_length % block_size)
  9.  
  10.  
  11. class NonPaddingCipher:
  12.     def __init__(self, key: bytes):
  13.         assert len(key) in AES.key_size
  14.         self.k = key
  15.  
  16.     def encrypt(self, message: bytes) -> bytes:
  17.         # padding
  18.         plain = zero_padding(message, AES.block_size)
  19.  
  20.         # encrypt using raw AES-CBC
  21.         iv = get_random_bytes(AES.block_size)
  22.         aes = AES.new(self.k, AES.MODE_CBC, IV=iv)
  23.         ciphertext = aes.encrypt(plain)
  24.         cip = iv + ciphertext
  25.  
  26.         # reorder the ciphertext blocks
  27.         reorder = cip[:-2*AES.block_size] + cip[-AES.block_size:] + \
  28.             cip[-2*AES.block_size:]
  29.  
  30.         return reorder[:AES.block_size + len(message)]
  31.  
  32.     def decrypt(self, ciphertext: bytes) -> bytes:
  33.         assert len(ciphertext) > AES.block_size
  34.  
  35.         # padding the cipherext
  36.         cipher = zero_padding(ciphertext, AES.block_size)
  37.  
  38.         # extract the last two blocks of ciphertext
  39.         c_k = cipher[-2*AES.block_size:-AES.block_size]  # C_{k}
  40.         c_kp1 = cipher[-AES.block_size:]                 # C'_{k+1}
  41.  
  42.         # calculate B'_{k+1} = F^{-1}_k(IV=C'_{k+1} || C_{k})
  43.         aes = AES.new(self.k, AES.MODE_CBC, IV=c_kp1)
  44.         b_kp1 = aes.decrypt(c_k)
  45.  
  46.         # calculate l
  47.         last_block_size = len(ciphertext) % AES.block_size
  48.         if last_block_size == 0:
  49.             last_block_size = AES.block_size
  50.  
  51.         # C'_k = C_{k+1} + B'_k+1
  52.         c_k_real = c_kp1[:last_block_size] + b_kp1[last_block_size:]
  53.  
  54.         # restore the original ciphertext
  55.         cip = cipher[:-2*AES.block_size] + c_k_real + c_k
  56.  
  57.         # decrypt using raw AES-CBC
  58.         iv = cip[:AES.block_size]
  59.         aes = AES.new(self.k, AES.MODE_CBC, IV=iv)
  60.         plain = aes.decrypt(cip[AES.block_size:])
  61.  
  62.         # check the padding
  63.         if last_block_size < AES.block_size:
  64.             if any(plain[-AES.block_size:][last_block_size:]):
  65.                 print("Bad Padding")
  66.                 return None
  67.  
  68.         return plain[:len(ciphertext) - AES.block_size]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement