ข้ามไปยังเนื้อหา
Toova
เครื่องมือทั้งหมด

ทำความเข้าใจการเข้ารหัส Base64 — คู่มือนักพัฒนาครบ

Toova

การเข้ารหัส Base64 ปรากฏในเกือบทุกพื้นที่ของการพัฒนาเว็บ — JWT token, data URI, ไฟล์แนบอีเมล, payload API, ลายเซ็นเชิงเข้ารหัส และไฟล์ config แม้แพร่หลาย มันมักถูกเข้าใจผิด: นักพัฒนาบางครั้งสับสนกับการเข้ารหัสลับ หรือใช้ในสถานการณ์ที่ทำให้เรื่องแย่ลง คู่มือนี้อธิบายเป๊ะว่า Base64 ทำงานอย่างไร, เมื่อใดควรเอื้อมหา, เมื่อใดควรหลีกเลี่ยง และวิธีใช้ถูกต้องใน JavaScript

การเข้ารหัส Base64 คืออะไร (และไม่ใช่)

Base64 คือรูปแบบการเข้ารหัส binary เป็นข้อความ งานเดียวของมันคือแปลงข้อมูล binary ใดเป็นสตริงของตัวอักษร ASCII ที่พิมพ์ได้ มันไม่บีบข้อมูล, ไม่เข้ารหัสลับข้อมูล และไม่ตรวจสอบข้อมูล มันคือการแปลงการแทนล้วน — รับไบต์ที่อาจรวม null byte, ตัวอักษรควบคุม หรือค่าที่จะทำลายโปรโตคอลที่อิงข้อความ และแปลงเป็นชุดตัวอักษรปลอดภัย

ชื่อมาจากตัวอักษรพิมพ์ได้ 64 ตัวที่ใช้เป็นตัวอักษรเข้ารหัส: A-Z (26 ตัว), a-z (26 ตัว), 0-9 (10 ตัว) บวก + และ / (2 ตัว) ตัวอักษร = ใช้สำหรับ padding เพราะมีค่าที่เป็นไปได้ 64 ค่าต่อตำแหน่งตัวอักษรและ 2^6 = 64, แต่ละตัวอักษร Base64 เข้ารหัสเป๊ะ 6 bit ของข้อมูลดั้งเดิม

วิธีที่ Base64 ทำงาน — "Hello" ทีละขั้น

วิธีที่ดีที่สุดในการเข้าใจ Base64 คือตามรอยตัวอย่างจริง มาเข้ารหัสสตริง Hello กัน

ขั้น 1: แปลงเป็นไบต์

แต่ละตัวอักษรใน Hello map กับรหัส ASCII ของมัน ซึ่งจากนั้นแสดงในเลขฐานสอง (8 bit ต่อไบต์):

H  e  l  l  o
72 65 6C 6C 6F   (ASCII / hex)
01001000 01100101 01101100 01101100 01101111   (binary)

ขั้น 2: จัดกลุ่มเป็นชิ้น 6-bit

เชื่อม bit ทั้งหมด: 0100100001100101011011000110110001101111 (40 bit) Base64 ประมวลผล 3 ไบต์ (24 bit) ในแต่ละครั้งและ map เป็น 4 ตัวอักษร Base64 (4 × 6 = 24 bit) จัด 40 bit เป็นชิ้น 6-bit, padding กลุ่มสุดท้ายด้วยศูนย์เพื่อเติม:

010010 000110 010101 101100 011011 000110 1111
18     6      21     44     27     6      (กลุ่มสุดท้าย padding ให้ครบ 6 bit: 111100 = 60)

ขั้น 3: Map เป็นตัวอักษร Base64

แต่ละค่า 6-bit map เป็นตัวอักษรในตัวอักษร Base64 (A=0, B=1, ... Z=25, a=26, ... z=51, 0=52, ... 9=61, +=62, /=63) เนื่องจาก 5 ไบต์ไม่ใช่พหุคูณของ 3, เพิ่มตัวอักษร padding = หนึ่งตัว:

Index: 18  6   21  44  27  6   60
Char:  S   G   V   s   b   G   8
ผลลัพธ์: SGVsbG8=   (= คือ padding)

ผลลัพธ์

"Hello" → "SGVsbG8="

คุณสามารถยืนยันสิ่งนี้ทันทีด้วย Toova Base64 encoder/decoder — paste Hello, คลิก Encode แล้วได้ SGVsbG8= คลิก Decode เพื่อย้อนกลับ

Overhead ขนาด 33%

การเข้ารหัส Base64 เพิ่มขนาดข้อมูลประมาณ 33% เสมอ คณิตศาสตร์ตรงไปตรงมา: 3 ไบต์ของ input (24 bit) ผลิต 4 ตัวอักษร Base64 (24 bit เข้ารหัสในกลุ่ม 4 × 6 bit) นั่นคืออัตราส่วน 4/3 หรือ 33.3% overhead เพิ่มตัวอักษร padding และ overhead จริงคือระหว่าง 33% และ 36% ขึ้นอยู่กับความยาว input

เรื่องนี้สำคัญอย่างมีนัยสำคัญสำหรับประสิทธิภาพ ภาพ 1 MB ฝังเป็น Base64 data URI ใน HTML กลายเป็นประมาณ 1.37 MB API ที่เข้ารหัสทุก payload binary ใน Base64 ส่งข้อมูลมากกว่าจำเป็น 33% สำหรับค่าเล็กเช่น token สั้นหรือ checksum, overhead ไม่สำคัญ สำหรับไฟล์ใหญ่ มันเป็นต้นทุนจริง

แบบ URL-Safe

Base64 มาตรฐานใช้ + และ / เป็นตัวอักษรสองตัวสุดท้าย ทั้งสองเป็นปัญหาใน URL:

  • + ถูกถอดรหัสเป็นตัวอักษรช่องว่างใน query string
  • / เป็นตัวคั่น path ใน URL

Base64 URL-safe (เรียกอีกชื่อว่า Base64url, นิยามใน RFC 4648 Section 5) แทน + ด้วย - และ / ด้วย _ Padding (=) มักถูกละไว้ในบริบท URL-safe เพราะมันยังอาจถูกตีความผิดโดย URL parser บางตัว

JWT token ใช้ Base64url โดยไม่มี padding เมื่อคุณถอดรหัส JWT header หรือ payload ด้วยมือ คุณต้องจัดการทั้งการแทนตัวอักษรและ padding ที่ขาด นี่คือวิธีทำใน JavaScript:

// Base64 URL-safe (แทน + ด้วย - และ / ด้วย _)
function toBase64Url(base64) {
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

function fromBase64Url(base64url) {
  const padded = base64url.padEnd(
    base64url.length + (4 - base64url.length % 4) % 4,
    '='
  );
  return atob(padded.replace(/-/g, '+').replace(/_/g, '/'));
}

Base64 encoder/decoder ของ Toova รองรับทั้งแบบมาตรฐานและ URL-safe ด้วย toggle เดียว

Base64 ใน JavaScript

เบราว์เซอร์: btoa() และ atob()

เบราว์เซอร์ให้ฟังก์ชันในตัวสอง: btoa() (binary to ASCII คือ encode) และ atob() (ASCII to binary คือ decode) แม้ลำดับชื่อสับสน, พวกมันมีในเบราว์เซอร์มาเกินทศวรรษ

// เบราว์เซอร์ — atob / btoa (สตริงเท่านั้น, ปลอดภัย ASCII)
const encoded = btoa("Hello");
console.log(encoded); // "SGVsbG8="

const decoded = atob("SGVsbG8=");
console.log(decoded); // "Hello"

ข้อจำกัดสำคัญ: btoa() ยอมรับเฉพาะสตริงที่มีตัวอักษรในช่วง Latin-1 (code point 0-255) หากส่งสตริงที่มีตัวอักษร Unicode เช่น emoji หรือตัวอักษร CJK, มันจะ throw DOMException เพื่อเข้ารหัสข้อมูล binary ใด แปลงเป็น Uint8Array ก่อน:

// เบราว์เซอร์ — เข้ารหัส binary ใดๆ (Uint8Array)
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
const encoded = btoa(String.fromCharCode(...bytes));
console.log(encoded); // "SGVsbG8="

สำหรับการเข้ารหัสสตริงใดที่อาจมีตัวอักษร Unicode, วิธีสมัยใหม่ที่แนะนำคือใช้ TextEncoder เพื่อให้ได้ Uint8Array ก่อน จากนั้นเข้ารหัสตามที่แสดงด้านบน

Node.js: Buffer

Node.js ให้คลาส Buffer ซึ่งจัดการข้อมูล binary ได้ถูกต้องและรองรับการเข้ารหัสหลายตัวรวม Base64 และ Base64url:

// Node.js — Buffer (จัดการ binary ได้อย่างปลอดภัย)
const encoded = Buffer.from('Hello').toString('base64');
console.log(encoded); // "SGVsbG8="

const decoded = Buffer.from('SGVsbG8=', 'base64').toString('utf8');
console.log(decoded); // "Hello"

// แบบ URL-safe ใน Node.js
const urlSafe = Buffer.from('Hello').toString('base64url');
console.log(urlSafe); // "SGVsbG8" (ไม่มี padding)

ตัวเลือกการเข้ารหัส base64url (มีตั้งแต่ Node.js 16) จัดการการแทนตัวอักษรและการเอา padding ออกโดยอัตโนมัติ ทำให้ง่ายกว่ามากเมื่อเทียบกับการทำการแปลงด้วยมือ

สำหรับสภาพแวดล้อมเบราว์เซอร์ที่ต้องจัดการไฟล์ binary ใหญ่, วิธี FileReader.readAsDataURL เข้ารหัสไฟล์เป็น Base64 data URI โดยไม่โหลดทุกอย่างเข้า memory ครั้งเดียว

เมื่อใดควรใช้ Base64

การฝังข้อมูล binary ในโปรโตคอลข้อความเท่านั้น

การใช้งานต้นฉบับสำหรับ Base64 คือการเข้ารหัสไฟล์แนบอีเมล binary ใน SMTP, โปรโตคอลที่รองรับเพียงข้อความ ASCII 7-bit หลักการเดียวกันใช้ทุกที่ที่ต้องรวมข้อมูล binary ใน format ที่ไม่สามารถจัดการไบต์ดิบ: payload API JSON, เอกสาร XML, attribute HTML, ค่า CSS, ส่วนหัว HTTP

Data URI สำหรับ asset เล็ก

CSS และ HTML อนุญาตให้คุณฝังภาพ, font และ SVG เป็น Base64 data URI สิ่งนี้ขจัด round-trip HTTP สำหรับ asset เล็กเช่นไอคอนและขจัด flash-of-unstyled-content สำหรับภาพ above-the-fold ที่สำคัญ

<!-- ไอคอน SVG inline เป็น Base64 data URI -->
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0c..." alt="icon" />

<!-- พื้นหลัง CSS inline -->
.icon {
  background-image: url("data:image/png;base64,iVBORw0KGgo...");
}

การแลกเปลี่ยน: Base64 data URI ไม่สามารถ cache แยกจากไฟล์ HTML/CSS ที่บรรจุ หากภาพไม่เคยเปลี่ยนแต่ HTML รอบเปลี่ยน เบราว์เซอร์ดาวน์โหลดข้อมูลภาพใหม่ทุกการโหลดหน้า ใช้ data URI เฉพาะสำหรับ asset เล็ก (ปกติต่ำกว่า 4 KB) ที่การขจัด round-trip ชนะค่าโทษ cache

การเข้ารหัสข้อมูล binary สำหรับ JSON หรือพารามิเตอร์ URL

JSON คือ format ข้อความ — ไม่สามารถแทนไบต์ binary ดิบโดยตรง เมื่อ API ต้องส่งข้อมูล binary (thumbnail ภาพ, ลายเซ็นเชิงเข้ารหัส, ข้อมูลที่บีบ), Base64 เป็นวิธีมาตรฐานที่จะรวมใน payload JSON ในทำนองเดียวกัน หากต้องส่งข้อมูล binary ในพารามิเตอร์ query URL, การเข้ารหัส Base64url รับประกันว่าข้อมูลรอดผ่าน percent-encoding โดยไม่เสียหาย

JWT และ format token อื่น

JWT token ใช้ Base64url เข้ารหัสส่วน header และ payload ของพวกมัน สิ่งนี้ทำให้ token เป็นสตริงที่พิมพ์ได้, URL-safe ที่สามารถส่งในส่วนหัว HTTP, cookie หรือพารามิเตอร์ URL การเข้ารหัสไม่ใช่สำหรับความปลอดภัย (payload อ่านได้โดยใครก็ตามที่มี token) — เพียงสำหรับการส่งที่ปลอดภัย

เมื่อใดไม่ควรใช้ Base64

ความปลอดภัยหรือความลับ

Base64 ให้ความปลอดภัยศูนย์ มันกลับคืนได้ง่ายในมิลลิวินาที อย่าใช้เพื่อ "obfuscate" รหัสผ่าน, API key หรือค่า config ที่ละเอียดอ่อน นักพัฒนาใดที่เห็นสตริง Base64 จะถอดรหัสทันที หากต้องการความลับ ใช้การเข้ารหัสลับ

การเก็บรหัสผ่าน

การเก็บรหัสผ่านที่เข้ารหัส Base64 เหมือนกับการเก็บใน plain text — การเข้ารหัสกลับคืนได้ทันที รหัสผ่านต้องถูก hash ด้วยฟังก์ชัน hash รหัสผ่านที่เหมาะเช่น bcrypt, Argon2 หรือ scrypt

ไฟล์ binary ใหญ่

การเข้ารหัสไฟล์ 10 MB เป็น Base64 ผลิตสตริง 13.7 MB หากคุณเก็บใน column ฐานข้อมูล, ค้นผ่าน หรือส่งผ่าน API, คุณจ่าย 33% overhead ทุกครั้ง สำหรับข้อมูล binary ใหญ่ ใช้ที่เก็บ binary เฉพาะ: column ฐานข้อมูล BLOB/BYTEA, object storage เช่น S3 หรือ GCS หรือ stream binary โดยตรง

สถานการณ์ที่คุณสามารถใช้ binary ตรง

หากโปรโตคอลหรือ format ของคุณรองรับ binary ดิบ — เช่น WebSocket ที่มีประเภทข้อความ binary, การอัปโหลด HTTP multipart/form-data หรือ format ไฟล์ binary — ใช้ binary โดยตรง Base64 จำเป็นเฉพาะเมื่อ medium การส่งไม่สามารถจัดการไบต์ดิบจริง

กับดักทั่วไป

สับสนการเข้ารหัสกับการเข้ารหัสลับ

นี่คือข้อผิดพลาดที่พบบ่อยที่สุด Base64 มองเห็นได้ มันไม่ใช่กลไกความปลอดภัย คอมเมนต์โค้ดอย่าง "รหัสผ่านถูกเก็บเป็น Base64-encoded เพื่อความปลอดภัย" แสดงถึงความเข้าใจผิดที่ร้ายแรงที่ควรจับในการรีวิวโค้ด

การใช้ btoa() กับสตริง Unicode

การเรียก btoa() บนสตริงที่มีตัวอักษรที่มี code point เหนือ 255 throw DOMException: Failed to execute 'btoa': The string to be encoded contains characters outside of the Latin1 range แปลงเป็น Uint8Array ผ่าน TextEncoder เสมอก่อนเข้ารหัสสตริงที่อาจมีตัวอักษร Unicode

ลืม padding เมื่อถอดรหัส

สตริง Base64 ต้องมีความยาวที่เป็นพหุคูณของ 4 หากสตริง Base64 ถูกสร้างโดยไม่มี padding (พบบ่อยในการเข้ารหัส URL-safe), คุณต้องเพิ่มตัวอักษร = จำนวนที่ถูกกลับก่อนถอดรหัส สตริง Base64 ที่มีความยาว n ต้องการตัวอักษร padding (4 - n % 4) % 4 การลืมเรื่องนี้ทำให้เกิด error การถอดรหัสที่ยากวินิจฉัย

การเข้ารหัสซ้อน

สตริง Base64 เองคือ ASCII ที่ถูกต้อง ดังนั้น btoa(btoa(data)) ทำงานโดยไม่มี error แต่ผลิต output ที่เข้ารหัสซ้อน เมื่อส่งค่า Base64 ผ่านการ serialize หลายชั้น (JSON ภายใน JSON เช่น), ง่ายที่จะเข้ารหัสข้อมูลเดียวกันสองครั้ง ถอดรหัสจำนวนครั้งเป๊ะที่เข้ารหัสเสมอ

อ้างอิงด่วน: Base64 ในทางปฏิบัติ

สำหรับการเข้ารหัสและถอดรหัสในเบราว์เซอร์โดยไม่เขียนโค้ด, Toova Base64 encoder/decoder ทำงานในเบราว์เซอร์ของคุณทั้งหมด — ไม่มี round-trip เซิร์ฟเวอร์ รองรับทั้งแบบมาตรฐานและ URL-safe, การอัปโหลดไฟล์สำหรับการเข้ารหัสไฟล์ binary และ output ทั้งข้อความและ hex สำหรับข้อมูลที่ถอดรหัส

หากกำลังทำงานกับเนื้อหาที่เข้ารหัสภายใน URL, URL encoder/decoder จัดการ percent-encoding แยกจาก Base64 สำหรับ HTML entity, HTML entities converter จัดการ character escaping ในบริบท HTML เหล่านี้คือรูปแบบการเข้ารหัสที่ต่างกัน — แต่ละตัวมีการใช้งานเฉพาะ

อ้างอิงที่เป็นทางการสำหรับ Base64 คือ RFC 4648 ซึ่งนิยาม Base64 มาตรฐาน (Section 4), Base64url (Section 5) และ Base32 (Section 6-7) สำหรับ API เบราว์เซอร์ btoa() และ atob(), เอกสาร MDN สำหรับ btoa() ครอบคลุมความเข้ากันของเบราว์เซอร์และข้อจำกัด Unicode อย่างละเอียด

สรุป

การเข้ารหัส Base64 แปลงข้อมูล binary เป็น ASCII ที่พิมพ์ได้โดยใช้ตัวอักษร 64 ตัว มันเพิ่มขนาดข้อมูล 33%, กลับคืนได้สมบูรณ์ และไม่ให้ความปลอดภัย ใช้เมื่อต้องฝังข้อมูล binary ใน format ที่อิงข้อความ — payload JSON, data URI HTML, JWT token, ไฟล์แนบอีเมล, พารามิเตอร์ URL หลีกเลี่ยงเมื่อต้องการความปลอดภัย, เมื่อการขนส่งรองรับ binary ตรง หรือเมื่อ 33% overhead สำคัญที่ระดับใหญ่

การเข้าใจว่า Base64 คืออะไร — และไม่ใช่อะไร — ป้องกันข้อผิดพลาดที่พบบ่อยที่สุด: การใช้สำหรับความปลอดภัย, การใช้กับไฟล์ใหญ่โดยไม่จำเป็น และความสับสนกับรูปแบบการเข้ารหัสอื่นเช่น URL encoding หรือ HTML entity แต่ละรูปแบบการเข้ารหัสแก้ปัญหาเฉพาะ Base64 แก้เพียงหนึ่ง: ทำให้ข้อมูล binary ปลอดภัยสำหรับช่องข้อความเท่านั้น

พร้อมเข้ารหัสหรือถอดรหัส? ลอง Toova Base64 encoder/decoder — paste ข้อความหรือ drop ไฟล์, toggle มาตรฐานหรือ URL-safe และคัดลอกผล ไม่มีบัญชี, ไม่มีเซิร์ฟเวอร์, ไม่มีขีดจำกัด