Skip to content

Commit 0810a4b

Browse files
gh-73613: Support Base32 and Base64 without padding
Add the padded parameter in functions related to Base32 and Base64 codecs in the binascii and base64 modules. In the encoding functions it controls whether the pad character can be added in the output, in the decoding functions it controls whether padding is required in input. Padding of input no longer required in base64.urlsafe_b64decode() by default.
1 parent 473d2a3 commit 0810a4b

File tree

13 files changed

+436
-119
lines changed

13 files changed

+436
-119
lines changed

Doc/library/base64.rst

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ The :rfc:`4648` encodings are suitable for encoding binary data so that it can b
5151
safely sent by email, used as parts of URLs, or included as part of an HTTP
5252
POST request.
5353

54-
.. function:: b64encode(s, altchars=None, *, wrapcol=0)
54+
.. function:: b64encode(s, altchars=None, *, padded=True, wrapcol=0)
5555

5656
Encode the :term:`bytes-like object` *s* using Base64 and return the encoded
5757
:class:`bytes`.
@@ -61,6 +61,10 @@ POST request.
6161
This allows an application to e.g. generate URL or filesystem safe Base64
6262
strings. The default is ``None``, for which the standard Base64 alphabet is used.
6363

64+
If *padded* is true (default), pad the encoded data with the '='
65+
character to a size multiple of 4.
66+
If *padded* is false, do not add the pad characters.
67+
6468
If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
6569
after at most every *wrapcol* characters.
6670
If *wrapcol* is zero (default), do not insert any newlines.
@@ -69,11 +73,11 @@ POST request.
6973
:exc:`TypeError` if *altchars* is not a :term:`bytes-like object`.
7074

7175
.. versionchanged:: 3.15
72-
Added the *wrapcol* parameter.
76+
Added the *padded* and *wrapcol* parameters.
7377

7478

75-
.. function:: b64decode(s, altchars=None, validate=False)
76-
b64decode(s, altchars=None, validate=True, *, ignorechars)
79+
.. function:: b64decode(s, altchars=None, validate=False, *, padded=True)
80+
b64decode(s, altchars=None, validate=True, *, ignorechars, padded=True)
7781
7882
Decode the Base64 encoded :term:`bytes-like object` or ASCII string
7983
*s* and return the decoded :class:`bytes`.
@@ -82,6 +86,11 @@ POST request.
8286
of length 2 which specifies the alternative alphabet used instead of the
8387
``+`` and ``/`` characters.
8488

89+
If *padded* is true, the last group of 4 base 64 alphabet characters must
90+
be padded with the '=' character.
91+
If *padded* is false, the '=' character is treated as other non-alphabet
92+
characters (depending on the value of *validate* and *ignorechars*).
93+
8594
A :exc:`binascii.Error` exception is raised
8695
if *s* is incorrectly padded.
8796

@@ -106,7 +115,7 @@ POST request.
106115
For more information about the strict base64 check, see :func:`binascii.a2b_base64`
107116

108117
.. versionchanged:: 3.15
109-
Added the *ignorechars* parameter.
118+
Added the *ignorechars* and *padded* parameters.
110119

111120
.. deprecated:: 3.15
112121
Accepting the ``+`` and ``/`` characters with an alternative alphabet
@@ -125,41 +134,52 @@ POST request.
125134
Base64 alphabet and return the decoded :class:`bytes`.
126135

127136

128-
.. function:: urlsafe_b64encode(s)
137+
.. function:: urlsafe_b64encode(s, *, padded=True)
129138

130139
Encode :term:`bytes-like object` *s* using the
131140
URL- and filesystem-safe alphabet, which
132141
substitutes ``-`` instead of ``+`` and ``_`` instead of ``/`` in the
133142
standard Base64 alphabet, and return the encoded :class:`bytes`. The result
134-
can still contain ``=``.
143+
can still contain ``=`` if *padded* is true (default).
144+
145+
.. versionchanged:: next
146+
Added the *padded* parameter.
135147

136148

137-
.. function:: urlsafe_b64decode(s)
149+
.. function:: urlsafe_b64decode(s, *, padded=False)
138150

139151
Decode :term:`bytes-like object` or ASCII string *s*
140152
using the URL- and filesystem-safe
141153
alphabet, which substitutes ``-`` instead of ``+`` and ``_`` instead of
142154
``/`` in the standard Base64 alphabet, and return the decoded
143155
:class:`bytes`.
144156

157+
.. versionchanged:: next
158+
Added the *padded* parameter.
159+
Padding of input is no longer required by default.
160+
145161
.. deprecated:: 3.15
146162
Accepting the ``+`` and ``/`` characters is now deprecated.
147163

148164

149-
.. function:: b32encode(s, *, wrapcol=0)
165+
.. function:: b32encode(s, *, padded=True, wrapcol=0)
150166

151167
Encode the :term:`bytes-like object` *s* using Base32 and return the
152168
encoded :class:`bytes`.
153169

170+
If *padded* is true (default), pad the encoded data with the '='
171+
character to a size multiple of 8.
172+
If *padded* is false, do not add the pad characters.
173+
154174
If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
155175
after at most every *wrapcol* characters.
156176
If *wrapcol* is zero (default), do not add any newlines.
157177

158178
.. versionchanged:: next
159-
Added the *wrapcol* parameter.
179+
Added the *padded* and *wrapcol* parameters.
160180

161181

162-
.. function:: b32decode(s, casefold=False, map01=None, *, ignorechars=b'')
182+
.. function:: b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b'')
163183

164184
Decode the Base32 encoded :term:`bytes-like object` or ASCII string *s* and
165185
return the decoded :class:`bytes`.
@@ -175,6 +195,11 @@ POST request.
175195
digit 0 is always mapped to the letter O). For security purposes the default is
176196
``None``, so that 0 and 1 are not allowed in the input.
177197

198+
If *padded* is true, the last group of 8 base 32 alphabet characters must
199+
be padded with the '=' character.
200+
If *padded* is false, the '=' character is treated as other non-alphabet
201+
characters (depending on the value of *ignorechars*).
202+
178203
*ignorechars* should be a :term:`bytes-like object` containing characters
179204
to ignore from the input.
180205

@@ -183,21 +208,21 @@ POST request.
183208
input.
184209

185210
.. versionchanged:: next
186-
Added the *ignorechars* parameter.
211+
Added the *ignorechars* and *padded* parameters.
187212

188213

189-
.. function:: b32hexencode(s, *, wrapcol=0)
214+
.. function:: b32hexencode(s, *, padded=True, wrapcol=0)
190215

191216
Similar to :func:`b32encode` but uses the Extended Hex Alphabet, as defined in
192217
:rfc:`4648`.
193218

194219
.. versionadded:: 3.10
195220

196221
.. versionchanged:: next
197-
Added the *wrapcol* parameter.
222+
Added the *padded* and *wrapcol* parameters.
198223

199224

200-
.. function:: b32hexdecode(s, casefold=False, *, ignorechars=b'')
225+
.. function:: b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b'')
201226

202227
Similar to :func:`b32decode` but uses the Extended Hex Alphabet, as defined in
203228
:rfc:`4648`.
@@ -210,7 +235,7 @@ POST request.
210235
.. versionadded:: 3.10
211236

212237
.. versionchanged:: next
213-
Added the *ignorechars* parameter.
238+
Added the *ignorechars* and *padded* parameters.
214239

215240

216241
.. function:: b16encode(s, *, wrapcol=0)

Doc/library/binascii.rst

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,20 @@ The :mod:`!binascii` module defines the following functions:
4848
Added the *backtick* parameter.
4949

5050

51-
.. function:: a2b_base64(string, /, *, alphabet=BASE64_ALPHABET, strict_mode=False)
52-
a2b_base64(string, /, *, ignorechars, alphabet=BASE64_ALPHABET, strict_mode=True)
51+
.. function:: a2b_base64(string, /, *, padded=True, alphabet=BASE64_ALPHABET, strict_mode=False)
52+
a2b_base64(string, /, *, ignorechars, padded=True, alphabet=BASE64_ALPHABET, strict_mode=True)
5353
5454
Convert a block of base64 data back to binary and return the binary data. More
5555
than one line may be passed at a time.
5656

5757
Optional *alphabet* must be a :class:`bytes` object of length 64 which
5858
specifies an alternative alphabet.
5959

60+
If *padded* is true, the last group of 4 base 64 alphabet characters must
61+
be padded with the '=' character.
62+
If *padded* is false, the '=' character is treated as other non-alphabet
63+
characters (depending on the value of *strict_mode* and *ignorechars*).
64+
6065
If *ignorechars* is specified, it should be a :term:`bytes-like object`
6166
containing characters to ignore from the input when *strict_mode* is true.
6267
If *ignorechars* contains the pad character ``'='``, the pad characters
@@ -79,14 +84,18 @@ The :mod:`!binascii` module defines the following functions:
7984
Added the *strict_mode* parameter.
8085

8186
.. versionchanged:: 3.15
82-
Added the *alphabet* and *ignorechars* parameters.
87+
Added the *alphabet*, *ignorechars* and *padded* parameters.
8388

8489

85-
.. function:: b2a_base64(data, *, alphabet=BASE64_ALPHABET, wrapcol=0, newline=True)
90+
.. function:: b2a_base64(data, *, padded=True, alphabet=BASE64_ALPHABET, wrapcol=0, newline=True)
8691

8792
Convert binary data to a line(s) of ASCII characters in base64 coding,
8893
as specified in :rfc:`4648`.
8994

95+
If *padded* is true (default), pad the encoded data with the '='
96+
character to a size multiple of 4.
97+
If *padded* is false, do not add the pad characters.
98+
9099
If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
91100
after at most every *wrapcol* characters.
92101
If *wrapcol* is zero (default), do not insert any newlines.
@@ -98,7 +107,7 @@ The :mod:`!binascii` module defines the following functions:
98107
Added the *newline* parameter.
99108

100109
.. versionchanged:: 3.15
101-
Added the *alphabet* and *wrapcol* parameters.
110+
Added the *alphabet*, *padded* and *wrapcol* parameters.
102111

103112

104113
.. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b'')
@@ -190,7 +199,7 @@ The :mod:`!binascii` module defines the following functions:
190199
.. versionadded:: 3.15
191200

192201

193-
.. function:: a2b_base32(string, /, *, alphabet=BASE32_ALPHABET, ignorechars=b'')
202+
.. function:: a2b_base32(string, /, *, padded=True, alphabet=BASE32_ALPHABET, ignorechars=b'')
194203

195204
Convert base32 data back to binary and return the binary data.
196205

@@ -208,6 +217,11 @@ The :mod:`!binascii` module defines the following functions:
208217
Optional *alphabet* must be a :class:`bytes` object of length 32 which
209218
specifies an alternative alphabet.
210219

220+
If *padded* is true, the last group of 8 base 32 alphabet characters must
221+
be padded with the '=' character.
222+
If *padded* is false, the '=' character is treated as other non-alphabet
223+
characters (depending on the value of *ignorechars*).
224+
211225
*ignorechars* should be a :term:`bytes-like object` containing characters
212226
to ignore from the input.
213227
If *ignorechars* contains the pad character ``'='``, the pad characters
@@ -218,14 +232,18 @@ The :mod:`!binascii` module defines the following functions:
218232

219233
.. versionadded:: next
220234

221-
.. function:: b2a_base32(data, /, *, alphabet=BASE32_ALPHABET, wrapcol=0)
235+
.. function:: b2a_base32(data, /, *, padded=True, alphabet=BASE32_ALPHABET, wrapcol=0)
222236

223237
Convert binary data to a line of ASCII characters in base32 coding,
224238
as specified in :rfc:`4648`. The return value is the converted line.
225239

226240
Optional *alphabet* must be a :term:`bytes-like object` of length 32 which
227241
specifies an alternative alphabet.
228242

243+
If *padded* is true (default), pad the encoded data with the '='
244+
character to a size multiple of 8.
245+
If *padded* is false, do not add the pad characters.
246+
229247
If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
230248
after at most every *wrapcol* characters.
231249
If *wrapcol* is zero (default), do not insert any newlines.

Doc/whatsnew/3.15.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,13 @@ base64
657657
* Added the *pad* parameter in :func:`~base64.z85encode`.
658658
(Contributed by Hauke Dämpfling in :gh:`143103`.)
659659

660+
* Added the *padded* parameter in
661+
:func:`~base64.b32encode`, :func:`~base64.b32decode`,
662+
:func:`~base64.b32hexencode`, :func:`~base64.b32hexdecode`,
663+
:func:`~base64.b64encode`, :func:`~base64.b64decode`,
664+
:func:`~base64.urlsafe_b64encode`, and :func:`~base64.urlsafe_b64decode`.
665+
(Contributed by Serhiy Storchaka in :gh:`73613`.)
666+
660667
* Added the *wrapcol* parameter in :func:`~base64.b16encode`,
661668
:func:`~base64.b32encode`, :func:`~base64.b32hexencode`,
662669
:func:`~base64.b64encode`, :func:`~base64.b85encode`, and
@@ -686,6 +693,11 @@ binascii
686693

687694
(Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.)
688695

696+
* Added the *padded* parameter in
697+
:func:`~binascii.b2a_base32`, :func:`~binascii.a2b_base32`,
698+
:func:`~binascii.b2a_base64`, and :func:`~binascii.a2b_base64`.
699+
(Contributed by Serhiy Storchaka in :gh:`73613`.)
700+
689701
* Added the *wrapcol* parameter in :func:`~binascii.b2a_base64`.
690702
(Contributed by Serhiy Storchaka in :gh:`143214`.)
691703

@@ -2022,3 +2034,9 @@ that may require changes to your code.
20222034
*dest* is now ``'foo'`` instead of ``'f'``.
20232035
Pass an explicit *dest* argument to preserve the old behavior.
20242036
(Contributed by Serhiy Storchaka in :gh:`138697`.)
2037+
2038+
* Padding of input no longer required in :func:`base64.urlsafe_b64decode`.
2039+
Pass a new argument ``padded=True`` or use :func:`base64.b64decode`
2040+
with argument ``altchars=b'-_'`` (this works with older Python versions)
2041+
to make padding required.
2042+
(Contributed by Serhiy Storchaka in :gh:`73613`.)

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,7 @@ struct _Py_global_strings {
697697
STRUCT_FOR_ID(overlapped)
698698
STRUCT_FOR_ID(owner)
699699
STRUCT_FOR_ID(pad)
700+
STRUCT_FOR_ID(padded)
700701
STRUCT_FOR_ID(pages)
701702
STRUCT_FOR_ID(parameter)
702703
STRUCT_FOR_ID(parent)

Include/internal/pycore_runtime_init_generated.h

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_unicodeobject_generated.h

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)