ToolDeck

การเข้ารหัส Base64

7 เครื่องมือ

การเข้ารหัสคืออะไร?

การเข้ารหัส (Encoding) คือกระบวนการแปลงข้อมูลจากรูปแบบหนึ่งไปยังอีกรูปแบบหนึ่ง ในการพัฒนาเว็บ การเข้ารหัสถูกใช้เพื่อส่งข้อมูลอย่างปลอดภัยผ่านช่องทางที่ออกแบบมาสำหรับชุดอักขระที่จำกัด — เช่น การส่งข้อมูลไบนารีผ่านโปรโตคอลแบบข้อความ หรือการรวมอักขระพิเศษใน URL

การเข้ารหัสอักขระกำหนดวิธีที่อักขระข้อความแมปกับไบต์ Base64 แปลงข้อมูลไบนารีเป็นข้อความ ASCII การเข้ารหัส URL ทำให้ข้อความใดก็ได้ปลอดภัยสำหรับการใช้งานใน URL การเข้าใจสามชั้นของการเข้ารหัสนี้ช่วยป้องกันข้อผิดพลาดและช่องโหว่ด้านความปลอดภัยที่ตรวจจับได้ยาก

ประวัติการเข้ารหัสอักขระ

การเข้ารหัสอักขระคือการแมประหว่างอักขระ (ตัวอักษร สัญลักษณ์) กับการแทนค่าแบบไบนารี วิวัฒนาการจาก ASCII ไปสู่ Unicode สะท้อนให้เห็นถึงการเป็นสากลของเว็บ:

ASCII1963
128 อักขระ

รหัสมาตรฐานอเมริกัน 7 บิต มี 128 อักขระ ได้แก่ ตัวอักษรอังกฤษ ตัวเลข เครื่องหมายวรรคตอน และรหัสควบคุม ถือเป็นการเข้ารหัสพื้นฐานที่ระบบอื่น ๆ ทั้งหมดต่อยอดจาก

Latin-11987
256 อักขระ

ASCII ที่ขยายสำหรับภาษาในยุโรปตะวันตก เพิ่มอีก 128 อักขระ (ตัวอักษรที่มีเครื่องหมายเน้นเสียง สัญลักษณ์) ไม่เหมาะสำหรับอักษรที่ไม่ใช่ละติน

Unicode1991
149 186+ อักขระ

ชุดอักขระสากลที่ครอบคลุมระบบการเขียนทุกชนิดในโลก กำหนดจุดรหัสสำหรับกว่า 149,000 อักขระใน 161 อักษร ไม่ได้กำหนดการเข้ารหัส — นั่นคือหน้าที่ของ UTF-8/16/32

UTF-81993
Unicode ทั้งหมด อักขระ

การเข้ารหัสแบบความกว้างผันแปรสำหรับ Unicode โดยใช้ 1–4 ไบต์ต่ออักขระ รองรับ ASCII (จุดรหัส 128 ตัวแรกใช้ไบต์เดียว) เป็นการเข้ารหัสที่ครองตลาดบนเว็บ — มากกว่า 98% ของเว็บไซต์ทั้งหมด

UTF-161996
Unicode ทั้งหมด อักขระ

การเข้ารหัสแบบความกว้างผันแปรโดยใช้ 2 หรือ 4 ไบต์ต่ออักขระ ใช้ภายในระบบ Windows, Java และสตริงของ JavaScript ไม่รองรับ ASCII

UTF-322000
Unicode ทั้งหมด อักขระ

การเข้ารหัสแบบความกว้างคงที่: ใช้ 4 ไบต์ต่ออักขระเสมอ เรียบง่ายแต่สิ้นเปลืองพื้นที่ ใช้ในระบบฐานข้อมูลบางตัว แทบไม่พบบนเว็บ

เหตุใด UTF-8 จึงได้รับชัยชนะ

UTF-8 กลายเป็นมาตรฐานที่ครองตลาด เนื่องจากรองรับ ASCII ย้อนหลัง (อักขระ 128 ตัวแรกเข้ารหัสเหมือนกันทุกประการ) ซิงโครไนซ์ตัวเองได้ (สามารถค้นหาขอบเขตของอักขระได้โดยการสแกน) และประหยัดพื้นที่สำหรับข้อความภาษาละติน เอกสาร ASCII ใด ๆ ก็เป็นเอกสาร UTF-8 ที่ถูกต้อง ทำให้การย้ายข้อมูลเป็นไปอย่างราบรื่น

การเข้ารหัส Base64

Base64 แปลงข้อมูลไบนารีเป็นข้อความโดยใช้เพียง 64 อักขระ ASCII ที่พิมพ์ได้: A-Z, a-z, 0-9, + และ / สิ่งนี้จำเป็นเมื่อข้อมูลไบนารีต้องส่งผ่านช่องทางที่รับเฉพาะข้อความ — ไฟล์แนบอีเมล, data URI, JWT token และ HTTP Basic Auth ล้วนใช้ Base64

วิธีการทำงาน

Base64 จัดกลุ่มไบต์ของข้อมูลอินพุตเป็นกลุ่มละ 3 ไบต์ (24 บิต) และเข้ารหัสแต่ละกลุ่มเป็นอักขระ Base64 จำนวน 4 ตัว (6 บิตต่อตัว) หากข้อมูลอินพุตไม่เป็นจำนวนเท่าของ 3 ไบต์ จะมีการเติมอักขระ = เพื่อให้กลุ่มสุดท้ายครบ:

อินพุตไบต์เลขฐานสิบหกBase64
"Man"77 61 6ETWFu
"Ma"4D 61TWE=
"M"4DTQ==

อักขระ = ที่ท้ายบ่งบอกว่ากลุ่ม 3 ไบต์สุดท้ายขาดไบต์ไปกี่ตัว = หนึ่งตัวหมายความว่าต้องเติม 1 ไบต์ และ == หมายความว่าต้องเติม 2 ไบต์ Base64 มาตรฐานจะสร้างผลลัพธ์ที่มีความยาวเป็นจำนวนเท่าของ 4 เสมอ

การเข้ารหัส URL

URL สามารถมีเฉพาะชุดอักขระ ASCII ที่ปลอดภัยในจำนวนจำกัด อักขระใด ๆ ที่อยู่นอกชุดนั้น — รวมถึงช่องว่าง เครื่องหมายวรรคตอน อักขระที่ไม่ใช่ ASCII และอักขระ URL พิเศษ เช่น &, = และ # — ต้องถูกเข้ารหัสแบบเปอร์เซ็นต์ (URL-encoded) ก่อนนำไปใส่ใน URL

การเข้ารหัสแบบเปอร์เซ็นต์จะแทนที่แต่ละไบต์ที่ไม่ปลอดภัยด้วย % ตามด้วยตัวเลขฐานสิบหกสองหลักที่แทนค่าของไบต์นั้น ช่องว่างกลายเป็น %20 เครื่องหมาย & กลายเป็น %26 เป็นต้น

อักขระที่มักถูกเข้ารหัส

อักขระที่เข้ารหัสแล้วหมายเหตุ
Space%20พบบ่อยที่สุด ใช้ในการส่งแบบฟอร์มในรูป + สำหรับ application/x-www-form-urlencoded
&%26ตัวคั่น query string ต้องเข้ารหัสเมื่อใช้เป็นค่าตามตัวอักษร
=%3Dตัวคั่นคีย์-ค่าใน query string ต้องเข้ารหัสเมื่อใช้เป็นข้อมูล
+%2Bถูกตีความเป็นช่องว่างใน application/x-www-form-urlencoded ต้องเข้ารหัสเพื่อรักษา + ตามตัวอักษร
#%23ตัวระบุ fragment ต้องเข้ารหัสเมื่อใช้เป็นข้อมูลตามตัวอักษรใน path หรือ query
/%2Fตัวคั่น path segment ต้องเข้ารหัสเมื่อใช้เป็นข้อมูลตามตัวอักษร ไม่ใช่เป็นตัวคั่น path
:%3Aตัวคั่น scheme ต้องเข้ารหัสใน path และ query
@%40ใช้ใน mailto: และการยืนยันตัวตน ต้องเข้ารหัสเมื่อใช้เป็นข้อมูลตามตัวอักษร

encodeURI vs encodeURIComponent

JavaScript มีฟังก์ชันเข้ารหัสสองตัวที่มีขอบเขตต่างกัน encodeURI เข้ารหัส URL ทั้งหมด — โดยปล่อยอักขระที่มีความหมายใน URL (:, /, ?, #, @) ไว้ไม่เข้ารหัส ส่วน encodeURIComponent เข้ารหัสองค์ประกอบ URL (ค่าพารามิเตอร์ query เดียว หรือ path segment) — โดยเข้ารหัสอักขระทุกตัวยกเว้น A-Z, a-z, 0-9, -, _, ., ~ ควรใช้ encodeURIComponent สำหรับค่าแต่ละตัว และใช้ encodeURI สำหรับ URL ทั้งหมด

บริบทที่การเข้ารหัสปรากฏในการพัฒนาเว็บ

HTTP Basic การตรวจสอบสิทธิ์

ส่วนหัว Authorization: Basic เข้ารหัสข้อมูลประจำตัวเป็น Base64(username:password) นี่คือการเข้ารหัสเพื่อความสะดวกในการส่ง ไม่ใช่ความปลอดภัย — Base64 ถอดรหัสได้ทันที ควรใช้ HTTPS ร่วมกับ Basic Auth เสมอ

Data URI

Data URI ฝังเนื้อหาไฟล์โดยตรงใน HTML หรือ CSS: data:image/png;base64,.... การเข้ารหัส Base64 สำหรับรูปภาพและฟอนต์แบบ inline ช่วยลดการร้องขอ HTTP แลกกับขนาดเอกสารที่เพิ่มขึ้น (~33% overhead)

ไฟล์แนบอีเมล MIME

อีเมลได้รับการออกแบบมาสำหรับ ASCII 7 บิต ไฟล์แนบไบนารี (รูปภาพ, PDF) จะถูก MIME เข้ารหัสด้วย Base64 ก่อนส่ง โปรแกรมอีเมลของคุณถอดรหัสโดยอัตโนมัติเมื่อแสดงผล

JWT Token

JWT token ใช้การเข้ารหัส Base64url (รูปแบบที่แทน + ด้วย - และ / ด้วย _ โดยไม่มี padding) สำหรับทั้งสามส่วน (header, payload, signature) ทำให้ token ปลอดภัยสำหรับ URL โดยไม่ต้องเข้ารหัสแบบเปอร์เซ็นต์เพิ่มเติม

พารามิเตอร์ Query String

ข้อมูลที่ผู้ใช้ป้อนใน query string ของ URL ต้องถูกเข้ารหัสแบบเปอร์เซ็นต์ การไม่เข้ารหัส & หรือ = ในค่าจะทำให้การแยกวิเคราะห์ query string เสียหายอย่างเงียบ ๆ ควรใช้ encodeURIComponent กับค่าแต่ละตัวเสมอ

ชื่อโดเมนนานาชาติ

ชื่อโดเมนที่ไม่ใช่ ASCII (เช่น münchen.de) ถูกเข้ารหัสด้วย Punycode (คำนำหน้า xn--) เพื่อความเข้ากันได้กับระบบ DNS เบราว์เซอร์แสดงรูปแบบ Unicode แต่ส่งรูปแบบ Punycode ไปยัง DNS resolver

คำถามที่พบบ่อย

Base64 เป็นรูปแบบการเข้ารหัสลับหรือไม่?

ไม่ใช่ Base64 คือการเข้ารหัส (encoding) ไม่ใช่การเข้ารหัสลับ (encryption) เป็นการแปลงแบบกลับได้โดยไม่มีคีย์ลับ ใครก็ตามที่เห็นสตริง Base64 สามารถถอดรหัสได้ทันที ห้ามใช้ Base64 เป็นมาตรการด้านความปลอดภัย

เหตุใดผลลัพธ์ Base64 จึงลงท้ายด้วย == บางครั้ง?

Base64 ประมวลผลข้อมูลอินพุตเป็นกลุ่มละ 3 ไบต์ หากข้อมูลอินพุตไม่เป็นจำนวนเท่าของ 3 ไบต์ จะมีการเติม = เพื่อให้กลุ่มสุดท้ายครบ = หนึ่งตัวหมายถึงเติม 1 ไบต์ และ == หมายถึงเติม 2 ไบต์ บางการติดตั้งไม่ใส่ padding (เช่น Base64url สำหรับ JWT)

Base64 และ Base64url ต่างกันอย่างไร?

Base64url เป็นรูปแบบของ Base64 ที่ปลอดภัยสำหรับ URL โดยแทน + ด้วย - และ / ด้วย _ และมักไม่ใส่ = padding ทำให้ใช้งานได้อย่างปลอดภัยใน URL และ HTTP header โดยไม่ต้องเข้ารหัสแบบเปอร์เซ็นต์ JWT ใช้ Base64url สำหรับทั้งสามส่วน

ควรใช้ encodeURI หรือ encodeURIComponent เมื่อไหร่?

ใช้ encodeURIComponent สำหรับค่าแต่ละตัว (ค่าพารามิเตอร์ query, ค่า path segment) ใช้ encodeURI สำหรับสตริง URL ทั้งหมดเมื่อต้องการรักษาอักขระโครงสร้าง URL (/, :, ?, #) หากไม่แน่ใจ ให้ใช้ encodeURIComponent

เหตุใด UTF-8 จึงดีกว่า UTF-16 สำหรับเว็บ?

UTF-8 รองรับ ASCII และประหยัดพื้นที่สำหรับข้อความภาษาละติน (URL, แท็ก HTML และโค้ดส่วนใหญ่เป็น ASCII) UTF-16 สิ้นเปลืองพื้นที่สำหรับเนื้อหา ASCII และไม่รองรับย้อนหลัง HTTP และ HTML ใช้ UTF-8 เป็นค่าเริ่มต้น

การเข้ารหัสแบบเปอร์เซ็นต์คืออะไร?

การเข้ารหัสแบบเปอร์เซ็นต์ (URL encoding) แทนอักขระด้วย % ตามด้วยค่าไบต์เลขฐานสิบหกสองหลัก ตัวอย่างเช่น ช่องว่างคือ %20 (ทศนิยม 32, เลขฐานสิบหก 20) อักขระ UTF-8 หลายไบต์จะเข้ารหัสแต่ละไบต์แยกกัน: é คือ %C3%A9

การเข้ารหัสส่งผลต่อประสิทธิภาพหรือไม่?

Base64 เพิ่มขนาดข้อมูลประมาณ 33% และเพิ่มภาระการประมวลผล CPU สำหรับการเข้ารหัสและถอดรหัส สำหรับระบบที่มีปริมาณงานสูง ควรใช้โปรโตคอลไบนารี การเข้ารหัส URL เพิ่มภาระน้อยมาก แต่อาจทำให้ URL ยาวขึ้นอย่างมากเมื่อมีอักขระพิเศษจำนวนมาก

Punycode คืออะไร?

Punycode คือการเข้ารหัสสำหรับแทน Unicode ใน DNS ที่รองรับ ASCII ชื่อโดเมนนานาชาติ เช่น münchen.de ถูกเข้ารหัสเป็น xn--mnchen-3ya.de ใน DNS query เบราว์เซอร์แสดงรูปแบบ Unicode แต่ใช้ Punycode ภายใน