## 介紹
- 使用 64 個字元進行編碼
- 可以想像成 64 進制
- $log_{2}64 = 6$,6 bits 可以表示 1 個 Base64 單元
- 4 個 Base64 單元,可以表示 3 bytes 的資料 (24 bits)
## 用途
- 表示二進位的編碼,通常是用在二進位資料的傳輸及儲存上
- 如果直接以二進位串流傳輸資料,在某些傳輸協議(protocol)可能錯誤解讀造成錯誤。
## RFC 4648 標準的 Base64 索引表
<!-- | Value | Encoding | Value | Encoding | Value | Encoding | Value | Encoding |
|-|-|-|-|-|-|-|-|
| 0 | A | 17 | R | 34 | i | 51 | z |
| 1 | B | 18 | S | 35 | j | 52 | 0 |
| 2 | C | 19 | T | 36 | k | 53 | 1 |
| 3 | D | 20 | U | 37 | l | 54 | 2 |
| 4 | E | 21 | V | 38 | m | 55 | 3 |
| 5 | F | 22 | W | 39 | n | 56 | 4 |
| 6 | G | 23 | X | 40 | o | 57 | 5 |
| 7 | H | 24 | Y | 41 | p | 58 | 6 |
| 8 | I | 25 | Z | 42 | q | 59 | 7 |
| 9 | J | 26 | a | 43 | r | 60 | 8 |
| 10 | K | 27 | b | 44 | s | 61 | 9 |
| 11 | L | 28 | c | 45 | t | 62 | + |
| 12 | M | 29 | d | 46 | u | 63 | / |
| 13 | N | 30 | e | 47 | v
| 14 | O | 31 | f | 48 | w | (pad) | = |
| 15 | P | 32 | g | 49 | x
| 16 | Q | 33 | h | 50 | y -->
<table class="wikitable" style="text-align:center">
<tbody><tr>
<th scope="col">十進位</th>
<th scope="col">二進位</th>
<th scope="col">字元
</th>
<td rowspan="17"> 
</td>
<th scope="col">十進位</th>
<th scope="col">二進位</th>
<th scope="col">字元
</th>
<td rowspan="17"> 
</td>
<th scope="col">十進位</th>
<th scope="col">二進位</th>
<th scope="col">字元
</th>
<td rowspan="17"> 
</td>
<th scope="col">十進位</th>
<th scope="col">二進位</th>
<th scope="col">字元
</th></tr>
<tr>
<td>0</td>
<td>000000</td>
<td>A</td>
<td>16</td>
<td>010000</td>
<td>Q</td>
<td>32</td>
<td>100000</td>
<td>g</td>
<td>48</td>
<td>110000</td>
<td>w
</td></tr>
<tr>
<td>1</td>
<td>000001</td>
<td>B</td>
<td>17</td>
<td>010001</td>
<td>R</td>
<td>33</td>
<td>100001</td>
<td>h</td>
<td>49</td>
<td>110001</td>
<td>x
</td></tr>
<tr>
<td>2</td>
<td>000010</td>
<td>C</td>
<td>18</td>
<td>010010</td>
<td>S</td>
<td>34</td>
<td>100010</td>
<td>i</td>
<td>50</td>
<td>110010</td>
<td>y
</td></tr>
<tr>
<td>3</td>
<td>000011</td>
<td>D</td>
<td>19</td>
<td>010011</td>
<td>T</td>
<td>35</td>
<td>100011</td>
<td>j</td>
<td>51</td>
<td>110011</td>
<td>z
</td></tr>
<tr>
<td>4</td>
<td>000100</td>
<td>E</td>
<td>20</td>
<td>010100</td>
<td>U</td>
<td>36</td>
<td>100100</td>
<td>k</td>
<td>52</td>
<td>110100</td>
<td>0
</td></tr>
<tr>
<td>5</td>
<td>000101</td>
<td>F</td>
<td>21</td>
<td>010101</td>
<td>V</td>
<td>37</td>
<td>100101</td>
<td>l</td>
<td>53</td>
<td>110101</td>
<td>1
</td></tr>
<tr>
<td>6</td>
<td>000110</td>
<td>G</td>
<td>22</td>
<td>010110</td>
<td>W</td>
<td>38</td>
<td>100110</td>
<td>m</td>
<td>54</td>
<td>110110</td>
<td>2
</td></tr>
<tr>
<td>7</td>
<td>000111</td>
<td>H</td>
<td>23</td>
<td>010111</td>
<td>X</td>
<td>39</td>
<td>100111</td>
<td>n</td>
<td>55</td>
<td>110111</td>
<td>3
</td></tr>
<tr>
<td>8</td>
<td>001000</td>
<td>I</td>
<td>24</td>
<td>011000</td>
<td>Y</td>
<td>40</td>
<td>101000</td>
<td>o</td>
<td>56</td>
<td>111000</td>
<td>4
</td></tr>
<tr>
<td>9</td>
<td>001001</td>
<td>J</td>
<td>25</td>
<td>011001</td>
<td>Z</td>
<td>41</td>
<td>101001</td>
<td>p</td>
<td>57</td>
<td>111001</td>
<td>5
</td></tr>
<tr>
<td>10</td>
<td>001010</td>
<td>K</td>
<td>26</td>
<td>011010</td>
<td>a</td>
<td>42</td>
<td>101010</td>
<td>q</td>
<td>58</td>
<td>111010</td>
<td>6
</td></tr>
<tr>
<td>11</td>
<td>001011</td>
<td>L</td>
<td>27</td>
<td>011011</td>
<td>b</td>
<td>43</td>
<td>101011</td>
<td>r</td>
<td>59</td>
<td>111011</td>
<td>7
</td></tr>
<tr>
<td>12</td>
<td>001100</td>
<td>M</td>
<td>28</td>
<td>011100</td>
<td>c</td>
<td>44</td>
<td>101100</td>
<td>s</td>
<td>60</td>
<td>111100</td>
<td>8
</td></tr>
<tr>
<td>13</td>
<td>001101</td>
<td>N</td>
<td>29</td>
<td>011101</td>
<td>d</td>
<td>45</td>
<td>101101</td>
<td>t</td>
<td>61</td>
<td>111101</td>
<td>9
</td></tr>
<tr>
<td>14</td>
<td>001110</td>
<td>O</td>
<td>30</td>
<td>011110</td>
<td>e</td>
<td>46</td>
<td>101110</td>
<td>u</td>
<td>62</td>
<td>111110</td>
<td>+
</td></tr>
<tr>
<td>15</td>
<td>001111</td>
<td>P</td>
<td>31</td>
<td>011111</td>
<td>f</td>
<td>47</td>
<td>101111</td>
<td>v</td>
<td>63</td>
<td>111111</td>
<td>/
</td></tr>
<tr>
<td colspan="2" align="center">填充</td>
<td>=
</td></tr></tbody></table>
## 實例
### 編碼的位元組數可以被3整除
<table class="wikitable">
<tbody><tr>
<th scope="row">文字
</th>
<td colspan="8" align="center"><b>M</b>
</td>
<td colspan="8" align="center"><b>a</b>
</td>
<td colspan="8" align="center"><b>n</b>
</td></tr>
<tr>
<th scope="row">ASCII編碼
</th>
<td colspan="8" align="center">77
</td>
<td colspan="8" align="center">97
</td>
<td colspan="8" align="center">110
</td></tr>
<tr>
<th scope="row">位元
</th>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0
</td></tr>
<tr>
<th scope="row">索引
</th>
<td colspan="6" align="center">19
</td>
<td colspan="6" align="center">22
</td>
<td colspan="6" align="center">5
</td>
<td colspan="6" align="center">46
</td></tr>
<tr>
<th scope="row">Base64編碼
</th>
<td colspan="6" align="center"><b>T</b>
</td>
<td colspan="6" align="center"><b>W</b>
</td>
<td colspan="6" align="center"><b>F</b>
</td>
<td colspan="6" align="center"><b>u</b>
</td></tr></tbody></table>
### 編碼的位元組數不能被3整除
<table class="wikitable">
<tbody><tr>
<th scope="row">文字(1 Byte)
</th>
<td colspan="8" align="center"><b>A</b>
</td>
<td colspan="8" align="center">
</td>
<td colspan="8" align="center">
</td></tr>
<tr>
<th scope="row">位元
</th>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0
</td></tr>
<tr>
<th scope="row">位元(補0)
</th>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td><b>0</b></td>
<td><b>0</b></td>
<td><b>0</b></td>
<td><b>0</b></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0
</td></tr>
<tr>
<th scope="row">Base64編碼
</th>
<td colspan="6" align="center"><b>Q</b>
</td>
<td colspan="6" align="center"><b>Q</b>
</td>
<td colspan="6" align="center">=
</td>
<td colspan="6" align="center">=
</td></tr>
<tr>
<th scope="row">文字(2 Byte)
</th>
<td colspan="8" align="center"><b>B</b>
</td>
<td colspan="8" align="center"><b>C</b>
</td>
<td colspan="8" align="center">
</td></tr>
<tr>
<th scope="row">位元
</th>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0
</td></tr>
<tr>
<th scope="row">位元(補0)
</th>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td><b>0</b></td>
<td><b>0</b></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0
</td></tr>
<tr>
<th scope="row">Base64編碼
</th>
<td colspan="6" align="center"><b>Q</b>
</td>
<td colspan="6" align="center"><b>k</b>
</td>
<td colspan="6" align="center"><b>M</b>
</td>
<td colspan="6" align="center">=
</td></tr></tbody></table>
## Python
```python=
import base64
# encode: string -> bytes object
s = base64.b64encode(input().encode('UTF-8'))
# Base64
print(s)
# 將 Base64 還原成原來的字串
print(base64.b64decode(s).decode('UTF-8'))
```
## Base 家族
- Base16
- Base32
- Base64
## 跟加密的不同之處
- Base64 是一種編碼,只要知道編碼方式,任何人都可以知道原文
- 加密需要有 key,即使知道加密方式,沒有 key 也無法找回原文
## Reference
- https://zh.wikipedia.org/zh-tw/Base64
- https://matthung0807.blogspot.com/2022/06/what-is-base64-encode.html
- https://ithelp.ithome.com.tw/articles/10211783
- https://shengyu7697.github.io/python-base64/
---
## picoCTF
- [[General Skills] Bases](https://play.picoctf.org/practice/challenge/67)