เครื่องมือสำหรับนักพัฒนา · ตัวเข้ารหัสและตัวถอดรหัส Base64
RFC 4648 อธิบาย: มาตรฐานที่กำหนด Base64, base32 และ base16
· พื้นหลัง
base64 การเข้ารหัส
RFC 4648 เป็นเอกสารขนาดสั้นที่สามารถอ่านได้เบื้องหลังการใช้งาน Base64 ทุกครั้ง โพสต์นี้จะอธิบายสิ่งที่ระบุ สิ่งที่จงใจเปิดทิ้งไว้ และเหตุใดการใช้งานจึงยังแตกต่างออกไป
ห้องสมุดสองแห่ง สองคำตอบสำหรับสตริงเดียวกัน - ปริศนาการทำงานร่วมกันอย่างแท้จริงที่มีเพียงมาตรฐานเท่านั้นที่ตัดสิน
ไลบรารี JavaScript สองไลบรารีสามารถส่งคืน Base64 ที่แตกต่างกันสำหรับสตริงเดียวกัน โดยแต่ละไลบรารีอ้างว่าถูกต้อง RFC 4648 เป็นเอกสารสิบสองหน้าที่สามารถอ่านได้ซึ่งควรแก้ไขข้อขัดแย้งดังกล่าว แต่การใช้งานยังคงแตกต่างออกไปเนื่องจาก RFC จงใจปล่อยให้การตัดสินใจบางอย่างแก่แอปพลิเคชัน บทความนี้จะอธิบายสิ่งที่ RFC 4648 ระบุ สิ่งที่ตั้งใจมอบหมายให้กับผู้โทร และเหตุใดการอ่านมาตรฐานเพียงครั้งเดียวจึงช่วยไขปริศนาความสามารถในการทำงานร่วมกันได้จริงส่วนใหญ่ เครื่องมือเข้ารหัสและถอดรหัส Base64 ประกอบด้วยเวกเตอร์ทดสอบ RFC 4648 เพื่อให้คุณสามารถตรวจสอบการใช้งานกับตัวอย่างที่เชื่อถือได้
RFC 4648 แทนที่และรวมเอกสารก่อนหน้านี้หลายฉบับ: Base64 จาก MIME (RFC 2045), Base64 จาก Privacy-Enhanced Mail (RFC 1421), base32 จาก S/MIME (RFC 2630) และ base16 จากแหล่งต่างๆ การรวมข้อมูลมีความจำเป็นเนื่องจาก MIME และ PEM แต่ละตัวมีตัวอักษรและกฎของตัวเอง และการตัดบรรทัด MIME ขัดแย้งกับบล็อกคอลัมน์ PEM ของ 64 RFC 4648 กำหนดกลุ่มการเข้ารหัสห้ากลุ่มในที่เดียว: base64, base64url, base32, base32hex และ base16 แต่ละกลุ่มมีตัวอักษรของตัวเอง กฎการเติม และเวกเตอร์ทดสอบตัวอย่าง ตัวอักษรฐาน 64 คือ A-Z, a-z, 0-9 บวกและเครื่องหมายทับตามลำดับนั้น
สิ่งที่เวกเตอร์การใช้งานและการทดสอบสร้างขึ้น - ตัวอักษรมาตรฐานและ URL-ปลอดภัย การจัดการช่องว่างภายใน และช่องว่าง
อักขระแต่ละตัวแสดงถึง 6 bits; ไบต์อินพุตสามไบต์ (24 bits) แมปกับอักขระเอาต์พุตสี่ตัว ตัวอักษรไม่ได้กำหนดเอง: โดยหลีกเลี่ยงอักขระที่แตกต่างกันระหว่าง EBCDIC และ ASCII โดยหลีกเลี่ยงอักขระควบคุม เครื่องหมายคำพูด และแบ็กสแลชที่ต้องมีการ Escape ในตัวอักษรสตริง C รูปแบบ base64url จะแทนที่เครื่องหมายบวกด้วยขีดกลางและเครื่องหมายทับด้วยขีดล่างเพื่อหลีกเลี่ยงอักขระที่สงวนไว้ใน URL และชื่อไฟล์ ตัวแปรทั้งสองมีความถูกต้องเท่าเทียมกัน RFC 4648 ส่วน 2 ระบุ base64 ส่วน 5 ระบุ base64url และแอปพลิเคชันจะต้องระบุว่าแอปพลิเคชันใดใช้
การเติมด้วยอักขระที่เท่ากันจะทำให้เอาต์พุตมีอักขระหลายตัวจากสี่อักขระ หากอินพุตคือ 1 byte (8 bits) เอาต์พุตจะเป็นอักขระสองตัวบวกเครื่องหมายเท่ากับสองตัว หากอินพุตคือ 2 bytes (16 bits) เอาต์พุตจะมีอักขระสามตัวบวกหนึ่งเครื่องหมายเท่ากับ หากอินพุตเป็นผลคูณของ 3 bytes ก็ไม่จำเป็นต้องเติมช่องว่าง แอปพลิเคชั่นบางตัวละเว้นช่องว่างภายในหรือปล่อยให้ช่องว่างภายในหายไปในการถอดรหัส RFC 4648 ส่วน 3.2 กำหนดการเข้ารหัสแบบ Canonical ให้มีเบาะเสมอ แต่ส่วน 3.3 ตั้งข้อสังเกตว่าตัวถอดรหัสอาจยอมรับช่องว่างภายในที่ขาดหายไปเพื่อความเข้ากันได้
ตัวอักษรที่เครื่องมือนี้ใช้ — Base64 และ Base64url มาตรฐาน ฐานอื่น ๆ ยังอยู่นอกขอบเขต
ความแตกต่างจากการเติมคือสาเหตุที่การใช้งานไม่เห็นด้วย: ตัวถอดรหัสที่เข้มงวดจะปฏิเสธการหายไปที่เท่าเทียมกัน ในขณะที่ตัวถอดรหัสที่ผ่อนปรนจะยอมรับมัน RFC 4648 กล่าวอย่างชัดเจน: โดยทั่วไปแล้วอักขระของแพดเท่ากับจะถูกเข้ารหัสเป็นเปอร์เซ็นต์เมื่อใช้ใน URL ดังนั้นหากใช้เอาต์พุต base64url โดยตรงในพารามิเตอร์ URL ก็ไม่จำเป็นต้องมีการเติมช่องว่างและควรละเว้น ประโยคนี้เป็นเหตุผลหนึ่งที่ URL-โหมดปลอดภัยและการละเว้นช่องว่างภายในมักถูกจับคู่กัน แม้ว่าทั้งสองตัวเลือกจะแยกกันก็ตาม ส่วน 5 (base64url) ไม่ห้ามการเติม มันเป็นเพียงบันทึกการปฏิบัติทั่วไป
ผู้เรียกที่เลือก base64url ต้องตัดสินใจว่าจำเป็นต้องมีการเติมสำหรับระบบรับหรือไม่ อักขระที่ไม่ใช่ตัวอักษรในอินพุตจะได้รับการจัดการที่แตกต่างกันโดยตัวถอดรหัสที่ต่างกัน RFC 4648 ส่วน 3.1 สถานะ: การใช้งาน MUST ปฏิเสธการเข้ารหัสหากมีอักขระนอกตัวอักษรฐาน อย่างไรก็ตาม ส่วน 3.3 ตั้งข้อสังเกตว่า MIME Base64 (RFC 2045) อนุญาตให้มีการขึ้นบรรทัดใหม่สำหรับ 76 การตัดอักขระ และตัวถอดรหัสสำหรับ MIME จะต้องข้ามช่องว่าง RFC แยกความแตกต่างระหว่างการถอดรหัสแบบเข้มงวด (ปฏิเสธที่ไม่ใช่ตัวอักษรทั้งหมด) และการถอดรหัสที่เข้ากันได้กับ MIME (ข้ามช่องว่าง ปฏิเสธอักขระอื่นๆ)
การเติม อักขระที่ไม่ใช่ตัวอักษร และการเข้ารหัสตามรูปแบบบัญญัติ — ส่วนที่อธิบายความขัดแย้งของตัวถอดรหัสส่วนใหญ่
แอปพลิเคชันจะต้องเลือกว่าจะปฏิบัติตามกฎใด มาตรฐานกำหนดทั้งสองอย่าง Base32 ใช้ A-Z และ 2-7 (32 อักขระทั้งหมด) เข้ารหัสไบต์อินพุตห้าไบต์ (40 bits) ถึงแปดอักขระเอาต์พุต Base32hex แทนที่ 0-9 และ a-v สำหรับอักขระตัวอักษร ซึ่งมีประโยชน์ในบริบทที่ต้องการใช้อักษรตัวพิมพ์เล็ก
ฐาน 16 เป็นเลขฐานสิบหก: 0-9 และ a-f Base32 และ base32hex มีกฎการเติมของตัวเองในส่วน 6 และ 7 และ RFC จัดเตรียมเวกเตอร์ทดสอบแยกกันสำหรับตัวอักษรแต่ละตัว นักพัฒนาส่วนใหญ่ต้องการเพียง base64 และ base64url เท่านั้น base32, base32hex และ base16 จะรวมอยู่ใน RFC เพื่อความสมบูรณ์และสำหรับแอปพลิเคชันเช่น TOTP ความลับ (RFC 4226) และการเข้ารหัส DNS
ตัวเลือกแอปพลิเคชันที่มองเห็นได้ในการใช้งานนี้ — การตัดบรรทัด การถอดรหัสข้อความที่เข้มงวด และการจัดการข้อผิดพลาด
เวกเตอร์ทดสอบใน RFC 4648 เป็นความจริงพื้นฐานสำหรับการตรวจสอบการใช้งาน การเข้ารหัสสตริง f, fo, foo, foob, fooba และ foobar จะสร้างเอาต์พุต base64 เฉพาะ: Zg==, Zm8=, Zm9v, Zm9vYg==, Zm9vYmE= และ Zm9vYmFy การใช้งานที่สร้างผลลัพธ์ที่แตกต่างกันสำหรับสายอักขระเหล่านี้ไม่ถูกต้อง RFC ให้เวกเตอร์ทดสอบที่เทียบเท่าสำหรับ base32, base32hex และ base16 เครื่องมือเข้ารหัสและถอดรหัส Base64 มีเวกเตอร์เหล่านี้เพื่อให้คุณสามารถตรวจสอบเอาต์พุตกับมาตรฐานได้ การตัดบรรทัดถือเป็นข้อกังวล MIME ไม่ใช่ข้อกังวลของ base64
RFC 2045 ระบุ 76-บรรทัดอักขระ; RFC 4648 ส่วน 3.1 บันทึกสิ่งนี้ในบริบทของ MIME แต่ไม่ได้กำหนดให้เป็นข้อกำหนดของ base64 เอง แอปพลิเคชันบางตัวจะมีความยาว 64 อักขระ (มาตรฐาน PEM ดั้งเดิม) คนอื่นไม่ห่อเลย ตัวถอดรหัส RFC 4648 base64 ที่เข้มงวดทำงานบนตัวอักษรและช่องว่างภายในเท่านั้น ตัวถอดรหัสที่เข้ากันได้กับ MIME จะต้องข้ามการขึ้นบรรทัดใหม่ (CR, LF, CRLF) แอปพลิเคชันที่ใช้ base64 ภายนอก MIME ไม่ควรเพิ่มตัวแบ่งบรรทัด เว้นแต่ระบบที่รับจะกำหนดให้ใช้ RFC ไม่ได้กำหนดการตัดบรรทัดเป็นส่วนหนึ่งของ base64
ตัวอย่างการทำงาน: เวกเตอร์ทดสอบของ RFC เอง - เข้ารหัสคำนำหน้า 'foobar' และตรวจสอบในเบราว์เซอร์
การจัดการช่องว่างเป็นอีกจุดหนึ่งของความแปรปรวนในการใช้งาน RFC 4648 กล่าวว่าตัวถอดรหัสที่เข้มงวดจะต้องปฏิเสธอักขระที่ไม่ใช่ตัวอักษร MIME-wrapped base64 (RFC 2045 base64) อนุญาตให้มีช่องว่างสำหรับการจัดรูปแบบ มาตรฐานทั้งสองเห็นพ้องกันว่าไบต์เอาท์พุตควรเป็นเท่าใด แต่แตกต่างกันขึ้นอยู่กับว่าอินพุตใดถูกต้อง การใช้งาน JavaScript ส่วนใหญ่เลือกความเข้ากันได้ MIME และข้ามช่องว่าง กฎที่เข้มงวดนั้นไม่ค่อยได้ใช้ในเบราว์เซอร์ ตัวเข้ารหัสและตัวถอดรหัส Base64 ยอมรับทั้งที่มีช่องว่าง (MIME) และอินพุตที่เข้มงวด ทำให้เห็นความแตกต่างที่ชัดเจน การถอดรหัสแบบ Canonical และการให้อภัยถือเป็นความแปรปรวนหลักขั้นสุดท้าย
การถอดรหัส Canonical เป็นไปตาม RFC 4648 ส่วน 3.2: ปฏิเสธการเติมที่มีรูปแบบไม่ถูกต้อง ปฏิเสธการเติมที่ขาดหายไป ปฏิเสธอักขระที่ไม่ใช่ตัวอักษร การถอดรหัสแบบให้อภัยที่ใช้ในมาตรฐานเว็บ (ข้อกำหนด HTML เรียกว่า forgiving-base64) เพิ่มกฎ: ละเว้นช่องว่าง ยอมรับช่องว่างภายในที่ขาดหายไป อนุญาตให้ใช้เส้นประและขีดเส้นใต้รวมทั้งบวกเครื่องหมายทับแม้ในโหมดมาตรฐาน base64 atob() ของ JavaScript กำลังให้อภัย ตัวถอดรหัส RFC 4648 ที่เข้มงวดนั้นเข้มงวดกว่า ไม่มีอะไรผิด พวกเขาให้บริการบริบทที่แตกต่างกัน แอปพลิเคชันที่อ่านข้อมูลจากผู้ใช้หรือจากเครือข่ายควรรู้ว่าอีกฝ่ายคาดหวังกฎใด
สิ่งนี้ไม่ครอบคลุม — ตัวเอกสาร MIME และ PEM และ API เฉพาะภาษา
RFC มีตัวเลือกเก้าตัวเลือกให้กับแอปพลิเคชัน: ตัวอักษรตัวใดในห้าตัวอักษร ว่าจะต้องมีหรืออนุญาตให้มีช่องว่างภายใน ไม่ว่าจะต้องการหรืออนุญาตให้มีช่องว่าง ไม่ว่าจะใช้เครื่องหมายขีดเส้นใต้บวกกับเครื่องหมายทับ วิธีรายงานข้อผิดพลาด วิธีจัดการกับจุดสิ้นสุดของอินพุต ไม่ว่าจะยอมรับช่องว่างภายในที่หายไป จำนวนไบต์เอาท์พุตที่จะจัดสรร และวิธีส่งสัญญาณขีดจำกัดขนาด ตัวเลือกเหล่านี้อธิบายว่าทำไมการใช้งาน RFC 4648 สองตัวจึงไม่เห็นด้วยกับอินพุตเดียวกัน อ่าน RFC หนึ่งครั้ง ตรวจสอบการใช้งานของคุณกับเวกเตอร์ทดสอบ ระบุตัวเลือกที่แอปพลิเคชันของคุณใช้ ทดสอบการทำงานร่วมกันกับเพียร์จริง ไม่ใช่สมมติฐาน
การทำความเข้าใจ RFC 4648 ยุติข้อพิพาท Base64 ส่วนใหญ่ เนื่องจากความขัดแย้งมักจะไม่เกี่ยวกับ RFC เอง แต่เกี่ยวกับตัวเลือกที่แต่ละฝ่ายเลือก RFC สั้นพอที่จะอ่านตั้งแต่ต้นจนจบได้ภายในหนึ่งชั่วโมง มาตรฐานจะกำหนดตัวอักษร จัดเตรียมเวกเตอร์ทดสอบ และเตือนว่าการใช้งานจะต้องตัดสินใจในส่วนใด เครื่องมือเข้ารหัสและถอดรหัส Base64 ให้คุณทดลองกับเวกเตอร์ทดสอบและดูการทำงานของตัวอักษรมาตรฐาน การใช้งาน base64 ในชีวิตประจำวันส่วนใหญ่ไม่จำเป็นต้องมีความรู้เชิงลึก RFC แต่เมื่อแก้ไขจุดบกพร่องการเข้ารหัสไม่ตรงกันหรือบูรณาการกับ API ที่ไม่คุ้นเคย การอ่านมาตรฐานครั้งเดียวจะช่วยลบการคาดเดาออก
ประเด็นสำคัญ: อ่านมาตรฐานหนึ่งครั้ง - วิธีที่ตัวเข้ารหัสและตัวถอดรหัส Base64 ช่วยให้คุณตรวจสอบเวกเตอร์ทดสอบของตัวอักษรมาตรฐานได้อย่างรวดเร็ว
RFC 4648 คือการผสานรวมการฝึกการเข้ารหัสแบบเฉพาะกิจที่สั่งสมมานานหลายทศวรรษให้เป็นข้อกำหนดเดียวที่สามารถอ่านได้ ไม่ได้กำหนดว่าเมื่อใดควรใช้ base64 (MIME, PEM, JWT, URI ข้อมูล ฯลฯ แต่ละรายการมีข้อกำหนดเฉพาะของตนเอง) มันกำหนดว่า base64 คืออะไร ด้วยการกำหนดกลุ่มการเข้ารหัสห้ากลุ่มและสังเกตว่าตัวเลือกใดเป็นแบบบัญญัติ RFC ทำให้สามารถตรวจสอบได้ว่าการใช้งานนั้นถูกต้องหรือไม่ เวกเตอร์การทดสอบที่เชื่อถือได้เป็นจุดเริ่มต้น: หากการใช้งานของคุณเข้ารหัส foobar และสร้างสิ่งอื่นนอกเหนือจาก Zm9vYmFy RFC จะบอกว่าการใช้งานนั้นผิด
ใช้สิทธิ์นั้นเป็นจุดตรวจสอบการตรวจสอบ: เข้ารหัสเวกเตอร์ทดสอบ RFC แต่ละตัว เปรียบเทียบอักขระที่ตรงกัน จากนั้นถอดรหัสผลลัพธ์เพื่อยืนยันว่าไบต์ต้นฉบับส่งคืนไม่เปลี่ยนแปลง การตรวจสอบโดยใช้เบราว์เซอร์นี้จะแยกข้อผิดพลาดของตัวอักษรหรือช่องว่างจากปัญหาอื่นๆ ในการบูรณาการ ขณะเดียวกันก็รักษามาตรฐานไว้เป็นข้อมูลอ้างอิง แทนที่จะอาศัยป้ายกำกับไลบรารี