# Data : Base64
- https://datatracker.ietf.org/doc/html/rfc4648
- https://base64encode.org/
## Overview
Encodes 3 bytes (24 bits) into 4 bytes (32 bits) using a 64-character alphabet of printable characters — typically `A-Za-z0-9+/` — and using `=` to pad the resulting string to a multiple of four. In other words, every 6 bits of data is turned into an 8-bit ASCII character.
The standard defines two variants:
- the primary or default variant (`Base64`), which uses `+/` as the last two characters; this variant is used by MIME
- the "URL- and filename-safe" variant (`Base64URL`), which uses `-_` instead.
#### Base32
Same concept, but encodes every 5 bits into 8 bits using a 32-character alphabet — or in other words, converts 5 bytes into 8 bytes using `=` to pad the resulting string to a multiple of eight.
Alphabet: `A-Z2-7`
## Python
There is no pre-built alphabet string for either Base64 variant, but you can create one as follows:
```python
import string
alphabet_base64 = string.ascii_uppercase + string.ascii_lowercase + string.digits + "+/"
alphabet_base64url = string.ascii_uppercase + string.ascii_lowercase + string.digits + "-_"
```
If you're dealing with inputs that include both variants of Base64 and want to normalize them to a single variant:
```python
def normalize_base64( data: str ) -> str:
return data.replace( "-", "+" ).replace( "_", "/" ) # convert Base64URL to Base64
```
If you need to generate cryptographically-secure random strings of Base64:
```python
import secrets
def random_base64( chars: int ) -> str:
padding = chars % 4
return "".join( secrets.choice( alphabet_base64 ) for i in range( chars ) ) + "=" * padding
def random_base64url( chars: int ) -> str:
padding = chars % 4
return "".join( secrets.choice( alphabet_base64url ) for i in range( chars ) ) + "=" * padding
```
#### base64 Package API
```python
# for Base64 variant
b64encode( bytes ) -> bytes # convert data (bytes) to Base64 (bytes)
b64decode( str | bytes ) -> bytes # convert Base64 (str|bytes) to data (bytes)
# for Base64URL variant
urlsafe_b64encode( bytes ) -> bytes
urlsafe_b64decode( str | bytes ) -> bytes
# for Base32
b32encode( bytes ) -> bytes # convert data (bytes) to Base32 (bytes)
b32decode( str | bytes ) -> bytes # convert Base32 (str|bytes) to data (bytes)
# reminder - to turn str into bytes or vice-versa:
mystr.encode() -> bytes
mybytes.decode() -> str
```