ทำไมเราถึงใช้ Base64


275

Wikipediaพูดว่า

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

แต่ไม่ใช่ว่าข้อมูลจะถูกจัดเก็บ / ส่งเป็นไบนารี่เสมอเพราะหน่วยความจำที่เครื่องของเรามีไบนารี่สโตร์และมันก็ขึ้นอยู่กับว่าคุณตีความมันอย่างไร ดังนั้นไม่ว่าคุณจะเข้ารหัสรูปแบบบิต010011010110000101101110เช่นเดียวกับManใน ASCII หรือTWFuใน Base64 ในที่สุดคุณก็จะเก็บรูปแบบบิตเดียวกัน

หากการเข้ารหัสขั้นสุดท้ายอยู่ในรูปของเลขศูนย์และทุกเครื่องและสื่อสามารถจัดการกับมันได้จะเป็นอย่างไรถ้าข้อมูลถูกแสดงเป็น ASCII หรือ Base64

"สื่อที่ออกแบบมาเพื่อจัดการกับข้อมูลที่เป็นข้อความ" หมายความว่าอย่างไร พวกเขาสามารถจัดการกับ binary => พวกเขาสามารถจัดการกับอะไรก็ได้


ขอบคุณทุกคนฉันคิดว่าฉันเข้าใจแล้ว

เมื่อเราส่งข้อมูลเราไม่สามารถมั่นใจได้ว่าข้อมูลจะถูกตีความในรูปแบบเดียวกับที่เราตั้งใจให้เป็น ดังนั้นเราจึงส่งข้อมูลที่เข้ารหัสในบางรูปแบบ (เช่น Base64) ที่ทั้งสองฝ่ายเข้าใจ ด้วยวิธีนี้แม้ว่าผู้ส่งและผู้รับจะตีความสิ่งเดียวกันต่างกัน แต่เนื่องจากพวกเขาเห็นด้วยกับรูปแบบการเข้ารหัสข้อมูลจะไม่ถูกตีความผิด

จากตัวอย่าง Mark Byers

ถ้าฉันต้องการส่ง

Hello
world!

วิธีหนึ่งคือการส่งใน ASCII เช่น

72 101 108 108 111 10 119 111 114 108 100 33

แต่ไบต์ 10 อาจตีความไม่ถูกต้องว่าเป็นบรรทัดใหม่ที่ปลายอีกด้าน ดังนั้นเราจึงใช้ชุดย่อยของ ASCII เพื่อเข้ารหัสเช่นนี้

83 71 86 115 98 71 56 115 67 110 100 118 99 109 120 107 73 61 61

ซึ่งมีค่าใช้จ่ายในการถ่ายโอนข้อมูลที่มากขึ้นสำหรับข้อมูลจำนวนเดียวกันทำให้มั่นใจได้ว่าผู้รับสามารถถอดรหัสข้อมูลในลักษณะที่ตั้งใจแม้ว่าผู้รับจะเกิดการตีความที่แตกต่างกันสำหรับส่วนที่เหลือของชุดอักขระ


6
ประวัติความเป็นมา: เซิร์ฟเวอร์อีเมลเคยเป็น ASCII 7 บิต หลายคนจะตั้งค่าบิตสูงเป็น 0 ดังนั้นคุณต้องส่งค่า 7 บิตเท่านั้น ดูen.wikipedia.org/wiki/Email#Content_encoding
Harold L

53
เราใช้ base64 เพราะสามารถอ่านได้มากกว่า Perl
Martin

2
@ มาร์ตินคุณล้อเล่น Perl ยากที่จะอ่าน แต่ base64 อ่านไม่ได้เลย
Peter Long

1
@Lazer รูปภาพของคุณหายไป
มิก

2
@Lazer "แต่ไบต์ 10 อาจตีความไม่ถูกต้องว่าเป็นบรรทัดใหม่ที่ปลายอีกด้าน" ทำไม? ทั้งสองฝ่ายได้ตกลงกับ ASCII และพวกเขาจะต้องตีความอย่างถูกต้อง!
ProgramCpp

คำตอบ:


298

ความผิดพลาดครั้งแรกของคุณคือการคิดว่าการเข้ารหัส ASCII และการเข้ารหัส Base64 สามารถใช้แทนกันได้ พวกเขาจะไม่. พวกเขาจะใช้เพื่อวัตถุประสงค์ที่แตกต่างกัน

  • เมื่อคุณเข้ารหัสข้อความใน ASCII คุณเริ่มต้นด้วยสตริงข้อความและแปลงเป็นลำดับไบต์
  • เมื่อคุณเข้ารหัสข้อมูลใน Base64 คุณเริ่มต้นด้วยลำดับไบต์และแปลงเป็นสตริงข้อความ

เพื่อให้เข้าใจว่าเหตุใด Base64 จึงมีความจำเป็นในตอนแรกเราต้องมีประวัติการคำนวณเล็กน้อย


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

เดิมการเข้ารหัสที่แตกต่างกันมากมายถูกสร้างขึ้น (เช่นBaudot code ) ซึ่งใช้จำนวนบิตที่แตกต่างกันต่อตัวอักษรจนกระทั่งในที่สุด ASCII กลายเป็นมาตรฐานที่มี 7 บิตต่อตัวอักษร อย่างไรก็ตามคอมพิวเตอร์ส่วนใหญ่จะเก็บข้อมูลไบนารี่เป็นไบต์ซึ่งประกอบด้วย 8 บิตแต่ละตัวดังนั้นASCIIจึงไม่เหมาะสำหรับการถ่ายโอนข้อมูลประเภทนี้ บางระบบอาจเช็ดบิตที่สำคัญที่สุด นอกจากนี้ความแตกต่างในการเข้ารหัสบรรทัดสิ้นสุดในระบบหมายความว่าอักขระ ASCII 10 และ 13 บางครั้งก็มีการแก้ไข

เพื่อแก้ปัญหาเหล่านี้การเข้ารหัสBase64ถูกนำมาใช้ สิ่งนี้ช่วยให้คุณเข้ารหัสไบต์ของ Aribtrary เป็นไบต์ซึ่งทราบว่าปลอดภัยในการส่งโดยไม่เกิดความเสียหาย (ตัวอักษรและตัวเลข ASCII และสัญลักษณ์สองสามตัว) ข้อเสียคือการเข้ารหัสข้อความโดยใช้ Base64 เพิ่มความยาว - ทุก 3 ไบต์ของข้อมูลจะถูกเข้ารหัสเป็น 4 อักขระ ASCII

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

ในอดีตมันถูกใช้เพื่อเข้ารหัสข้อมูลเลขฐานสองในข้อความอีเมลที่เซิร์ฟเวอร์อีเมลอาจแก้ไขจุดสิ้นสุดบรรทัด ตัวอย่างที่ทันสมัยมากขึ้นคือการใช้ Base64 เข้ารหัสเพื่อข้อมูลภาพฝังโดยตรงในซอร์สโค้ด HTML ที่นี่มีความจำเป็นต้องเข้ารหัสข้อมูลเพื่อหลีกเลี่ยงอักขระเช่น '<' และ '>' ที่ถูกตีความเป็นแท็ก


นี่คือตัวอย่างการทำงาน:

ฉันต้องการส่งข้อความที่มีสองบรรทัด:

สวัสดี
โลก!

ถ้าฉันส่งเป็น ASCII (หรือ UTF-8) มันจะมีหน้าตาแบบนี้:

72 101 108 108 111 10 119 111 114 108 100 33

ไบต์ 10 เสียหายในบางระบบดังนั้นเราจึงสามารถเข้ารหัส 64 ไบต์เหล่านี้เป็นสตริง Base64:

SGVsbG8sCndvcmxkIQ ==

ซึ่งเมื่อเข้ารหัสโดยใช้ ASCII มีลักษณะดังนี้:

83 71 86 115 98 71 56 115 67 110 100 118 99 109 120 107 73 61 61

ไบต์ทั้งหมดในที่นี้รู้จักกันในชื่อไบต์ที่ปลอดภัยดังนั้นจึงมีโอกาสน้อยมากที่ระบบใด ๆ จะทำลายข้อความนี้ ฉันสามารถส่งสิ่งนี้แทนข้อความต้นฉบับของฉันและให้ผู้รับกลับกระบวนการเพื่อกู้คืนข้อความต้นฉบับ


4
"โปรโตคอลการสื่อสารที่ทันสมัยที่สุดจะไม่ทำลายข้อมูล" - แม้ว่าอีเมลอาจมีเอเจนต์การจัดส่งแทนที่สตริงอักขระ "\ n จาก" เป็น "\ n> จาก" เมื่อบันทึกข้อความไปยังกล่องจดหมาย หรือส่วนหัว HTTP ถูกขึ้นบรรทัดใหม่โดยไม่มีวิธีย้อนกลับเพื่อหลีกเลี่ยงการขึ้นบรรทัดใหม่ในข้อมูล base64 ดีกว่าปลอดภัยเพียง 7 บิตมันเป็นตัวอักษรและ - = + / ปลอดภัย
Steve Jessop

1
"ข้อเสียคือการเข้ารหัสข้อความโดยใช้ Base64 เพิ่มความยาว - ทุก 3 ไบต์ของข้อมูลถูกเข้ารหัสเป็น 4 ไบต์" มันเพิ่มขึ้นถึง 4 ไบต์ได้อย่างไร? มันจะยังคงเป็น 3 * 8 = 24 บิตเท่านั้นหรือไม่
Lazer

4
@ Lazer: ไม่ ดูตัวอย่างของคุณเอง - "Man" ถูกเข้ารหัส -64 เป็น "TWFu" 3 ไบต์ -> 4 ไบต์ เป็นเพราะอินพุตได้รับอนุญาตให้เป็นหนึ่งใน 2 ^ 8 = 256 ไบต์ที่เป็นไปได้ในขณะที่เอาต์พุตใช้เพียง 2 ^ 6 = 64 ของพวกเขา (และ = เพื่อช่วยระบุความยาวของข้อมูล) 8 บิตต่อสี่เอาต์พุตเป็น "สูญเปล่า" เพื่อป้องกันไม่ให้เอาต์พุตมีอักขระ "ตื่นเต้น" ใด ๆ แม้ว่าอินพุตทำ
Steve Jessop

2
อาจเป็นประโยชน์ในการย้ำ "เมื่อคุณเข้ารหัสข้อมูลใน Base64 คุณเริ่มต้นด้วยลำดับไบต์และแปลงเป็นสตริงข้อความ" เป็น "เมื่อคุณเข้ารหัสข้อมูลใน Base64 คุณเริ่มต้นด้วยลำดับไบต์และแปลงเป็น ลำดับของไบต์ที่ประกอบด้วยค่า ASCII เท่านั้น " ลำดับของไบต์ที่ประกอบด้วยอักขระ ASCII เพียงอย่างเดียวคือสิ่งที่ SMTP ต้องการซึ่งเป็นสาเหตุที่ Base64 (และที่ยกมาพิมพ์ได้) ถูกใช้เป็นการเข้ารหัสการถ่ายโอนเนื้อหา ภาพรวมที่ยอดเยี่ยม!
ALEXintlsos

1
ฉันจะลงคะแนน แต่มี 64 คะแนน ขออภัยที่สมบูรณ์แบบ
Jessé Catrinck

61

การเข้ารหัสข้อมูลไบนารีใน XML

สมมติว่าคุณต้องการฝังภาพสองภาพภายในเอกสาร XML รูปภาพเป็นข้อมูลไบนารีในขณะที่เอกสาร XML เป็นข้อความ แต่ XML ไม่สามารถจัดการกับข้อมูลไบนารีในตัวได้ แล้วคุณจะทำอย่างไร

ทางเลือกหนึ่งคือการเข้ารหัสภาพใน base64 เปลี่ยนข้อมูลไบนารีเป็นข้อความที่ XML สามารถจัดการได้

แทน:

<images>
  <image name="Sally">{binary gibberish that breaks XML parsers}</image>
  <image name="Bobby">{binary gibberish that breaks XML parsers}</image>
</images>

คุณทำ:

<images>
  <image name="Sally" encoding="base64">j23894uaiAJSD3234kljasjkSD...</image>
  <image name="Bobby" encoding="base64">Ja3k23JKasil3452AsdfjlksKsasKD...</image>
</images>

และตัวแยกวิเคราะห์ XML จะสามารถแยกวิเคราะห์เอกสาร XML ได้อย่างถูกต้องและแยกข้อมูลรูปภาพ


นี่อาจเป็น.mhtรูปแบบเก่าของ Microsoft (ไฟล์ html + รูปในไฟล์เดียว)
Sridhar Sarnobat

38

ทำไมไม่ลองดูRFC ที่กำหนด Base64 ในปัจจุบัน ?

การเข้ารหัสฐานของข้อมูลถูกใช้ในหลาย ๆ สถานการณ์เพื่อจัดเก็บหรือถ่ายโอน
ข้อมูลในสภาพแวดล้อมที่อาจถูก จำกัด ด้วยข้อมูลแบบ US-ASCII [1] ข้อมูลพื้นฐานการเข้ารหัสสามารถใช้ในแอปพลิเคชั่นใหม่ที่ไม่มีข้อ จำกัด แบบดั้งเดิม เพียงเพราะมันเป็นไปได้ที่จะจัดการกับวัตถุด้วยโปรแกรมแก้ไขข้อความ

ในอดีตการใช้งานที่แตกต่างกันนั้นมีข้อกำหนดที่แตกต่างกันและบางครั้งก็ใช้การเข้ารหัสพื้นฐานด้วยวิธีที่ต่างกันเล็กน้อย วันนี้ข้อกำหนดของโปรโตคอลบางครั้งใช้การเข้ารหัสพื้นฐานโดยทั่วไปและโดยเฉพาะ "base64" โดยไม่มีคำอธิบายหรือการอ้างอิงที่แม่นยำ ส่วนขยายจดหมายทางอินเทอร์เน็ตอเนกประสงค์ (MIME) [4] มักถูกใช้เป็นข้อมูลอ้างอิงสำหรับ base64 โดยไม่คำนึงถึงผลที่ตามมาสำหรับการตัดบรรทัดหรืออักขระที่ไม่ใช่ตัวอักษร วัตถุประสงค์ของข้อกำหนดนี้คือการสร้างตัวอักษรทั่วไปและข้อควรพิจารณาเกี่ยวกับการเข้ารหัส หวังว่าสิ่งนี้จะช่วยลดความคลุมเครือในเอกสารอื่น ๆ ซึ่งนำไปสู่การทำงานร่วมกันที่ดีขึ้น

เดิมที Base64 ถูกออกแบบมาเพื่อให้สามารถแนบข้อมูลไบนารีไปกับอีเมลได้ซึ่งเป็นส่วนหนึ่งของส่วนขยายจดหมายอินเทอร์เน็ตอเนกประสงค์


26

สื่อที่ถูกออกแบบมาสำหรับข้อมูลที่เป็นข้อความนั้นแน่นอนว่าในที่สุดไบนารีก็เช่นกัน แต่สื่อที่เป็นข้อความมักจะใช้ค่าไบนารีบางอย่างสำหรับอักขระควบคุม นอกจากนี้สื่อข้อความอาจปฏิเสธค่าไบนารีบางอย่างที่ไม่ใช่ข้อความ

การเข้ารหัส Base64 จะเข้ารหัสข้อมูลไบนารีเป็นค่าที่สามารถตีความได้ว่าเป็นข้อความในสื่อข้อความและไม่มีอักขระพิเศษและ / หรืออักขระควบคุมดังนั้นข้อมูลจะถูกเก็บรักษาไว้ในสื่อต้นฉบับเดิมเช่นกัน


ดังนั้นเหมือนกับ Base64 ส่วนใหญ่ทั้งต้นทางและปลายทางจะตีความข้อมูลในลักษณะเดียวกันเพราะส่วนใหญ่พวกเขาอาจตีความตัวละคร 64 ตัวในลักษณะเดียวกันแม้ว่าพวกเขาจะตีความตัวควบคุมในวิธีที่ต่างกัน นั่นถูกต้องใช่ไหม?
Lazer

6
ข้อมูลเหล่านั้นอาจถูกทำลายระหว่างทาง ตัวอย่างเช่นโปรแกรม FTP จำนวนมากเขียนซ้ำการจบบรรทัดจาก 13,10 ถึง 10 หรือในทางกลับกันหากระบบปฏิบัติการของเซิร์ฟเวอร์และไคลเอนต์ไม่ตรงกันและการถ่ายโอนถูกตั้งค่าสถานะเป็นโหมดข้อความ FTP เป็นเพียงตัวอย่างแรกที่มาถึงใจของฉันมันไม่ดีเพราะ FTP รองรับโหมดไบนารี
Hendrik Brummermann

@nhnb: ฉันคิดว่า FTP เป็นตัวอย่างที่ดีเนื่องจากมันแสดงให้เห็นว่าโหมดข้อความไม่เหมาะสำหรับสิ่งที่ต้องการข้อมูลไบนารี
jamesdlin

สื่อข้อความคืออะไร?
Koray Tugay

18

มันเป็นมากกว่าที่สื่อตรวจสอบของการเข้ารหัสสตริงดังนั้นเราจึงต้องการให้แน่ใจว่าข้อมูลเป็นที่ยอมรับโดยแอปพลิเคชันการจัดการ (และไม่มีลำดับไบนารีที่เป็นตัวแทนของ EOL เช่น)

ลองนึกภาพคุณต้องการส่งข้อมูลไบนารีในอีเมลด้วยการเข้ารหัส UTF-8 - อีเมลอาจแสดงไม่ถูกต้องหากกระแสข้อมูลของคนและค่าศูนย์สร้างลำดับที่ไม่ถูกต้อง Unicode ในการเข้ารหัส UTF-8

สิ่งประเภทเดียวกันนี้เกิดขึ้นใน URL เมื่อเราต้องการเข้ารหัสอักขระไม่ถูกต้องสำหรับ URL ใน URL นั้น:

http://www.foo.com/helloเพื่อนของฉัน -> http://www.foo.com/hello%20my%20friend

นี่เป็นเพราะเราต้องการส่งช่องว่างบนระบบที่จะคิดว่าพื้นที่นั้นมีกลิ่นแรง

ทั้งหมดที่เรากำลังทำคือการสร้างความมั่นใจว่ามีการทำแผนที่ 1 ต่อ 1 ระหว่างที่รู้จักกันดีที่ยอมรับและลำดับที่ไม่เป็นอันตรายของบิตลำดับตัวอักษรอื่นของบิตและการประยุกต์ใช้การจัดการไม่แยกแยะการเข้ารหัส

ในตัวอย่างของคุณmanอาจเป็น ASCII ที่ถูกต้องในรูปแบบแรก แต่บ่อยครั้งที่คุณอาจต้องการส่งค่าที่เป็นไบนารีแบบสุ่ม (เช่นการส่งภาพในอีเมล):

MIME-Version: 1.0
Content-Description: "Base64 encode a.gif"
ประเภทเนื้อหา: image / gif; name = "a.gif"
การเข้ารหัสการถ่ายโอน
เนื้อหา: Base64 การจัดการเนื้อหา: สิ่งที่แนบมา; ชื่อไฟล์ = "a.gif"

ที่นี่เราเห็นว่าภาพ GIF ถูกเข้ารหัสใน base64 เป็นอัน ๆ ของอีเมล ไคลเอนต์อีเมลอ่านส่วนหัวและถอดรหัส เนื่องจากการเข้ารหัสเราสามารถมั่นใจได้ว่า GIF ไม่มีสิ่งใดที่อาจตีความได้ว่าเป็นโปรโตคอลและเราหลีกเลี่ยงการแทรกข้อมูลที่ SMTP หรือ POP อาจพบว่ามีความสำคัญ


1
เยี่ยมมาก - คำอธิบายนี้ทำให้คลิกได้ ไม่ใช่เพื่อทำให้งงงวยหรือบีบอัดข้อมูล แต่เพียงเพื่อหลีกเลี่ยงการใช้ลำดับพิเศษที่สามารถตีความเป็นโปรโตคอล
Patrick Michaelsen

13

Base64 แทนที่จะหนีอักขระพิเศษ

ฉันจะให้คุณตัวอย่างที่แตกต่างกันมาก แต่จริง: ฉันเขียนรหัสจาวาสคริปต์เพื่อให้ทำงานในเบราว์เซอร์ แท็ก HTML มีค่า ID แต่มีข้อ จำกัด เกี่ยวกับอักขระที่ใช้ได้ใน ID

แต่ฉันต้องการให้ ID ของฉันอ้างถึงไฟล์ในระบบไฟล์ของฉันโดยไม่สูญเสียข้อมูล ไฟล์ในความเป็นจริงสามารถมีตัวละครที่แปลกและน่าทึ่งได้จากเครื่องหมายอัศเจรีย์ตัวละครที่เน้นเสียงตัวหนอนแม้แต่อีโมจิ! ฉันทำไม่ได้:

<div id="/path/to/my_strangely_named_file!@().jpg">
    <img src="http://myserver.com/path/to/my_strangely_named_file!@().jpg">
    Here's a pic I took in Moscow.
</div>

สมมติว่าฉันต้องการเรียกใช้รหัสเช่นนี้:

# ERROR
document.getElementById("/path/to/my_strangely_named_file!@().jpg");

ฉันคิดว่ารหัสนี้จะล้มเหลวเมื่อดำเนินการ

ด้วย Base64 ฉันสามารถอ้างถึงบางสิ่งที่ซับซ้อนโดยไม่ต้องกังวลว่าภาษาใดที่อนุญาตให้ใช้อักขระพิเศษใดและต้องการหลบหนี:

document.getElementById("18GerPD8fY4iTbNpC9hHNXNHyrDMampPLA");

แตกต่างจากการใช้ MD5 หรือฟังก์ชั่นการแปลงแป้นพิมพ์อื่น ๆ คุณสามารถย้อนกลับการเข้ารหัสเพื่อค้นหาว่าข้อมูลนั้นมีประโยชน์จริงๆ

ฉันหวังว่าฉันรู้เกี่ยวกับ Base64 ปีที่แล้ว ฉันจะหลีกเลี่ยงการฉีกผมด้วย ' encodeURIComponent' และstr.replace(‘\n’,’\\n’)

การถ่ายโอนข้อความ SSH:

หากคุณกำลังพยายามส่งข้อมูลที่ซับซ้อนไปยัง ssh (เช่น dotfile เพื่อให้คุณได้รับการปรับแต่งเปลือกของคุณ) ขอให้โชคดีโดยไม่ต้องใช้ Base 64 นี่คือวิธีที่คุณจะใช้กับ base 64 (ฉันรู้ว่าคุณสามารถใช้ SCP ได้ แต่นั่นจะใช้หลายคำสั่ง - ซึ่งทำให้การเชื่อมโยงคีย์สำหรับ sshing เข้าสู่เซิร์ฟเวอร์มีความซับซ้อน):


12

ตัวอย่างหนึ่งของเมื่อผมพบว่ามันเป็นความสะดวกสบายเมื่อพยายามที่จะข้อมูลไบนารีฝังในรูปแบบ XML ตัวแยกวิเคราะห์ SAX บางส่วนถูกตีความผิดเนื่องจากข้อมูลนั้นอาจเป็นอะไรก็ได้รวมถึงอักขระพิเศษ XML Base64 เข้ารหัสข้อมูลที่จุดสิ้นสุดการส่งข้อมูลและถอดรหัสที่จุดรับที่ได้รับการแก้ไขปัญหานั้น


1
+1 - แต่นี่ไม่ได้หมายความว่าเฉพาะ SAX มันจะเกิดขึ้นกับตัวแยกวิเคราะห์ XML ใด ๆ เช่น DOM หรือ XLINQ
Billy ONeal

1
@Billy: ใช่แน่นอน ฉันเพิ่งจะใช้ SAX parser สำหรับแอปพลิเคชันนั้น
Bill the Lizard

เอ็นจิ้นที่แตกต่างกันตัวอย่างเช่นตัวแยกวิเคราะห์ SAX อาจตีความค่า ASCII บางส่วนด้วยวิธีที่ต่างกัน (อักขระควบคุมต่างกัน) ดังนั้นความคิดที่นี่คือการใช้ชุดย่อยของ ASCII ที่มีความหมายทั่วไปในระดับสากล ขวา?
Lazer

1
@Lazer: ถูกต้อง ข้อมูลไบนารีที่ไม่มีการเข้ารหัสจะมีอักขระควบคุมอยู่โดยบังเอิญเมื่อคุณพยายามตีความว่าเป็น ASCII (ซึ่งในกรณีนี้มันไม่ใช่)
Bill the Lizard

10

คอมพิวเตอร์ส่วนใหญ่เก็บข้อมูลในรูปแบบไบนารี 8 บิต แต่นี่ไม่ใช่ข้อกำหนด เครื่องจักรและสื่อส่งสัญญาณบางอย่างสามารถจัดการ 7 บิต (หรืออาจน้อยกว่า) ในแต่ละครั้ง สื่อดังกล่าวจะตีความกระแสในทวีคูณของ 7 บิตดังนั้นถ้าคุณจะส่งข้อมูล 8 บิตคุณจะไม่ได้รับสิ่งที่คุณคาดหวังในอีกด้านหนึ่ง Base-64 เป็นเพียงวิธีหนึ่งในการแก้ปัญหานี้: คุณเข้ารหัสอินพุตเป็นรูปแบบ 6 บิตส่งผ่านสื่อของคุณและถอดรหัสกลับเป็นรูปแบบ 8 บิตที่จุดสิ้นสุดการรับ


3
ทำไมมันเป็นปัญหาถ้ากระแสขัดจังหวะหลังจาก 7 บิต ในตอนท้ายเครื่องอื่นจะมีข้อมูลทั้งหมดที่ได้รับจากกระแสข้อมูลจากนั้นสามารถเลือกรูปแบบ 8 บิตสำหรับแสดงผลได้หรือไม่ มีอะไรผิดปกติในใจของฉัน!
mallaudin

6

นอกเหนือจากคำตอบอื่น ๆ (ค่อนข้างยาว): แม้จะไม่สนใจระบบเก่าที่รองรับเพียง ASCII 7 บิตปัญหาพื้นฐานเกี่ยวกับการจัดหาข้อมูลไบนารีในโหมดข้อความคือ:

  • โดยทั่วไปบรรทัดใหม่จะถูกแปลงในโหมดข้อความ
  • จะต้องระมัดระวังไม่ให้ถือ NUL ไบต์เป็นจุดสิ้นสุดของสตริงข้อความซึ่งเป็นเรื่องง่ายเกินไปที่จะทำในโปรแกรมใด ๆ กับ C lineage

นอกจากนี้ยังมีอักขระควบคุมเช่น ^ C, ^ D และ ^ Z ซึ่งตีความว่าเป็นจุดสิ้นสุดไฟล์ในบางแพลตฟอร์ม
dan04

5

"สื่อที่ออกแบบมาเพื่อจัดการกับข้อมูลที่เป็นข้อความ" หมายความว่าอย่างไร

โปรโตคอลเหล่านั้นได้รับการออกแบบมาเพื่อจัดการข้อความ (บ่อยครั้งคือข้อความภาษาอังกฤษเท่านั้น) แทนที่จะเป็นข้อมูลไบนารี (เช่นรูปภาพ. png และ. jpg)

พวกเขาสามารถจัดการกับ binary => พวกเขาสามารถจัดการกับอะไรก็ได้

แต่การสนทนาไม่เป็นความจริง โปรโตคอลที่ออกแบบมาเพื่อแสดงข้อความอาจจัดการข้อมูลไบนารีที่ไม่เหมาะสมซึ่งมี:

  • ไบต์ 0x0A และ 0x0D ใช้สำหรับการสิ้นสุดบรรทัดซึ่งแตกต่างกันตามแพลตฟอร์ม
  • อักขระควบคุมอื่น ๆ เช่น 0x00 (NULL = C string terminator), 0x03 (END OF TEXT), 0x04 (END OF TRANSMISSION) หรือ 0x1A (DOS end-of-file) ซึ่งอาจส่งสัญญาณการสิ้นสุดของข้อมูลก่อนกำหนด
  • ไบต์ด้านบน 0x7F (ถ้าโปรโตคอลที่ออกแบบมาสำหรับ ASCII)
  • ลำดับไบต์ที่ไม่ถูกต้อง UTF-8

ดังนั้นคุณไม่สามารถส่งข้อมูลไบนารีผ่านโปรโตคอลข้อความได้ คุณถูก จำกัด ไบต์ที่แสดงถึงอักขระ ASCII ที่ไม่ต้องมีการเว้นวรรคควบคุมซึ่งมี 94 เหตุผลที่เลือก 64 ฐานคือว่าเร็วกว่าที่จะทำงานกับพลังของสองและ 64 เป็นตัวที่ใหญ่ที่สุดที่ทำงาน .

แม้ว่าหนึ่งคำถาม ระบบยังคงไม่เห็นด้วยกับเทคนิคการเข้ารหัสทั่วไปเช่น UTF-8 ทั่วไปได้อย่างไร

บนเว็บอย่างน้อยพวกเขาส่วนใหญ่มี ส่วนใหญ่ของเว็บไซต์ที่ใช้ UTF-8

ปัญหาในตะวันตกคือมีซอฟต์แวร์เก่าจำนวนมากที่ ass-u-me-s ที่ 1 ไบต์ = 1 อักขระและไม่สามารถทำงานกับ UTF-8 ได้

ปัญหาในภาคตะวันออกคือสิ่งที่แนบมากับการเข้ารหัสเช่น GB2312 และ Shift_JIS

และความจริงที่ว่า Microsoft ดูเหมือนจะยังไม่ได้รับการเข้ารหัส UTF ที่ผิด หากคุณต้องการใช้ Windows API หรือไลบรารีรันไทม์ Microsoft C คุณ จำกัด UTF-16 หรือการเข้ารหัส "ANSI" ของโลแคล มันทำให้เจ็บปวดที่จะใช้ UTF-8 เพราะคุณต้องแปลงตลอดเวลา


5

ทำไม / เราใช้การเข้ารหัส Base64 ได้อย่างไร

Base64 เป็นหนึ่งในรูปแบบการเข้ารหัสแบบไบนารีต่อข้อความที่มีประสิทธิภาพ 75% มันถูกใช้เพื่อให้ข้อมูลไบนารีทั่วไป (เช่นรูปภาพ) อาจถูกส่งอย่างปลอดภัยผ่านช่องทาง "ไม่สะอาด 8 บิต" แบบดั้งเดิม ในเครือข่ายอีเมลก่อนหน้านี้ (จนถึงต้นปี 1990) ข้อความอีเมลส่วนใหญ่เป็นข้อความธรรมดาในชุดอักขระ US-ASCII 7 บิต มาตรฐานโปรโตคอลต้นกำเนิดจำนวนมากได้รับการออกแบบมาเพื่อทำงานกับลิงก์ "7 บิต" การเชื่อมโยง "ไม่ทำความสะอาด 8 บิต" ประสิทธิภาพของโครงการคืออัตราส่วนระหว่างจำนวนบิตในอินพุตและจำนวนบิตในเอาต์พุตที่เข้ารหัส เลขฐานสิบหก (Base16) เป็นหนึ่งในรูปแบบการเข้ารหัสแบบไบนารีต่อข้อความด้วยประสิทธิภาพ 50%

ขั้นตอนการเข้ารหัส Base64 (แบบง่าย):

  1. ข้อมูลไบนารีถูกจัดเรียงเป็นกลุ่มอย่างต่อเนื่อง 24 บิต (3 ไบต์)
  2. อัน 24 บิตแต่ละอันถูกจัดกลุ่มเป็นสี่ส่วนละ 6 บิต
  3. แต่ละกลุ่ม 6 บิตจะถูกแปลงเป็นค่าอักขระ Base64 ที่สอดคล้องกันเช่นการเข้ารหัส Base64 แปลงสามอ็อกเท็ตเป็นสี่อักขระที่เข้ารหัส อัตราส่วนของเอาต์พุตไบต์ต่อไบต์อินพุตคือ 4: 3 (โอเวอร์เฮด 33%)
  4. ที่น่าสนใจตัวละครเดียวกันจะถูกเข้ารหัสแตกต่างกันไปขึ้นอยู่กับตำแหน่งของพวกเขาภายในกลุ่มสามกลุ่มซึ่งถูกเข้ารหัสเพื่อสร้างตัวละครสี่ตัว
  5. ผู้รับจะต้องย้อนกลับกระบวนการนี้เพื่อกู้คืนข้อความต้นฉบับ

3

"สื่อที่ออกแบบมาเพื่อจัดการกับข้อมูลที่เป็นข้อความ" หมายความว่าอย่างไร

ย้อนกลับไปในวันที่ ASCII ครองโลกที่จัดการกับค่าที่ไม่ใช่ ASCII มันปวดหัว ผู้คนกระโดดผ่านห่วงทุกประเภทเพื่อรับสิ่งเหล่านี้ผ่านสายโดยไม่สูญเสียข้อมูล


3
ที่จริงแล้วในวันนั้น ASCII ไม่ได้ใช้ทุกที่เลย โปรโตคอลจำนวนมากมีโหมดข้อความแยกต่างหากและโหมดไบนารีสำหรับการถ่ายโอนข้อมูล แต่น่าเสียดายที่อีเมลไม่ได้กลับมาในตอนนั้น จำเป็นต้องใช้โหมดข้อความอย่างแม่นยำเนื่องจากไม่มีการเข้ารหัสข้อความเดียวครองโลกไม่ใช่ ASCII; เครือข่ายคอมพิวเตอร์ทุกเครื่องมีการเข้ารหัสที่ชื่นชอบของตัวเองดังนั้นจึงมีเกตเวย์ที่มีหน้าที่ในการแปลงข้อความที่แลกเปลี่ยนเป็นการเข้ารหัสในท้องถิ่นเพื่อให้ บริษัท ญี่ปุ่นสามารถส่งอีเมลไปยังที่ปรึกษาทางธุรกิจอเมริกันโดยไม่ต้อง mojibake การแปลงนี้เห็นได้ชัดว่าไม่พึงประสงค์เมื่อส่งข้อมูลไบนารี
Lie Ryan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.