test_base64.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. import unittest
  2. import base64
  3. import binascii
  4. import os
  5. from array import array
  6. from test.support import os_helper
  7. from test.support import script_helper
  8. class LegacyBase64TestCase(unittest.TestCase):
  9. # Legacy API is not as permissive as the modern API
  10. def check_type_errors(self, f):
  11. self.assertRaises(TypeError, f, "")
  12. self.assertRaises(TypeError, f, [])
  13. multidimensional = memoryview(b"1234").cast('B', (2, 2))
  14. self.assertRaises(TypeError, f, multidimensional)
  15. int_data = memoryview(b"1234").cast('I')
  16. self.assertRaises(TypeError, f, int_data)
  17. def test_encodebytes(self):
  18. eq = self.assertEqual
  19. eq(base64.encodebytes(b"www.python.org"), b"d3d3LnB5dGhvbi5vcmc=\n")
  20. eq(base64.encodebytes(b"a"), b"YQ==\n")
  21. eq(base64.encodebytes(b"ab"), b"YWI=\n")
  22. eq(base64.encodebytes(b"abc"), b"YWJj\n")
  23. eq(base64.encodebytes(b""), b"")
  24. eq(base64.encodebytes(b"abcdefghijklmnopqrstuvwxyz"
  25. b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  26. b"0123456789!@#0^&*();:<>,. []{}"),
  27. b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
  28. b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT"
  29. b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n")
  30. # Non-bytes
  31. eq(base64.encodebytes(bytearray(b'abc')), b'YWJj\n')
  32. eq(base64.encodebytes(memoryview(b'abc')), b'YWJj\n')
  33. eq(base64.encodebytes(array('B', b'abc')), b'YWJj\n')
  34. self.check_type_errors(base64.encodebytes)
  35. def test_decodebytes(self):
  36. eq = self.assertEqual
  37. eq(base64.decodebytes(b"d3d3LnB5dGhvbi5vcmc=\n"), b"www.python.org")
  38. eq(base64.decodebytes(b"YQ==\n"), b"a")
  39. eq(base64.decodebytes(b"YWI=\n"), b"ab")
  40. eq(base64.decodebytes(b"YWJj\n"), b"abc")
  41. eq(base64.decodebytes(b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
  42. b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT"
  43. b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n"),
  44. b"abcdefghijklmnopqrstuvwxyz"
  45. b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  46. b"0123456789!@#0^&*();:<>,. []{}")
  47. eq(base64.decodebytes(b''), b'')
  48. # Non-bytes
  49. eq(base64.decodebytes(bytearray(b'YWJj\n')), b'abc')
  50. eq(base64.decodebytes(memoryview(b'YWJj\n')), b'abc')
  51. eq(base64.decodebytes(array('B', b'YWJj\n')), b'abc')
  52. self.check_type_errors(base64.decodebytes)
  53. def test_encode(self):
  54. eq = self.assertEqual
  55. from io import BytesIO, StringIO
  56. infp = BytesIO(b'abcdefghijklmnopqrstuvwxyz'
  57. b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  58. b'0123456789!@#0^&*();:<>,. []{}')
  59. outfp = BytesIO()
  60. base64.encode(infp, outfp)
  61. eq(outfp.getvalue(),
  62. b'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE'
  63. b'RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT'
  64. b'Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n')
  65. # Non-binary files
  66. self.assertRaises(TypeError, base64.encode, StringIO('abc'), BytesIO())
  67. self.assertRaises(TypeError, base64.encode, BytesIO(b'abc'), StringIO())
  68. self.assertRaises(TypeError, base64.encode, StringIO('abc'), StringIO())
  69. def test_decode(self):
  70. from io import BytesIO, StringIO
  71. infp = BytesIO(b'd3d3LnB5dGhvbi5vcmc=')
  72. outfp = BytesIO()
  73. base64.decode(infp, outfp)
  74. self.assertEqual(outfp.getvalue(), b'www.python.org')
  75. # Non-binary files
  76. self.assertRaises(TypeError, base64.encode, StringIO('YWJj\n'), BytesIO())
  77. self.assertRaises(TypeError, base64.encode, BytesIO(b'YWJj\n'), StringIO())
  78. self.assertRaises(TypeError, base64.encode, StringIO('YWJj\n'), StringIO())
  79. class BaseXYTestCase(unittest.TestCase):
  80. # Modern API completely ignores exported dimension and format data and
  81. # treats any buffer as a stream of bytes
  82. def check_encode_type_errors(self, f):
  83. self.assertRaises(TypeError, f, "")
  84. self.assertRaises(TypeError, f, [])
  85. def check_decode_type_errors(self, f):
  86. self.assertRaises(TypeError, f, [])
  87. def check_other_types(self, f, bytes_data, expected):
  88. eq = self.assertEqual
  89. b = bytearray(bytes_data)
  90. eq(f(b), expected)
  91. # The bytearray wasn't mutated
  92. eq(b, bytes_data)
  93. eq(f(memoryview(bytes_data)), expected)
  94. eq(f(array('B', bytes_data)), expected)
  95. # XXX why is b64encode hardcoded here?
  96. self.check_nonbyte_element_format(base64.b64encode, bytes_data)
  97. self.check_multidimensional(base64.b64encode, bytes_data)
  98. def check_multidimensional(self, f, data):
  99. padding = b"\x00" if len(data) % 2 else b""
  100. bytes_data = data + padding # Make sure cast works
  101. shape = (len(bytes_data) // 2, 2)
  102. multidimensional = memoryview(bytes_data).cast('B', shape)
  103. self.assertEqual(f(multidimensional), f(bytes_data))
  104. def check_nonbyte_element_format(self, f, data):
  105. padding = b"\x00" * ((4 - len(data)) % 4)
  106. bytes_data = data + padding # Make sure cast works
  107. int_data = memoryview(bytes_data).cast('I')
  108. self.assertEqual(f(int_data), f(bytes_data))
  109. def test_b64encode(self):
  110. eq = self.assertEqual
  111. # Test default alphabet
  112. eq(base64.b64encode(b"www.python.org"), b"d3d3LnB5dGhvbi5vcmc=")
  113. eq(base64.b64encode(b'\x00'), b'AA==')
  114. eq(base64.b64encode(b"a"), b"YQ==")
  115. eq(base64.b64encode(b"ab"), b"YWI=")
  116. eq(base64.b64encode(b"abc"), b"YWJj")
  117. eq(base64.b64encode(b""), b"")
  118. eq(base64.b64encode(b"abcdefghijklmnopqrstuvwxyz"
  119. b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  120. b"0123456789!@#0^&*();:<>,. []{}"),
  121. b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
  122. b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT"
  123. b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==")
  124. # Test with arbitrary alternative characters
  125. eq(base64.b64encode(b'\xd3V\xbeo\xf7\x1d', altchars=b'*$'), b'01a*b$cd')
  126. eq(base64.b64encode(b'\xd3V\xbeo\xf7\x1d', altchars=bytearray(b'*$')),
  127. b'01a*b$cd')
  128. eq(base64.b64encode(b'\xd3V\xbeo\xf7\x1d', altchars=memoryview(b'*$')),
  129. b'01a*b$cd')
  130. eq(base64.b64encode(b'\xd3V\xbeo\xf7\x1d', altchars=array('B', b'*$')),
  131. b'01a*b$cd')
  132. # Non-bytes
  133. self.check_other_types(base64.b64encode, b'abcd', b'YWJjZA==')
  134. self.check_encode_type_errors(base64.b64encode)
  135. self.assertRaises(TypeError, base64.b64encode, b"", altchars="*$")
  136. # Test standard alphabet
  137. eq(base64.standard_b64encode(b"www.python.org"), b"d3d3LnB5dGhvbi5vcmc=")
  138. eq(base64.standard_b64encode(b"a"), b"YQ==")
  139. eq(base64.standard_b64encode(b"ab"), b"YWI=")
  140. eq(base64.standard_b64encode(b"abc"), b"YWJj")
  141. eq(base64.standard_b64encode(b""), b"")
  142. eq(base64.standard_b64encode(b"abcdefghijklmnopqrstuvwxyz"
  143. b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  144. b"0123456789!@#0^&*();:<>,. []{}"),
  145. b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
  146. b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT"
  147. b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==")
  148. # Non-bytes
  149. self.check_other_types(base64.standard_b64encode,
  150. b'abcd', b'YWJjZA==')
  151. self.check_encode_type_errors(base64.standard_b64encode)
  152. # Test with 'URL safe' alternative characters
  153. eq(base64.urlsafe_b64encode(b'\xd3V\xbeo\xf7\x1d'), b'01a-b_cd')
  154. # Non-bytes
  155. self.check_other_types(base64.urlsafe_b64encode,
  156. b'\xd3V\xbeo\xf7\x1d', b'01a-b_cd')
  157. self.check_encode_type_errors(base64.urlsafe_b64encode)
  158. def test_b64decode(self):
  159. eq = self.assertEqual
  160. tests = {b"d3d3LnB5dGhvbi5vcmc=": b"www.python.org",
  161. b'AA==': b'\x00',
  162. b"YQ==": b"a",
  163. b"YWI=": b"ab",
  164. b"YWJj": b"abc",
  165. b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
  166. b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT"
  167. b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==":
  168. b"abcdefghijklmnopqrstuvwxyz"
  169. b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  170. b"0123456789!@#0^&*();:<>,. []{}",
  171. b'': b'',
  172. }
  173. for data, res in tests.items():
  174. eq(base64.b64decode(data), res)
  175. eq(base64.b64decode(data.decode('ascii')), res)
  176. # Non-bytes
  177. self.check_other_types(base64.b64decode, b"YWJj", b"abc")
  178. self.check_decode_type_errors(base64.b64decode)
  179. # Test with arbitrary alternative characters
  180. tests_altchars = {(b'01a*b$cd', b'*$'): b'\xd3V\xbeo\xf7\x1d',
  181. }
  182. for (data, altchars), res in tests_altchars.items():
  183. data_str = data.decode('ascii')
  184. altchars_str = altchars.decode('ascii')
  185. eq(base64.b64decode(data, altchars=altchars), res)
  186. eq(base64.b64decode(data_str, altchars=altchars), res)
  187. eq(base64.b64decode(data, altchars=altchars_str), res)
  188. eq(base64.b64decode(data_str, altchars=altchars_str), res)
  189. # Test standard alphabet
  190. for data, res in tests.items():
  191. eq(base64.standard_b64decode(data), res)
  192. eq(base64.standard_b64decode(data.decode('ascii')), res)
  193. # Non-bytes
  194. self.check_other_types(base64.standard_b64decode, b"YWJj", b"abc")
  195. self.check_decode_type_errors(base64.standard_b64decode)
  196. # Test with 'URL safe' alternative characters
  197. tests_urlsafe = {b'01a-b_cd': b'\xd3V\xbeo\xf7\x1d',
  198. b'': b'',
  199. }
  200. for data, res in tests_urlsafe.items():
  201. eq(base64.urlsafe_b64decode(data), res)
  202. eq(base64.urlsafe_b64decode(data.decode('ascii')), res)
  203. # Non-bytes
  204. self.check_other_types(base64.urlsafe_b64decode, b'01a-b_cd',
  205. b'\xd3V\xbeo\xf7\x1d')
  206. self.check_decode_type_errors(base64.urlsafe_b64decode)
  207. def test_b64decode_padding_error(self):
  208. self.assertRaises(binascii.Error, base64.b64decode, b'abc')
  209. self.assertRaises(binascii.Error, base64.b64decode, 'abc')
  210. def test_b64decode_invalid_chars(self):
  211. # issue 1466065: Test some invalid characters.
  212. tests = ((b'%3d==', b'\xdd'),
  213. (b'$3d==', b'\xdd'),
  214. (b'[==', b''),
  215. (b'YW]3=', b'am'),
  216. (b'3{d==', b'\xdd'),
  217. (b'3d}==', b'\xdd'),
  218. (b'@@', b''),
  219. (b'!', b''),
  220. (b"YWJj\n", b"abc"),
  221. (b'YWJj\nYWI=', b'abcab'))
  222. funcs = (
  223. base64.b64decode,
  224. base64.standard_b64decode,
  225. base64.urlsafe_b64decode,
  226. )
  227. for bstr, res in tests:
  228. for func in funcs:
  229. with self.subTest(bstr=bstr, func=func):
  230. self.assertEqual(func(bstr), res)
  231. self.assertEqual(func(bstr.decode('ascii')), res)
  232. with self.assertRaises(binascii.Error):
  233. base64.b64decode(bstr, validate=True)
  234. with self.assertRaises(binascii.Error):
  235. base64.b64decode(bstr.decode('ascii'), validate=True)
  236. # Normal alphabet characters not discarded when alternative given
  237. res = b'\xFB\xEF\xBE\xFF\xFF\xFF'
  238. self.assertEqual(base64.b64decode(b'++[[//]]', b'[]'), res)
  239. self.assertEqual(base64.urlsafe_b64decode(b'++--//__'), res)
  240. def test_b32encode(self):
  241. eq = self.assertEqual
  242. eq(base64.b32encode(b''), b'')
  243. eq(base64.b32encode(b'\x00'), b'AA======')
  244. eq(base64.b32encode(b'a'), b'ME======')
  245. eq(base64.b32encode(b'ab'), b'MFRA====')
  246. eq(base64.b32encode(b'abc'), b'MFRGG===')
  247. eq(base64.b32encode(b'abcd'), b'MFRGGZA=')
  248. eq(base64.b32encode(b'abcde'), b'MFRGGZDF')
  249. # Non-bytes
  250. self.check_other_types(base64.b32encode, b'abcd', b'MFRGGZA=')
  251. self.check_encode_type_errors(base64.b32encode)
  252. def test_b32decode(self):
  253. eq = self.assertEqual
  254. tests = {b'': b'',
  255. b'AA======': b'\x00',
  256. b'ME======': b'a',
  257. b'MFRA====': b'ab',
  258. b'MFRGG===': b'abc',
  259. b'MFRGGZA=': b'abcd',
  260. b'MFRGGZDF': b'abcde',
  261. }
  262. for data, res in tests.items():
  263. eq(base64.b32decode(data), res)
  264. eq(base64.b32decode(data.decode('ascii')), res)
  265. # Non-bytes
  266. self.check_other_types(base64.b32decode, b'MFRGG===', b"abc")
  267. self.check_decode_type_errors(base64.b32decode)
  268. def test_b32decode_casefold(self):
  269. eq = self.assertEqual
  270. tests = {b'': b'',
  271. b'ME======': b'a',
  272. b'MFRA====': b'ab',
  273. b'MFRGG===': b'abc',
  274. b'MFRGGZA=': b'abcd',
  275. b'MFRGGZDF': b'abcde',
  276. # Lower cases
  277. b'me======': b'a',
  278. b'mfra====': b'ab',
  279. b'mfrgg===': b'abc',
  280. b'mfrggza=': b'abcd',
  281. b'mfrggzdf': b'abcde',
  282. }
  283. for data, res in tests.items():
  284. eq(base64.b32decode(data, True), res)
  285. eq(base64.b32decode(data.decode('ascii'), True), res)
  286. self.assertRaises(binascii.Error, base64.b32decode, b'me======')
  287. self.assertRaises(binascii.Error, base64.b32decode, 'me======')
  288. # Mapping zero and one
  289. eq(base64.b32decode(b'MLO23456'), b'b\xdd\xad\xf3\xbe')
  290. eq(base64.b32decode('MLO23456'), b'b\xdd\xad\xf3\xbe')
  291. map_tests = {(b'M1023456', b'L'): b'b\xdd\xad\xf3\xbe',
  292. (b'M1023456', b'I'): b'b\x1d\xad\xf3\xbe',
  293. }
  294. for (data, map01), res in map_tests.items():
  295. data_str = data.decode('ascii')
  296. map01_str = map01.decode('ascii')
  297. eq(base64.b32decode(data, map01=map01), res)
  298. eq(base64.b32decode(data_str, map01=map01), res)
  299. eq(base64.b32decode(data, map01=map01_str), res)
  300. eq(base64.b32decode(data_str, map01=map01_str), res)
  301. self.assertRaises(binascii.Error, base64.b32decode, data)
  302. self.assertRaises(binascii.Error, base64.b32decode, data_str)
  303. def test_b32decode_error(self):
  304. tests = [b'abc', b'ABCDEF==', b'==ABCDEF']
  305. prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF']
  306. for i in range(0, 17):
  307. if i:
  308. tests.append(b'='*i)
  309. for prefix in prefixes:
  310. if len(prefix) + i != 8:
  311. tests.append(prefix + b'='*i)
  312. for data in tests:
  313. with self.subTest(data=data):
  314. with self.assertRaises(binascii.Error):
  315. base64.b32decode(data)
  316. with self.assertRaises(binascii.Error):
  317. base64.b32decode(data.decode('ascii'))
  318. def test_b32hexencode(self):
  319. test_cases = [
  320. # to_encode, expected
  321. (b'', b''),
  322. (b'\x00', b'00======'),
  323. (b'a', b'C4======'),
  324. (b'ab', b'C5H0===='),
  325. (b'abc', b'C5H66==='),
  326. (b'abcd', b'C5H66P0='),
  327. (b'abcde', b'C5H66P35'),
  328. ]
  329. for to_encode, expected in test_cases:
  330. with self.subTest(to_decode=to_encode):
  331. self.assertEqual(base64.b32hexencode(to_encode), expected)
  332. def test_b32hexencode_other_types(self):
  333. self.check_other_types(base64.b32hexencode, b'abcd', b'C5H66P0=')
  334. self.check_encode_type_errors(base64.b32hexencode)
  335. def test_b32hexdecode(self):
  336. test_cases = [
  337. # to_decode, expected, casefold
  338. (b'', b'', False),
  339. (b'00======', b'\x00', False),
  340. (b'C4======', b'a', False),
  341. (b'C5H0====', b'ab', False),
  342. (b'C5H66===', b'abc', False),
  343. (b'C5H66P0=', b'abcd', False),
  344. (b'C5H66P35', b'abcde', False),
  345. (b'', b'', True),
  346. (b'00======', b'\x00', True),
  347. (b'C4======', b'a', True),
  348. (b'C5H0====', b'ab', True),
  349. (b'C5H66===', b'abc', True),
  350. (b'C5H66P0=', b'abcd', True),
  351. (b'C5H66P35', b'abcde', True),
  352. (b'c4======', b'a', True),
  353. (b'c5h0====', b'ab', True),
  354. (b'c5h66===', b'abc', True),
  355. (b'c5h66p0=', b'abcd', True),
  356. (b'c5h66p35', b'abcde', True),
  357. ]
  358. for to_decode, expected, casefold in test_cases:
  359. with self.subTest(to_decode=to_decode, casefold=casefold):
  360. self.assertEqual(base64.b32hexdecode(to_decode, casefold),
  361. expected)
  362. self.assertEqual(base64.b32hexdecode(to_decode.decode('ascii'),
  363. casefold), expected)
  364. def test_b32hexdecode_other_types(self):
  365. self.check_other_types(base64.b32hexdecode, b'C5H66===', b'abc')
  366. self.check_decode_type_errors(base64.b32hexdecode)
  367. def test_b32hexdecode_error(self):
  368. tests = [b'abc', b'ABCDEF==', b'==ABCDEF', b'c4======']
  369. prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF']
  370. for i in range(0, 17):
  371. if i:
  372. tests.append(b'='*i)
  373. for prefix in prefixes:
  374. if len(prefix) + i != 8:
  375. tests.append(prefix + b'='*i)
  376. for data in tests:
  377. with self.subTest(to_decode=data):
  378. with self.assertRaises(binascii.Error):
  379. base64.b32hexdecode(data)
  380. with self.assertRaises(binascii.Error):
  381. base64.b32hexdecode(data.decode('ascii'))
  382. def test_b16encode(self):
  383. eq = self.assertEqual
  384. eq(base64.b16encode(b'\x01\x02\xab\xcd\xef'), b'0102ABCDEF')
  385. eq(base64.b16encode(b'\x00'), b'00')
  386. # Non-bytes
  387. self.check_other_types(base64.b16encode, b'\x01\x02\xab\xcd\xef',
  388. b'0102ABCDEF')
  389. self.check_encode_type_errors(base64.b16encode)
  390. def test_b16decode(self):
  391. eq = self.assertEqual
  392. eq(base64.b16decode(b'0102ABCDEF'), b'\x01\x02\xab\xcd\xef')
  393. eq(base64.b16decode('0102ABCDEF'), b'\x01\x02\xab\xcd\xef')
  394. eq(base64.b16decode(b'00'), b'\x00')
  395. eq(base64.b16decode('00'), b'\x00')
  396. # Lower case is not allowed without a flag
  397. self.assertRaises(binascii.Error, base64.b16decode, b'0102abcdef')
  398. self.assertRaises(binascii.Error, base64.b16decode, '0102abcdef')
  399. # Case fold
  400. eq(base64.b16decode(b'0102abcdef', True), b'\x01\x02\xab\xcd\xef')
  401. eq(base64.b16decode('0102abcdef', True), b'\x01\x02\xab\xcd\xef')
  402. # Non-bytes
  403. self.check_other_types(base64.b16decode, b"0102ABCDEF",
  404. b'\x01\x02\xab\xcd\xef')
  405. self.check_decode_type_errors(base64.b16decode)
  406. eq(base64.b16decode(bytearray(b"0102abcdef"), True),
  407. b'\x01\x02\xab\xcd\xef')
  408. eq(base64.b16decode(memoryview(b"0102abcdef"), True),
  409. b'\x01\x02\xab\xcd\xef')
  410. eq(base64.b16decode(array('B', b"0102abcdef"), True),
  411. b'\x01\x02\xab\xcd\xef')
  412. # Non-alphabet characters
  413. self.assertRaises(binascii.Error, base64.b16decode, '0102AG')
  414. # Incorrect "padding"
  415. self.assertRaises(binascii.Error, base64.b16decode, '010')
  416. def test_a85encode(self):
  417. eq = self.assertEqual
  418. tests = {
  419. b'': b'',
  420. b"www.python.org": b'GB\\6`E-ZP=Df.1GEb>',
  421. bytes(range(255)): b"""!!*-'"9eu7#RLhG$k3[W&.oNg'GVB"(`=52*$$"""
  422. b"""(B+<_pR,UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Ykm5X@_(6q'R884cE"""
  423. b"""H9MJ8X:f1+h<)lt#=BSg3>[:ZC?t!MSA7]@cBPD3sCi+'.E,fo>FEMbN"""
  424. b"""G^4U^I!pHnJ:W<)KS>/9Ll%"IN/`jYOHG]iPa.Q$R$jD4S=Q7DTV8*TU"""
  425. b"""nsrdW2ZetXKAY/Yd(L?['d?O\\@K2_]Y2%o^qmn*`5Ta:aN;TJbg"GZd"""
  426. b"""*^:jeCE.%f\\,!5gtgiEi8N\\UjQ5OekiqBum-X60nF?)@o_%qPq"ad`"""
  427. b"""r;HT""",
  428. b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  429. b"0123456789!@#0^&*();:<>,. []{}":
  430. b'@:E_WAS,RgBkhF"D/O92EH6,BF`qtRH$VbC6UX@47n?3D92&&T'
  431. b":Jand;cHat='/U/0JP==1c70M3&r-I,;<FN.OZ`-3]oSW/g+A(H[P",
  432. b"no padding..": b'DJpY:@:Wn_DJ(RS',
  433. b"zero compression\0\0\0\0": b'H=_,8+Cf>,E,oN2F(oQ1z',
  434. b"zero compression\0\0\0": b'H=_,8+Cf>,E,oN2F(oQ1!!!!',
  435. b"Boundary:\0\0\0\0": b'6>q!aA79M(3WK-[!!',
  436. b"Space compr: ": b';fH/TAKYK$D/aMV+<VdL',
  437. b'\xff': b'rr',
  438. b'\xff'*2: b's8N',
  439. b'\xff'*3: b's8W*',
  440. b'\xff'*4: b's8W-!',
  441. }
  442. for data, res in tests.items():
  443. eq(base64.a85encode(data), res, data)
  444. eq(base64.a85encode(data, adobe=False), res, data)
  445. eq(base64.a85encode(data, adobe=True), b'<~' + res + b'~>', data)
  446. self.check_other_types(base64.a85encode, b"www.python.org",
  447. b'GB\\6`E-ZP=Df.1GEb>')
  448. self.assertRaises(TypeError, base64.a85encode, "")
  449. eq(base64.a85encode(b"www.python.org", wrapcol=7, adobe=False),
  450. b'GB\\6`E-\nZP=Df.1\nGEb>')
  451. eq(base64.a85encode(b"\0\0\0\0www.python.org", wrapcol=7, adobe=False),
  452. b'zGB\\6`E\n-ZP=Df.\n1GEb>')
  453. eq(base64.a85encode(b"www.python.org", wrapcol=7, adobe=True),
  454. b'<~GB\\6`\nE-ZP=Df\n.1GEb>\n~>')
  455. eq(base64.a85encode(b' '*8, foldspaces=True, adobe=False), b'yy')
  456. eq(base64.a85encode(b' '*7, foldspaces=True, adobe=False), b'y+<Vd')
  457. eq(base64.a85encode(b' '*6, foldspaces=True, adobe=False), b'y+<U')
  458. eq(base64.a85encode(b' '*5, foldspaces=True, adobe=False), b'y+9')
  459. def test_b85encode(self):
  460. eq = self.assertEqual
  461. tests = {
  462. b'': b'',
  463. b'www.python.org': b'cXxL#aCvlSZ*DGca%T',
  464. bytes(range(255)): b"""009C61O)~M2nh-c3=Iws5D^j+6crX17#SKH9337X"""
  465. b"""AR!_nBqb&%C@Cr{EG;fCFflSSG&MFiI5|2yJUu=?KtV!7L`6nNNJ&ad"""
  466. b"""OifNtP*GA-R8>}2SXo+ITwPvYU}0ioWMyV&XlZI|Y;A6DaB*^Tbai%j"""
  467. b"""czJqze0_d@fPsR8goTEOh>41ejE#<ukdcy;l$Dm3n3<ZJoSmMZprN9p"""
  468. b"""q@|{(sHv)}tgWuEu(7hUw6(UkxVgH!yuH4^z`?@9#Kp$P$jQpf%+1cv"""
  469. b"""(9zP<)YaD4*xB0K+}+;a;Njxq<mKk)=;`X~?CtLF@bU8V^!4`l`1$(#"""
  470. b"""{Qdp""",
  471. b"""abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"""
  472. b"""0123456789!@#0^&*();:<>,. []{}""":
  473. b"""VPa!sWoBn+X=-b1ZEkOHadLBXb#`}nd3r%YLqtVJM@UIZOH55pPf$@("""
  474. b"""Q&d$}S6EqEFflSSG&MFiI5{CeBQRbjDkv#CIy^osE+AW7dwl""",
  475. b'no padding..': b'Zf_uPVPs@!Zf7no',
  476. b'zero compression\x00\x00\x00\x00': b'dS!BNAY*TBaB^jHb7^mG00000',
  477. b'zero compression\x00\x00\x00': b'dS!BNAY*TBaB^jHb7^mG0000',
  478. b"""Boundary:\x00\x00\x00\x00""": b"""LT`0$WMOi7IsgCw00""",
  479. b'Space compr: ': b'Q*dEpWgug3ZE$irARr(h',
  480. b'\xff': b'{{',
  481. b'\xff'*2: b'|Nj',
  482. b'\xff'*3: b'|Ns9',
  483. b'\xff'*4: b'|NsC0',
  484. }
  485. for data, res in tests.items():
  486. eq(base64.b85encode(data), res)
  487. self.check_other_types(base64.b85encode, b"www.python.org",
  488. b'cXxL#aCvlSZ*DGca%T')
  489. def test_a85decode(self):
  490. eq = self.assertEqual
  491. tests = {
  492. b'': b'',
  493. b'GB\\6`E-ZP=Df.1GEb>': b'www.python.org',
  494. b"""! ! * -'"\n\t\t9eu\r\n7# RL\vhG$k3[W&.oNg'GVB"(`=52*$$"""
  495. b"""(B+<_pR,UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Ykm5X@_(6q'R884cE"""
  496. b"""H9MJ8X:f1+h<)lt#=BSg3>[:ZC?t!MSA7]@cBPD3sCi+'.E,fo>FEMbN"""
  497. b"""G^4U^I!pHnJ:W<)KS>/9Ll%"IN/`jYOHG]iPa.Q$R$jD4S=Q7DTV8*TU"""
  498. b"""nsrdW2ZetXKAY/Yd(L?['d?O\\@K2_]Y2%o^qmn*`5Ta:aN;TJbg"GZd"""
  499. b"""*^:jeCE.%f\\,!5gtgiEi8N\\UjQ5OekiqBum-X60nF?)@o_%qPq"ad`"""
  500. b"""r;HT""": bytes(range(255)),
  501. b"""@:E_WAS,RgBkhF"D/O92EH6,BF`qtRH$VbC6UX@47n?3D92&&T:Jand;c"""
  502. b"""Hat='/U/0JP==1c70M3&r-I,;<FN.OZ`-3]oSW/g+A(H[P""":
  503. b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234'
  504. b'56789!@#0^&*();:<>,. []{}',
  505. b'DJpY:@:Wn_DJ(RS': b'no padding..',
  506. b'H=_,8+Cf>,E,oN2F(oQ1z': b'zero compression\x00\x00\x00\x00',
  507. b'H=_,8+Cf>,E,oN2F(oQ1!!!!': b'zero compression\x00\x00\x00',
  508. b'6>q!aA79M(3WK-[!!': b"Boundary:\x00\x00\x00\x00",
  509. b';fH/TAKYK$D/aMV+<VdL': b'Space compr: ',
  510. b'rr': b'\xff',
  511. b's8N': b'\xff'*2,
  512. b's8W*': b'\xff'*3,
  513. b's8W-!': b'\xff'*4,
  514. }
  515. for data, res in tests.items():
  516. eq(base64.a85decode(data), res, data)
  517. eq(base64.a85decode(data, adobe=False), res, data)
  518. eq(base64.a85decode(data.decode("ascii"), adobe=False), res, data)
  519. eq(base64.a85decode(b'<~' + data + b'~>', adobe=True), res, data)
  520. eq(base64.a85decode(data + b'~>', adobe=True), res, data)
  521. eq(base64.a85decode('<~%s~>' % data.decode("ascii"), adobe=True),
  522. res, data)
  523. eq(base64.a85decode(b'yy', foldspaces=True, adobe=False), b' '*8)
  524. eq(base64.a85decode(b'y+<Vd', foldspaces=True, adobe=False), b' '*7)
  525. eq(base64.a85decode(b'y+<U', foldspaces=True, adobe=False), b' '*6)
  526. eq(base64.a85decode(b'y+9', foldspaces=True, adobe=False), b' '*5)
  527. self.check_other_types(base64.a85decode, b'GB\\6`E-ZP=Df.1GEb>',
  528. b"www.python.org")
  529. def test_b85decode(self):
  530. eq = self.assertEqual
  531. tests = {
  532. b'': b'',
  533. b'cXxL#aCvlSZ*DGca%T': b'www.python.org',
  534. b"""009C61O)~M2nh-c3=Iws5D^j+6crX17#SKH9337X"""
  535. b"""AR!_nBqb&%C@Cr{EG;fCFflSSG&MFiI5|2yJUu=?KtV!7L`6nNNJ&ad"""
  536. b"""OifNtP*GA-R8>}2SXo+ITwPvYU}0ioWMyV&XlZI|Y;A6DaB*^Tbai%j"""
  537. b"""czJqze0_d@fPsR8goTEOh>41ejE#<ukdcy;l$Dm3n3<ZJoSmMZprN9p"""
  538. b"""q@|{(sHv)}tgWuEu(7hUw6(UkxVgH!yuH4^z`?@9#Kp$P$jQpf%+1cv"""
  539. b"""(9zP<)YaD4*xB0K+}+;a;Njxq<mKk)=;`X~?CtLF@bU8V^!4`l`1$(#"""
  540. b"""{Qdp""": bytes(range(255)),
  541. b"""VPa!sWoBn+X=-b1ZEkOHadLBXb#`}nd3r%YLqtVJM@UIZOH55pPf$@("""
  542. b"""Q&d$}S6EqEFflSSG&MFiI5{CeBQRbjDkv#CIy^osE+AW7dwl""":
  543. b"""abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"""
  544. b"""0123456789!@#0^&*();:<>,. []{}""",
  545. b'Zf_uPVPs@!Zf7no': b'no padding..',
  546. b'dS!BNAY*TBaB^jHb7^mG00000': b'zero compression\x00\x00\x00\x00',
  547. b'dS!BNAY*TBaB^jHb7^mG0000': b'zero compression\x00\x00\x00',
  548. b"""LT`0$WMOi7IsgCw00""": b"""Boundary:\x00\x00\x00\x00""",
  549. b'Q*dEpWgug3ZE$irARr(h': b'Space compr: ',
  550. b'{{': b'\xff',
  551. b'|Nj': b'\xff'*2,
  552. b'|Ns9': b'\xff'*3,
  553. b'|NsC0': b'\xff'*4,
  554. }
  555. for data, res in tests.items():
  556. eq(base64.b85decode(data), res)
  557. eq(base64.b85decode(data.decode("ascii")), res)
  558. self.check_other_types(base64.b85decode, b'cXxL#aCvlSZ*DGca%T',
  559. b"www.python.org")
  560. def test_a85_padding(self):
  561. eq = self.assertEqual
  562. eq(base64.a85encode(b"x", pad=True), b'GQ7^D')
  563. eq(base64.a85encode(b"xx", pad=True), b"G^'2g")
  564. eq(base64.a85encode(b"xxx", pad=True), b'G^+H5')
  565. eq(base64.a85encode(b"xxxx", pad=True), b'G^+IX')
  566. eq(base64.a85encode(b"xxxxx", pad=True), b'G^+IXGQ7^D')
  567. eq(base64.a85decode(b'GQ7^D'), b"x\x00\x00\x00")
  568. eq(base64.a85decode(b"G^'2g"), b"xx\x00\x00")
  569. eq(base64.a85decode(b'G^+H5'), b"xxx\x00")
  570. eq(base64.a85decode(b'G^+IX'), b"xxxx")
  571. eq(base64.a85decode(b'G^+IXGQ7^D'), b"xxxxx\x00\x00\x00")
  572. def test_b85_padding(self):
  573. eq = self.assertEqual
  574. eq(base64.b85encode(b"x", pad=True), b'cmMzZ')
  575. eq(base64.b85encode(b"xx", pad=True), b'cz6H+')
  576. eq(base64.b85encode(b"xxx", pad=True), b'czAdK')
  577. eq(base64.b85encode(b"xxxx", pad=True), b'czAet')
  578. eq(base64.b85encode(b"xxxxx", pad=True), b'czAetcmMzZ')
  579. eq(base64.b85decode(b'cmMzZ'), b"x\x00\x00\x00")
  580. eq(base64.b85decode(b'cz6H+'), b"xx\x00\x00")
  581. eq(base64.b85decode(b'czAdK'), b"xxx\x00")
  582. eq(base64.b85decode(b'czAet'), b"xxxx")
  583. eq(base64.b85decode(b'czAetcmMzZ'), b"xxxxx\x00\x00\x00")
  584. def test_a85decode_errors(self):
  585. illegal = (set(range(32)) | set(range(118, 256))) - set(b' \t\n\r\v')
  586. for c in illegal:
  587. with self.assertRaises(ValueError, msg=bytes([c])):
  588. base64.a85decode(b'!!!!' + bytes([c]))
  589. with self.assertRaises(ValueError, msg=bytes([c])):
  590. base64.a85decode(b'!!!!' + bytes([c]), adobe=False)
  591. with self.assertRaises(ValueError, msg=bytes([c])):
  592. base64.a85decode(b'<~!!!!' + bytes([c]) + b'~>', adobe=True)
  593. self.assertRaises(ValueError, base64.a85decode,
  594. b"malformed", adobe=True)
  595. self.assertRaises(ValueError, base64.a85decode,
  596. b"<~still malformed", adobe=True)
  597. # With adobe=False (the default), Adobe framing markers are disallowed
  598. self.assertRaises(ValueError, base64.a85decode,
  599. b"<~~>")
  600. self.assertRaises(ValueError, base64.a85decode,
  601. b"<~~>", adobe=False)
  602. base64.a85decode(b"<~~>", adobe=True) # sanity check
  603. self.assertRaises(ValueError, base64.a85decode,
  604. b"abcx", adobe=False)
  605. self.assertRaises(ValueError, base64.a85decode,
  606. b"abcdey", adobe=False)
  607. self.assertRaises(ValueError, base64.a85decode,
  608. b"a b\nc", adobe=False, ignorechars=b"")
  609. self.assertRaises(ValueError, base64.a85decode, b's', adobe=False)
  610. self.assertRaises(ValueError, base64.a85decode, b's8', adobe=False)
  611. self.assertRaises(ValueError, base64.a85decode, b's8W', adobe=False)
  612. self.assertRaises(ValueError, base64.a85decode, b's8W-', adobe=False)
  613. self.assertRaises(ValueError, base64.a85decode, b's8W-"', adobe=False)
  614. def test_b85decode_errors(self):
  615. illegal = list(range(33)) + \
  616. list(b'"\',./:[\\]') + \
  617. list(range(128, 256))
  618. for c in illegal:
  619. with self.assertRaises(ValueError, msg=bytes([c])):
  620. base64.b85decode(b'0000' + bytes([c]))
  621. self.assertRaises(ValueError, base64.b85decode, b'|')
  622. self.assertRaises(ValueError, base64.b85decode, b'|N')
  623. self.assertRaises(ValueError, base64.b85decode, b'|Ns')
  624. self.assertRaises(ValueError, base64.b85decode, b'|NsC')
  625. self.assertRaises(ValueError, base64.b85decode, b'|NsC1')
  626. def test_decode_nonascii_str(self):
  627. decode_funcs = (base64.b64decode,
  628. base64.standard_b64decode,
  629. base64.urlsafe_b64decode,
  630. base64.b32decode,
  631. base64.b16decode,
  632. base64.b85decode,
  633. base64.a85decode)
  634. for f in decode_funcs:
  635. self.assertRaises(ValueError, f, 'with non-ascii \xcb')
  636. def test_ErrorHeritage(self):
  637. self.assertTrue(issubclass(binascii.Error, ValueError))
  638. def test_RFC4648_test_cases(self):
  639. # test cases from RFC 4648 section 10
  640. b64encode = base64.b64encode
  641. b32hexencode = base64.b32hexencode
  642. b32encode = base64.b32encode
  643. b16encode = base64.b16encode
  644. self.assertEqual(b64encode(b""), b"")
  645. self.assertEqual(b64encode(b"f"), b"Zg==")
  646. self.assertEqual(b64encode(b"fo"), b"Zm8=")
  647. self.assertEqual(b64encode(b"foo"), b"Zm9v")
  648. self.assertEqual(b64encode(b"foob"), b"Zm9vYg==")
  649. self.assertEqual(b64encode(b"fooba"), b"Zm9vYmE=")
  650. self.assertEqual(b64encode(b"foobar"), b"Zm9vYmFy")
  651. self.assertEqual(b32encode(b""), b"")
  652. self.assertEqual(b32encode(b"f"), b"MY======")
  653. self.assertEqual(b32encode(b"fo"), b"MZXQ====")
  654. self.assertEqual(b32encode(b"foo"), b"MZXW6===")
  655. self.assertEqual(b32encode(b"foob"), b"MZXW6YQ=")
  656. self.assertEqual(b32encode(b"fooba"), b"MZXW6YTB")
  657. self.assertEqual(b32encode(b"foobar"), b"MZXW6YTBOI======")
  658. self.assertEqual(b32hexencode(b""), b"")
  659. self.assertEqual(b32hexencode(b"f"), b"CO======")
  660. self.assertEqual(b32hexencode(b"fo"), b"CPNG====")
  661. self.assertEqual(b32hexencode(b"foo"), b"CPNMU===")
  662. self.assertEqual(b32hexencode(b"foob"), b"CPNMUOG=")
  663. self.assertEqual(b32hexencode(b"fooba"), b"CPNMUOJ1")
  664. self.assertEqual(b32hexencode(b"foobar"), b"CPNMUOJ1E8======")
  665. self.assertEqual(b16encode(b""), b"")
  666. self.assertEqual(b16encode(b"f"), b"66")
  667. self.assertEqual(b16encode(b"fo"), b"666F")
  668. self.assertEqual(b16encode(b"foo"), b"666F6F")
  669. self.assertEqual(b16encode(b"foob"), b"666F6F62")
  670. self.assertEqual(b16encode(b"fooba"), b"666F6F6261")
  671. self.assertEqual(b16encode(b"foobar"), b"666F6F626172")
  672. class TestMain(unittest.TestCase):
  673. def tearDown(self):
  674. if os.path.exists(os_helper.TESTFN):
  675. os.unlink(os_helper.TESTFN)
  676. def get_output(self, *args):
  677. return script_helper.assert_python_ok('-m', 'base64', *args).out
  678. def test_encode_decode(self):
  679. output = self.get_output('-t')
  680. self.assertSequenceEqual(output.splitlines(), (
  681. b"b'Aladdin:open sesame'",
  682. br"b'QWxhZGRpbjpvcGVuIHNlc2FtZQ==\n'",
  683. b"b'Aladdin:open sesame'",
  684. ))
  685. def test_encode_file(self):
  686. with open(os_helper.TESTFN, 'wb') as fp:
  687. fp.write(b'a\xffb\n')
  688. output = self.get_output('-e', os_helper.TESTFN)
  689. self.assertEqual(output.rstrip(), b'Yf9iCg==')
  690. def test_encode_from_stdin(self):
  691. with script_helper.spawn_python('-m', 'base64', '-e') as proc:
  692. out, err = proc.communicate(b'a\xffb\n')
  693. self.assertEqual(out.rstrip(), b'Yf9iCg==')
  694. self.assertIsNone(err)
  695. def test_decode(self):
  696. with open(os_helper.TESTFN, 'wb') as fp:
  697. fp.write(b'Yf9iCg==')
  698. output = self.get_output('-d', os_helper.TESTFN)
  699. self.assertEqual(output.rstrip(), b'a\xffb')
  700. def test_prints_usage_with_help_flag(self):
  701. output = self.get_output('-h')
  702. self.assertIn(b'usage: ', output)
  703. self.assertIn(b'-d, -u: decode', output)
  704. def test_prints_usage_with_invalid_flag(self):
  705. output = script_helper.assert_python_failure('-m', 'base64', '-x').err
  706. self.assertIn(b'usage: ', output)
  707. self.assertIn(b'-d, -u: decode', output)
  708. if __name__ == '__main__':
  709. unittest.main()