# Path: pycoind/util/pyaes/util.py
# def append_PKCS7_padding(data):
#     pad = 16 - (len(data) % 16)
#     return data + pad * chr(pad)
# 
# def strip_PKCS7_padding(data):
#     if len(data) % 16 != 0:
#         raise ValueError("invalid length")
# 
#     pad = ord(data[-1])
# 
#     if pad > 16:
#         raise ValueError("invalid padding byte")
# 
#     return data[:-pad]


from .aes import AESBlockModeOfOperation, AESSegmentModeOfOperation, AESStreamModeOfOperation
from .util import append_PKCS7_padding, strip_PKCS7_padding
AESBlockModeOfOperation._can_consume = _block_can_consume
AESBlockModeOfOperation._final_encrypt = _block_final_encrypt
AESBlockModeOfOperation._final_decrypt = _block_final_decrypt



# CFB is a segment cipher

def _segment_can_consume(self, size):
    return self.segment_bytes * int(size // self.segment_bytes)

# CFB can handle a non-segment-sized block at the end using the remaining cipherblock
def _segment_final_encrypt(self, data):
    padded = data + (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
    return self.encrypt(padded)[:len(data)]

# CFB can handle a non-segment-sized block at the end using the remaining cipherblock
def _segment_final_decrypt(self, data):
    padded = data + (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
    return self.decrypt(padded)[:len(data)]

AESSegmentModeOfOperation._can_consume = _segment_can_consume
AESSegmentModeOfOperation._final_encrypt = _segment_final_encrypt
AESSegmentModeOfOperation._final_decrypt = _segment_final_decrypt



# OFB and CTR are stream ciphers

def _stream_can_consume(self, size):

# Path: pycoind/util/pyaes/util.py
# def append_PKCS7_padding(data):
#     pad = 16 - (len(data) % 16)
#     return data + pad * chr(pad)
# 
# def strip_PKCS7_padding(data):
#     if len(data) % 16 != 0:
#         raise ValueError("invalid length")
# 
#     pad = ord(data[-1])
# 
#     if pad > 16:
#         raise ValueError("invalid padding byte")
# 
#     return data[:-pad]


# Path: pycoind/util/pyaes/blockfeeder.py
from .aes import AESBlockModeOfOperation, AESSegmentModeOfOperation, AESStreamModeOfOperation
from .util import append_PKCS7_padding, strip_PKCS7_padding

AESBlockModeOfOperation._can_consume = _block_can_consume
AESBlockModeOfOperation._final_encrypt = _block_final_encrypt
AESBlockModeOfOperation._final_decrypt = _block_final_decrypt



# CFB is a segment cipher

def _segment_can_consume(self, size):
    return self.segment_bytes * int(size // self.segment_bytes)

# CFB can handle a non-segment-sized block at the end using the remaining cipherblock
def _segment_final_encrypt(self, data):
    padded = data + (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
    return self.encrypt(padded)[:len(data)]

# CFB can handle a non-segment-sized block at the end using the remaining cipherblock
def _segment_final_decrypt(self, data):
    padded = data + (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
    return self.decrypt(padded)[:len(data)]

AESSegmentModeOfOperation._can_consume = _segment_can_consume
AESSegmentModeOfOperation._final_encrypt = _segment_final_encrypt
AESSegmentModeOfOperation._final_decrypt = _segment_final_decrypt



# OFB and CTR are stream ciphers

def _stream_can_consume(self, size):

    return size