0,0 → 1,247 |
# ============================================================================= |
# Copyright (c) 2008 Christophe Oosterlynck <christophe.oosterlynck_AT_gmail.com> |
# & NXP ( Philippe Teuwen <philippe.teuwen_AT_nxp.com> ) |
# |
# Permission is hereby granted, free of charge, to any person obtaining a copy |
# of this software and associated documentation files (the "Software"), to deal |
# in the Software without restriction, including without limitation the rights |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
# copies of the Software, and to permit persons to whom the Software is |
# furnished to do so, subject to the following conditions: |
# |
# The above copyright notice and this permission notice shall be included in |
# all copies or substantial portions of the Software. |
# |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
# THE SOFTWARE. |
# ============================================================================= |
|
"""Module for padding functions |
|
padding info here: http://en.wikipedia.org/wiki/Padding_(cryptography) |
""" |
|
import random |
|
PAD = 0 |
UNPAD = 1 |
|
def bitPadding (padData, direction, length=None): |
"""Pad a string using bitPadding |
|
padData = raw string to pad/unpad |
direction = PAD or UNPAD |
length = amount of bytes the padded string should be a multiple of |
(length variable is not used when unpadding) |
|
returns: (un)padded raw string |
|
A new block full of padding will be added when padding data that is |
already a multiple of the length. |
|
Example: |
========= |
>>> import padding |
|
>>> padding.bitPadding('test', padding.PAD, 8) |
'test\\x80\\x00\\x00\\x00' |
>>> padding.bitPadding(_,padding.UNPAD) |
'test'""" |
if direction == PAD: |
if length == None: |
raise ValueError,"Supply a valid length" |
return __bitPadding(padData, length) |
elif direction == UNPAD: |
return __bitPadding_unpad(padData) |
else: |
raise ValueError,"Supply a valid direction" |
|
def __bitPadding (toPad,length): |
padded = toPad + '\x80' + '\x00'*(length - len(toPad)%length -1) |
return padded |
|
def __bitPadding_unpad (padded): |
if padded.rstrip('\x00')[-1] == '\x80': |
return padded.rstrip('\x00')[:-1] |
else: |
return padded |
|
def zerosPadding (padData, direction, length=None): |
"""Pad a string using zerosPadding |
|
padData = raw string to pad/unpad |
direction = PAD or UNPAD |
beware: padding and unpadding a string ending in 0's |
will remove those 0's too |
length = amount of bytes the padded string should be a multiple of |
(length variable is not used when unpadding) |
|
returns: (un)padded raw string |
|
No padding will be added when padding data that is already a |
multiple of the given length. |
|
Example: |
========= |
>>> import padding |
|
>>> padding.zerosPadding('12345678',padding.PAD,16) |
'12345678\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' |
>>> padding.zerosPadding(_,padding.UNPAD) |
'12345678'""" |
if direction == PAD: |
if length == None: |
raise ValueError,"Supply a valid length" |
return __zerosPadding(padData, length) |
elif direction == UNPAD: |
return __zerosPadding_unpad(padData) |
else: |
raise ValueError,"Supply a valid direction" |
|
def __zerosPadding (toPad, length): |
padLength = (length - len(toPad))%length |
return toPad + '\x00'*padLength |
|
def __zerosPadding_unpad (padded ): |
return padded.rstrip('\x00') |
|
def PKCS7(padData, direction, length=None): |
"""Pad a string using PKCS7 |
|
padData = raw string to pad/unpad |
direction = PAD or UNPAD |
length = amount of bytes the padded string should be a multiple of |
(length variable is not used when unpadding) |
|
returns: (un)padded raw string |
|
A new block full of padding will be added when padding data that is |
already a multiple of the given length. |
|
Example: |
========= |
>>> import padding |
|
>>> padding.PKCS7('12345678',padding.PAD,16) |
'12345678\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08' |
>>> padding.PKCS7(_,padding.UNPAD) |
'12345678'""" |
if direction == PAD: |
if length == None: |
raise ValueError,"Supply a valid length" |
return __PKCS7(padData, length) |
elif direction == UNPAD: |
return __PKCS7_unpad(padData) |
else: |
raise ValueError,"Supply a valid direction" |
|
|
def __PKCS7 (toPad, length): |
amount = length - len(toPad)%length |
pattern = chr(amount) |
pad = pattern*amount |
return toPad + pad |
|
def __PKCS7_unpad (padded): |
pattern = padded[-1] |
length = ord(pattern) |
#check if the bytes to be removed are all the same pattern |
if padded.endswith(pattern*length): |
return padded[:-length] |
else: |
return padded |
print 'error: padding pattern not recognized' |
|
def ANSI_X923 (padData, direction, length=None): |
"""Pad a string using ANSI_X923 |
|
padData = raw string to pad/unpad |
direction = PAD or UNPAD |
length = amount of bytes the padded string should be a multiple of |
(length variable is not used when unpadding) |
|
returns: (un)padded raw string |
|
A new block full of padding will be added when padding data that is |
already a multiple of the given length. |
|
Example: |
========= |
>>> import padding |
|
>>> padding.ANSI_X923('12345678',padding.PAD,16) |
'12345678\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08' |
>>> padding.ANSI_X923(_,padding.UNPAD) |
'12345678'""" |
if direction == PAD: |
if length == None: |
raise ValueError,"Supply a valid length" |
return __ANSI_X923(padData, length) |
elif direction == UNPAD: |
return __ANSI_X923_unpad(padData) |
else: |
raise ValueError,"Supply a valid direction" |
|
def __ANSI_X923 (toPad, length): |
bytesToPad = length - len(toPad)%length |
trail = chr(bytesToPad) |
pattern = '\x00'*(bytesToPad -1) + trail |
return toPad + pattern |
|
def __ANSI_X923_unpad (padded): |
length =ord(padded[-1]) |
#check if the bytes to be removed are all zero |
if padded.count('\x00',-length,-1) == length - 1: |
return padded[:-length] |
else: |
print 'error: padding pattern not recognized %s' % padded.count('\x00',-length,-1) |
return padded |
|
def ISO_10126 (padData, direction, length=None): |
"""Pad a string using ISO_10126 |
|
padData = raw string to pad/unpad |
direction = PAD or UNPAD |
length = amount of bytes the padded string should be a multiple of |
(length variable is not used when unpadding) |
|
returns: (un)padded raw string |
|
A new block full of padding will be added when padding data that is |
already a multiple of the given length. |
|
Example: |
========= |
>>> import padding |
|
>>> padded = padding.ISO_10126('12345678',padding.PAD,16) |
>>> padding.ISO_10126(padded,padding.UNPAD) |
'12345678'""" |
if direction == PAD: |
if length == None: |
raise ValueError,"Supply a valid length" |
return __ISO_10126(padData, length) |
elif direction == UNPAD: |
return __ISO_10126_unpad(padData) |
else: |
raise ValueError,"Supply a valid direction" |
|
def __ISO_10126 (toPad, length): |
bytesToPad = length - len(toPad)%length |
randomPattern = ''.join(chr(random.randint(0,255)) for x in range(0,bytesToPad-1)) |
return toPad + randomPattern + chr(bytesToPad) |
|
def __ISO_10126_unpad (padded): |
return padded[0:len(padded)-ord(padded[-1])] |
|
def _test(): |
import doctest |
doctest.testmod() |
|
if __name__ == "__main__": |
_test() |