Spaces:
Sleeping
Sleeping
# | |
# Util/Padding.py : Functions to manage padding | |
# | |
# =================================================================== | |
# | |
# Copyright (c) 2014, Legrandin <[email protected]> | |
# All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions | |
# are met: | |
# | |
# 1. Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# 2. Redistributions in binary form must reproduce the above copyright | |
# notice, this list of conditions and the following disclaimer in | |
# the documentation and/or other materials provided with the | |
# distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
# POSSIBILITY OF SUCH DAMAGE. | |
# =================================================================== | |
__all__ = [ 'pad', 'unpad' ] | |
from Crypto.Util.py3compat import * | |
def pad(data_to_pad, block_size, style='pkcs7'): | |
"""Apply standard padding. | |
Args: | |
data_to_pad (byte string): | |
The data that needs to be padded. | |
block_size (integer): | |
The block boundary to use for padding. The output length is guaranteed | |
to be a multiple of :data:`block_size`. | |
style (string): | |
Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. | |
Return: | |
byte string : the original data with the appropriate padding added at the end. | |
""" | |
padding_len = block_size-len(data_to_pad)%block_size | |
if style == 'pkcs7': | |
padding = bchr(padding_len)*padding_len | |
elif style == 'x923': | |
padding = bchr(0)*(padding_len-1) + bchr(padding_len) | |
elif style == 'iso7816': | |
padding = bchr(128) + bchr(0)*(padding_len-1) | |
else: | |
raise ValueError("Unknown padding style") | |
return data_to_pad + padding | |
def unpad(padded_data, block_size, style='pkcs7'): | |
"""Remove standard padding. | |
Args: | |
padded_data (byte string): | |
A piece of data with padding that needs to be stripped. | |
block_size (integer): | |
The block boundary to use for padding. The input length | |
must be a multiple of :data:`block_size`. | |
style (string): | |
Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. | |
Return: | |
byte string : data without padding. | |
Raises: | |
ValueError: if the padding is incorrect. | |
""" | |
pdata_len = len(padded_data) | |
if pdata_len == 0: | |
raise ValueError("Zero-length input cannot be unpadded") | |
if pdata_len % block_size: | |
raise ValueError("Input data is not padded") | |
if style in ('pkcs7', 'x923'): | |
padding_len = bord(padded_data[-1]) | |
if padding_len<1 or padding_len>min(block_size, pdata_len): | |
raise ValueError("Padding is incorrect.") | |
if style == 'pkcs7': | |
if padded_data[-padding_len:]!=bchr(padding_len)*padding_len: | |
raise ValueError("PKCS#7 padding is incorrect.") | |
else: | |
if padded_data[-padding_len:-1]!=bchr(0)*(padding_len-1): | |
raise ValueError("ANSI X.923 padding is incorrect.") | |
elif style == 'iso7816': | |
padding_len = pdata_len - padded_data.rfind(bchr(128)) | |
if padding_len<1 or padding_len>min(block_size, pdata_len): | |
raise ValueError("Padding is incorrect.") | |
if padding_len>1 and padded_data[1-padding_len:]!=bchr(0)*(padding_len-1): | |
raise ValueError("ISO 7816-4 padding is incorrect.") | |
else: | |
raise ValueError("Unknown padding style") | |
return padded_data[:-padding_len] | |