1 # =============================================================================
2 # Copyright (c) 2008 Christophe Oosterlynck <christophe.oosterlynck_AT_gmail.com>
3 # & NXP ( Philippe Teuwen <philippe.teuwen_AT_nxp.com> )
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # =============================================================================
24 """Module for padding functions
26 padding info here: http://en.wikipedia.org/wiki/Padding_(cryptography)
34 def bitPadding (padData
, direction
, length
=None):
35 """Pad a string using bitPadding
37 padData = raw string to pad/unpad
38 direction = PAD or UNPAD
39 length = amount of bytes the padded string should be a multiple of
40 (length variable is not used when unpadding)
42 returns: (un)padded raw string
44 A new block full of padding will be added when padding data that is
45 already a multiple of the length.
51 >>> padding.bitPadding('test', padding.PAD, 8)
52 'test\\x80\\x00\\x00\\x00'
53 >>> padding.bitPadding(_,padding.UNPAD)
57 raise ValueError,"Supply a valid length"
58 return __bitPadding(padData
, length
)
59 elif direction
== UNPAD
:
60 return __bitPadding_unpad(padData
)
62 raise ValueError,"Supply a valid direction"
64 def __bitPadding (toPad
,length
):
65 padded
= toPad
+ '\x80' + '\x00'*(length
- len(toPad
)%length
-1)
68 def __bitPadding_unpad (padded
):
69 if padded
.rstrip('\x00')[-1] == '\x80':
70 return padded
.rstrip('\x00')[:-1]
74 def zerosPadding (padData
, direction
, length
=None):
75 """Pad a string using zerosPadding
77 padData = raw string to pad/unpad
78 direction = PAD or UNPAD
79 beware: padding and unpadding a string ending in 0's
80 will remove those 0's too
81 length = amount of bytes the padded string should be a multiple of
82 (length variable is not used when unpadding)
84 returns: (un)padded raw string
86 No padding will be added when padding data that is already a
87 multiple of the given length.
93 >>> padding.zerosPadding('12345678',padding.PAD,16)
94 '12345678\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'
95 >>> padding.zerosPadding(_,padding.UNPAD)
99 raise ValueError,"Supply a valid length"
100 return __zerosPadding(padData
, length
)
101 elif direction
== UNPAD
:
102 return __zerosPadding_unpad(padData
)
104 raise ValueError,"Supply a valid direction"
106 def __zerosPadding (toPad
, length
):
107 padLength
= (length
- len(toPad
))%length
108 return toPad
+ '\x00'*padLength
110 def __zerosPadding_unpad (padded
):
111 return padded
.rstrip('\x00')
113 def PKCS7(padData
, direction
, length
=None):
114 """Pad a string using PKCS7
116 padData = raw string to pad/unpad
117 direction = PAD or UNPAD
118 length = amount of bytes the padded string should be a multiple of
119 (length variable is not used when unpadding)
121 returns: (un)padded raw string
123 A new block full of padding will be added when padding data that is
124 already a multiple of the given length.
130 >>> padding.PKCS7('12345678',padding.PAD,16)
131 '12345678\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08'
132 >>> padding.PKCS7(_,padding.UNPAD)
136 raise ValueError,"Supply a valid length"
137 return __PKCS7(padData
, length
)
138 elif direction
== UNPAD
:
139 return __PKCS7_unpad(padData
)
141 raise ValueError,"Supply a valid direction"
144 def __PKCS7 (toPad
, length
):
145 amount
= length
- len(toPad
)%length
146 pattern
= chr(amount
)
150 def __PKCS7_unpad (padded
):
152 length
= ord(pattern
)
153 #check if the bytes to be removed are all the same pattern
154 if padded
.endswith(pattern
*length
):
155 return padded
[:-length
]
158 print 'error: padding pattern not recognized'
160 def ANSI_X923 (padData
, direction
, length
=None):
161 """Pad a string using ANSI_X923
163 padData = raw string to pad/unpad
164 direction = PAD or UNPAD
165 length = amount of bytes the padded string should be a multiple of
166 (length variable is not used when unpadding)
168 returns: (un)padded raw string
170 A new block full of padding will be added when padding data that is
171 already a multiple of the given length.
177 >>> padding.ANSI_X923('12345678',padding.PAD,16)
178 '12345678\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08'
179 >>> padding.ANSI_X923(_,padding.UNPAD)
183 raise ValueError,"Supply a valid length"
184 return __ANSI_X923(padData
, length
)
185 elif direction
== UNPAD
:
186 return __ANSI_X923_unpad(padData
)
188 raise ValueError,"Supply a valid direction"
190 def __ANSI_X923 (toPad
, length
):
191 bytesToPad
= length
- len(toPad
)%length
192 trail
= chr(bytesToPad
)
193 pattern
= '\x00'*(bytesToPad
-1) + trail
194 return toPad
+ pattern
196 def __ANSI_X923_unpad (padded
):
197 length
=ord(padded
[-1])
198 #check if the bytes to be removed are all zero
199 if padded
.count('\x00',-length
,-1) == length
- 1:
200 return padded
[:-length
]
202 print 'error: padding pattern not recognized %s' % padded
.count('\x00',-length
,-1)
205 def ISO_10126 (padData
, direction
, length
=None):
206 """Pad a string using ISO_10126
208 padData = raw string to pad/unpad
209 direction = PAD or UNPAD
210 length = amount of bytes the padded string should be a multiple of
211 (length variable is not used when unpadding)
213 returns: (un)padded raw string
215 A new block full of padding will be added when padding data that is
216 already a multiple of the given length.
222 >>> padded = padding.ISO_10126('12345678',padding.PAD,16)
223 >>> padding.ISO_10126(padded,padding.UNPAD)
227 raise ValueError,"Supply a valid length"
228 return __ISO_10126(padData
, length
)
229 elif direction
== UNPAD
:
230 return __ISO_10126_unpad(padData
)
232 raise ValueError,"Supply a valid direction"
234 def __ISO_10126 (toPad
, length
):
235 bytesToPad
= length
- len(toPad
)%length
236 randomPattern
= ''.join(chr(random
.randint(0,255)) for x
in range(0,bytesToPad
-1))
237 return toPad
+ randomPattern
+ chr(bytesToPad
)
239 def __ISO_10126_unpad (padded
):
240 return padded
[0:len(padded
)-ord(padded
[-1])]
246 if __name__
== "__main__":