คำตอบสั้น ๆ
คุณจำเป็นต้องผลักดันbytes-like
วัตถุ ( bytes
, bytearray
ฯลฯ ) กับbase64.b64encode()
วิธีการ นี่คือสองวิธี:
>>> data = base64.b64encode(b'data to be encoded')
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
หรือด้วยตัวแปร:
>>> string = 'data to be encoded'
>>> data = base64.b64encode(string.encode())
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
ทำไม?
ใน Python 3 str
วัตถุไม่ใช่อาร์เรย์ของอักขระแบบ C (ดังนั้นจึงไม่ใช่อาร์เรย์ไบต์) แต่เป็นโครงสร้างข้อมูลที่ไม่มีการเข้ารหัสโดยธรรมชาติ คุณสามารถเข้ารหัสสตริงนั้น (หรือตีความมัน) ได้หลายวิธี (และค่าเริ่มต้นใน Python 3) ที่พบมากที่สุดคือ utf-8 โดยเฉพาะอย่างยิ่งเนื่องจากเข้ากันได้กับ ASCII (แม้ว่าจะเป็นการเข้ารหัสที่ใช้กันอย่างแพร่หลายที่สุด) นั่นคือสิ่งที่เกิดขึ้นเมื่อคุณใช้ a string
และเรียกใช้.encode()
เมธอดดังกล่าว: Python ตีความสตริงเป็น utf-8 (การเข้ารหัสเริ่มต้น) และให้อาร์เรย์ของไบต์ที่สอดคล้องกับคุณ
การเข้ารหัส Base-64 ใน Python 3
แต่เดิมชื่อคำถามที่ถามเกี่ยวกับการเข้ารหัส Base-64 อ่านต่อสำหรับ Base-64 stuff
base64
การเข้ารหัสต้องใช้ไบนารีจำนวน 6 บิตและเข้ารหัสโดยใช้อักขระ AZ, az, 0-9, '+', '/', และ '=' (การเข้ารหัสบางตัวใช้อักขระที่แตกต่างกันแทน '+' และ '/') . นี่คือการเข้ารหัสตัวอักษรที่ยึดตามโครงสร้างทางคณิตศาสตร์ของระบบเลขฐาน 64 หรือฐาน 64 แต่แตกต่างกันมาก Base-64 ในคณิตศาสตร์คือระบบตัวเลขเช่นเลขฐานสองหรือฐานสิบและคุณทำการเปลี่ยนค่าฐานในจำนวนเต็มทั้งหมดหรือ (ถ้าฐานที่คุณแปลงจากนั้นคือกำลัง 2 น้อยกว่า 64) ในหน่วยจากขวาไปเป็น ซ้าย.
ในการbase64
เข้ารหัสการแปลเสร็จจากซ้ายไปขวา ผู้ 64 ตัวแรกที่มีเหตุผลที่เรียกว่าการเข้ารหัสbase64
สัญลักษณ์ 65th '=' ใช้สำหรับแพ็ดดิ้งเนื่องจากการเข้ารหัสดึงชิ้น 6 บิต แต่ข้อมูลมักจะหมายถึงการเข้ารหัสเป็นไบต์ 8 บิตดังนั้นบางครั้งมีเพียงสองหรือ 4 บิตในก้อนสุดท้าย
ตัวอย่าง:
>>> data = b'test'
>>> for byte in data:
... print(format(byte, '08b'), end=" ")
...
01110100 01100101 01110011 01110100
>>>
หากคุณตีความว่าข้อมูลไบนารีนั้นเป็นจำนวนเต็มเดียวนี่คือวิธีที่คุณจะแปลงเป็นฐาน 10 และฐาน 64 ( ตารางสำหรับฐาน 64 ):
base-2: 01 110100 011001 010111 001101 110100 (base-64 grouping shown)
base-10: 1952805748
base-64: B 0 Z X N 0
base64
อย่างไรก็ตามการเข้ารหัสจะจัดกลุ่มข้อมูลนี้ใหม่:
base-2: 011101 000110 010101 110011 011101 00(0000) <- pad w/zeros to make a clean 6-bit chunk
base-10: 29 6 21 51 29 0
base-64: d G V z d A
ดังนั้น 'B0ZXN0' จึงเป็นเวอร์ชั่นฐาน 64 ของไบนารีของเรา อย่างไรก็ตามการbase64
เข้ารหัสจะต้องทำการเข้ารหัสในทิศทางตรงกันข้าม (ดังนั้นข้อมูลดิบจะถูกแปลงเป็น 'dGVzdA') และยังมีกฎที่จะบอกแอปพลิเคชันอื่น ๆ ว่ามีพื้นที่เหลือเท่าใดในตอนท้าย สิ่งนี้ทำได้โดยการเติมจุดสิ้นสุดด้วยสัญลักษณ์ '=' ดังนั้นการbase64
เข้ารหัสของข้อมูลนี้คือ 'dGVzdA ==' พร้อมด้วยสัญลักษณ์สอง '=' เพื่อแสดงว่าบิตสองคู่จะต้องถูกลบออกจากจุดสิ้นสุดเมื่อข้อมูลนี้ได้รับการถอดรหัสเพื่อให้ตรงกับข้อมูลต้นฉบับ
ลองทดสอบสิ่งนี้ดูว่าฉันไม่ซื่อสัตย์หรือไม่:
>>> encoded = base64.b64encode(data)
>>> print(encoded)
b'dGVzdA=='
ทำไมต้องใช้การbase64
เข้ารหัส
สมมติว่าฉันต้องส่งข้อมูลให้ใครบางคนทางอีเมลเช่นข้อมูลนี้:
>>> data = b'\x04\x6d\x73\x67\x08\x08\x08\x20\x20\x20'
>>> print(data.decode())
>>> print(data)
b'\x04msg\x08\x08\x08 '
>>>
มีปัญหาสองข้อที่ฉันปลูก:
- ถ้าฉันพยายามส่งอีเมลนั้นใน Unix อีเมลจะส่งทันทีที่
\x04
อ่านตัวอักษรเพราะนั่นคือ ASCII สำหรับEND-OF-TRANSMISSION
(Ctrl-D) ดังนั้นข้อมูลที่เหลือจะถูกส่งออกไป
- นอกจากนี้ในขณะที่ Python ฉลาดพอที่จะหลบหนีอักขระควบคุมความชั่วร้ายทั้งหมดของฉันเมื่อฉันพิมพ์ข้อมูลโดยตรงเมื่อสตริงนั้นถอดรหัสเป็น ASCII คุณจะเห็นว่า 'msg' ไม่อยู่ที่นั่น นั่นเป็นเพราะฉันใช้
BACKSPACE
ตัวละครสามตัวและSPACE
ตัวละครสามตัวเพื่อลบ 'msg' ดังนั้นแม้ว่าฉันจะไม่มีEOF
ตัวอักษรอยู่ก็ตามผู้ใช้จะไม่สามารถแปลจากข้อความบนหน้าจอเป็นข้อมูลดิบที่แท้จริงได้
นี่เป็นเพียงตัวอย่างเพื่อแสดงให้คุณเห็นว่าการส่งข้อมูลดิบนั้นยากเพียงใด การเข้ารหัสข้อมูลในรูปแบบ base64 ให้ข้อมูลที่แน่นอนเหมือนกัน แต่ในรูปแบบที่ทำให้แน่ใจว่าปลอดภัยสำหรับการส่งผ่านสื่ออิเล็กทรอนิกส์เช่นอีเมล