<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>base64 on Bloggings</title>
        <link>https://theoutsidelaine.com/tags/base64/</link>
        <description>Recent content in base64 on Bloggings</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Mon, 25 Mar 2024 22:00:00 +0000</lastBuildDate><atom:link href="https://theoutsidelaine.com/tags/base64/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>base64</title>
        <link>https://theoutsidelaine.com/p/base64-encode-decode/</link>
        <pubDate>Mon, 25 Mar 2024 22:00:00 +0000</pubDate>
        
        <guid>https://theoutsidelaine.com/p/base64-encode-decode/</guid>
        <description>&lt;img src="https://theoutsidelaine.com/p/base64-encode-decode/cover.png" alt="Featured image of post base64" /&gt;&lt;p&gt;沒想到第一篇技術分享文章會先從這個小主題開始。主要原因是之前在面試一家非常喜歡的公司，其中一個面試關卡因為沒有考慮到問題條件限制之一是 input 資料為以 base64 編譯後的資料，需要先用程式 decode 為 binary 再做後續處理，最後很可惜沒有進入下一關。後來回想一下，其實我在實習的時候就有碰過這個東西了，只不過當時做 base64 encode 我都直接把 service 密碼明文丟到 google 上的 &amp;ldquo;online base64 encoder&amp;rdquo; 直接做好 encode 後的 string🫠，算是根本沒懂過這個概念。所以決定針對他好好來研究一下，並記錄自己的研究內容～&lt;/p&gt;
&lt;h2 id=&#34;base64-的基本概念&#34;&gt;base64 的基本概念&lt;/h2&gt;
&lt;p&gt;base64 是一種數據格式轉換方法，基本上 base64 encoding 的輸入資料會是一組二進制（binary）編碼，之後依照某種轉換規則，將一組組的 binary 數據對應到特定的 base64 character，最後再輸出一個 text form 的 output。&lt;/p&gt;
&lt;h2 id=&#34;為什麼要做-base64-轉換&#34;&gt;為什麼要做 base64 轉換?&lt;/h2&gt;
&lt;p&gt;主要原因大概如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;提升安全性&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;有時候一些人類很直觀能理解的密碼明文，比如 「&lt;code&gt;elaine_hsieh&lt;/code&gt;」，如果直接撰寫在 service configuration 上，會讓取得密碼的過程太過容易。如果將這樣的資訊包上一層 base64 encoding、變成「&lt;code&gt;ZWxhaW5lX2hzaWVo&lt;/code&gt;」，之後有人想要取得 service 密碼將需要多一道解譯的手續。因此，透過 base64 encoding 可以進而提升一點資訊安全性。&lt;/p&gt;
&lt;p&gt;以 base64 編碼還有個額外好處：便於不同編碼方式之間進行數據轉換後的數據傳輸。&lt;/p&gt;
&lt;p&gt;通常某個 service 密碼明文會使用 &lt;strong&gt;ASCII&lt;/strong&gt; 或是 &lt;strong&gt;UTF-8&lt;/strong&gt; 的編碼方式。使用 ASCII 的明文包含範圍較小，通常僅包含 256 個基本的字元，例如英文字母、數字、標點符號（此處指的是extended ASCII）；使用 UTF-8 的明文包含範圍較大，例如英文字母、數字、標點符號、拉丁字母、中日韓等亞洲文字、表情符號與其他符號。由於 base64 character set包含了部分 ASCII character set，所以不論原始數據是以 ASCII做編碼（例：&lt;code&gt;titan&lt;/code&gt; in ASCII code）、或是以 UTF-8做編碼（例：&lt;code&gt;titan&lt;/code&gt; in UTF-8 code），都可以透過 base64 轉換規則轉換為一組 base64 encoding（例：都會被 base64 轉譯為 &lt;code&gt;dGl0YW4=&lt;/code&gt;）。所以可以說，base64 可用於不同編碼方式之間進行數據轉換後的數據傳輸。&lt;/p&gt;
&lt;p&gt;如果要寬鬆一點說，base64 會有點類似於加密，只不過 base64 可以被輕易的反編碼、讀取到原文，並且此資訊公開給所有人，沒有公私鑰授權特定用戶的功能，所以嚴格來說 base64 不能算是一種加密 (encryption)方法，只能算是一種編譯（encoding）方法。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;便於圖片、音樂、多媒體文件等資訊在網路世界中傳遞&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;在 HTTP、SMTP 等網絡通訊協議中，想要傳送圖片等多媒體資訊其實會有很多限制。HTTP、SMTP、POP3、FTP 等網絡協議只能傳送 text form data，但是圖片、音樂、多媒體文件等資訊通常都會使用 binary code 來儲存資訊：比如像素、顏色深度、每幀畫面、音頻等，通常會用 16 或 32 bit 資訊做紀錄。&lt;/p&gt;
&lt;p&gt;所以當我們想要用電子郵件傳送圖片時，我們會需要先將「&lt;code&gt;00101010101000001&lt;/code&gt;」的圖片 binary data，用 base64 轉換為「&lt;code&gt;MDAxMDEwMTAxMDEwMDAwMDE=&lt;/code&gt;」，電子郵件的 html 形式會類似於 &amp;lt;img&amp;gt; &lt;code&gt;MDAxMDEwMTAxMDEwMDAwMDE=&lt;/code&gt; &amp;lt;/img&amp;gt;。之後傳送到目的方時，再使用 base64 decode 那串 text，就可以看得到&amp;lt;img&amp;gt; &amp;lt;/img&amp;gt; 裡的內容了。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;base64-轉換規則&#34;&gt;base64 轉換規則&lt;/h2&gt;
&lt;p&gt;以string input為例，大致上來說 base64 有四個步驟：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;將 string 依照編碼（eg: ASCII） 轉換為 binary。我們知道 ASCII 編碼一共有 256 種可能，所以轉換後每個字母會對應到 0~255 ASCII number，與8 個bits。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;將這些 binary 以每 6 bits 為單位進行分組。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;將每組 bits 轉換為對應的 base64 character:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(1) base64 有一個自己的 character set, 只有 64 個 character，分別是：大小寫字母（A-Z、a-z）、數字（0-9）和兩個特殊字符（+ 和 /）。這也是 base64 得到這個名字的原因。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(2) 每組 binary 有6 bits, 相當於一共有 64 種可能性，正好可以對應到 base64 character set。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果原始的 string長度不是3的倍數，base64 會自動補上一個 &amp;ldquo;=&amp;quot;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(1) 這麼做的理由相當於宣告最後一組bits「後面有補0，才得以是 6個bits」&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(2) &amp;ldquo;=&amp;rdquo; 相當於宣告這組 bits的特殊性&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;最後將轉換後的 base64 characters回傳，即大功告成。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;值得注意的是，base64 編碼後的數據通常比原始數據更長。這是因為 base64 編碼會將原本以 8 bits 為單位的 string，重新打散單位、轉換為 6 bits 的 base64 characters，這導致編碼後的數據會比原始數據增加約 33% 的大小。&lt;/p&gt;
&lt;h2 id=&#34;舉例說明&#34;&gt;舉例說明&lt;/h2&gt;
&lt;p&gt;假設我們有一串 string名為「Hello」，其長度=5，不是3的倍數。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;依照 ASCII 編碼，「Hello」每一個 character 會對應到一個 8 bits 組合（＝對應到 0~ 255 之間的一個數字）。組合起來即為「01001000 01100101 01101100 01101100 01101111」，一共 40 bits。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;將以上 40 bits 每 6 個分一組，一共可以分成 6 組有完整 6 bits + 1組只有4 bits：「010010」、「000110」、「010101」、「101100」、「011011」、「000110」、「1111」&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;最後那一組補 0，讓他還是擁有 6 bits, 只不過後面放入一個 base64 character: &amp;ldquo;=&amp;quot;，標註他的特殊性。所以就變成以下：「010010」、「000110」、「010101」、「101100」、「011011」、「000110」、「11110&lt;strong&gt;0=&lt;/strong&gt;」&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;每一組對應到 base64 character set中的數字（對應表可以參考本篇文章的首頁圖）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;最後的 output即為 「SGVsbG8=」&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;python-library-實作&#34;&gt;python library 實作&lt;/h2&gt;
&lt;p&gt;在 python中，有很便利的 library協助我們做到 base64 encoding. 可以參考以下的 code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;import base64
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;original_text = &amp;#34;Hello, world!&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;original_bytes = original_text.encode(&amp;#39;utf-8&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;encoded_bytes = base64.b64encode(original_bytes)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;encoded_text = encoded_bytes.decode(&amp;#39;utf-8&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;print(&amp;#34;Base64 編碼結果:&amp;#34;, encoded_text)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;decoded_bytes = base64.b64decode(encoded_bytes)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;decoded_text = decoded_bytes.decode(&amp;#39;utf-8&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;print(&amp;#34;Base64 解碼結果:&amp;#34;, decoded_text)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;結果如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Base64 編碼結果: SGVsbG8sIHdvcmxkIQ==
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Base64 解碼結果: Hello, world!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        </item>
        
    </channel>
</rss>
