العربية

أدوات المطور · التشفير ووحدة فك التشفير Base64

فك تشفير Base64 إلى UTF-8 بدون mojibake: atob plus TextDecoder

· كيف يعمل

base64 ترميز يونيكود

خط الأنابيب من Base64 إلى UTF-8 يُظهر فشل mojibake
الرسم التوضيحي المتجه الأصلي ToolAcre

تُرجع الدالة atob()‎ وحدات البايت المتخفية على شكل أحرف، ولهذا السبب يبدو النص المُعلم معطلاً بعد فك التشفير. يعرض هذا المنشور المسار الصحيح من Base64 إلى البايتات إلى نص UTF-8، وكيفية التعرف على نمط الفشل.

استجابة API التي يتم فك ترميزها إلى "Café" - أحد أعراض mojibake الملموسة والبايتين خلف الحرفين الخاطئين

سلسلة Base64 Q2Fmw6k= يتم فك التشفير إلى وحدات البايت (67، 97، 102، 195، 169)، وهي UTF-8 text Café. الصق في وحدة فك الترميز الساذجة (فقط تحويل atob والسلسلة) ويكون الإخراج غالبًا Café، ويتم استبدال كل لهجة بحرفين خاطئين. يحدث هذا mojibake لأن atob يُرجع سلسلة من البايتات (وحدات التعليمات البرمجية 0–255)، وليس UTF-8 نصًا. يتم ترميز البايتات 195 و169 بعلامة é في UTF-8.

إن التعامل معها كما لو كانت أحرف لاتينية - 1 منفصلة يعطي نمط mojibake. خط الأنابيب الصحيح هو atob (البايت كسلسلة)، ثم TextDecoder (تفسير البايت كـ UTF-8)، ويعود النص الأصلي. لم يتم كسر الدالة أتوب؛ وهي مصممة للبيانات الثنائية. يأتي اسمها من ASCII-to-binary، والسلسلة الثنائية التي تنتجها هي تسلسل من وحدات التعليمات البرمجية 0–255، يمثل كل منها بايت واحد.

ما تُرجعه atob()‎ فعليًا — سلسلة من وحدات التعليمات البرمجية 0–255 التي تمثل وحدات البايت، وليس النص الذي تم فك تشفيره

إذا قمت بإطعامه Q2Fmw6k= (base64 القياسي)، فإنه يخرج سلسلة حيث يكون كل حرف بايت واحد: وحدة التعليمات البرمجية 67، ثم 97، ثم 102، ثم 195، ثم 169. إذا قمت بعرض هذه السلسلة مباشرة أو ترجمتها كنص لاتيني-1، فسترى إخراجًا مشوهًا. الخطوة المفقودة هي تحويل وحدات التعليمات البرمجية إلى صفيف بايت ثم فك تشفير الصفيف كـ UTF-8.

تستعيد حلقة charCodeAt قيم البايت: لكل حرف في مخرجات atob، اتصل بـ charCodeAt للحصول على وحدة التعليمات البرمجية (رقم 0–255)، وقم بتخزينها في Uint8Array. بمجرد وجود مجموعة من البايتات، قم بالتمرير إلى TextDecoder باستخدام مجموعة الأحرف utf-8. يقرأ TextDecoder تسلسل البايت ويفسره كنص UTF-8، ويجمع تسلسلات البايت مثل (195، 169) في أحرف مفردة مثل é. تصبح البايتات (67، 97، ​​102، 195، 169) سلسلة من أربعة أحرف Café. الحلقة مملة بشكل متعمد: اقرأ كل وحدة تعليمات برمجية تم إرجاعها باستخدام charCodeAt وقم بتعيينها إلى موضع Uint8Array المطابق. لا يحدث هناك قرار محدد للشخصية. يصل التفسير الوحيد عندما يتلقى TextDecoder تلك المصفوفة ويطبق UTF-8 مع معالجة الأخطاء الفادحة.

تحويل هذه السلسلة إلى Uint8Array - حلقة charCodeAt ولماذا هي نسخة بايت وليست تحويل

هذه العملية المكونة من خطوتين — استرداد البايت، ثم التفسير UTF-8 — هي ما يفعله برنامج التشفير ووحدة فك التشفير Base64 داخليًا. يعد نمط mojibake علامة واضحة على هذا الخطأ. إذا ظهر Café كـ Café، فإنك تشاهد الترجمة اللاتينية 1 لـ UTF-8 بايت. UTF-8 بايت لـ é هي 0xC3 0xA9 (العلامة العشرية 195، 169). في اللاتينية-1، وحدة الكود 195 هي Á، ووحدة الكود 169 هي ©.

عند قراءة تسلسل البايت UTF-8 كما لو كان كل بايت عبارة عن حرف لاتيني-1 منفصل، فإن كل تسلسل UTF-8 متعدد البايت ينتج أحرف بديلة خاطئة. إذا ظهر Café كـ Caf متبوعًا بالحرف البديل، أو كـ Caf؟ أو Caf plus U+FFFD، فإنك ترى فشلًا مختلفًا: لم يتعرف برنامج فك التشفير على تسلسل البايت باعتباره صالحًا UTF-8. مثال ملموس: Base64 SGVsbG8sIOS4lueVjCEg8J-Zgg== يقوم بفك التشفير على النحو التالي.

TextDecoder وقرار مجموعة الأحرف - فك التشفير كـ UTF-8، ولماذا تعتبر مجموعة الأحرف حقيقة منفصلة يجب أن تعرفها

يُنتج atob سلسلة ثنائية بالبايتات (72، 101، 108، 108، 111، 44، 32، 228، 184، 180، 149، 140، 33، 32، 240، 159، 152، 130). البايتات الستة الأولى هي ASCII: تصبح مرحبًا. البايتات 228، 184، 180 عبارة عن تسلسل ثلاثي البايت UTF-8 يمثل CJK حرفًا. البايتات 149، 140 هي جزء من التسلسل التالي. يتضمن التسلسل الكامل تسلسلًا للرموز التعبيرية رباعي البايت (240، 159، 152، 130) للشخصية النهائية.

عند معالجتها بشكل صحيح من خلال TextDecoder، يتم دمج كافة البايتات لإنتاج نص أصلي مختلط. UTF-8 تسلسلات البايت لها أطوال يمكن التنبؤ بها: البايت الذي يبدأ بـ 0xxxxxxxxx هو بايت واحد ASCII؛ البايت الذي يبدأ بـ 110xxxxxx يتوقع البايت التالي الذي يبدأ بـ 10xxxxxx (إجمالي بايتين)؛ البايت الذي يبدأ بـ 1110xxxx يتوقع وحدتي بايت متتاليتين (إجمالي ثلاث بايت)؛ البايت الذي يبدأ بـ 11110xxx يتوقع ثلاث بايتات متتابعة (إجمالي أربع بايتات). بالنسبة لنموذج CJK المختلط والرموز التعبيرية، يكون عرض البايت تشخيصيًا بشكل خاص لأن حدس ASCII لم يعد يساعد. تنتمي عدة بايتات إلى كل رمز مرئي، ويؤدي حذف بايت واحد إلى تحويل التسلسل المتبقي إلى UTF-8 غير صالح. يؤدي فك التشفير الصارم إلى تحويل هذا التحول إلى فشل مسمى بدلاً من الضرر الذي يبدو معقولاً.

مثال عملي: فك تشفير سلسلة Base64 تحتوي على CJK ورمز تعبيري - بايت ونقاط رمز والسلسلة النهائية مقارنة بالأصل

التسلسل الذي يبدأ بـ 1111110x غير صالح في UTF-8 (محجوز للمستقبل، غير مستخدم). يجب ألا تظهر البايت الذي يبدأ بـ 10xxxxxx أبدًا كبايت أولي؛ إنه استمرار. إذا كان تدفق البايت ينتهك القواعد، فهو غير صالح UTF-8. يقوم TextDecoder مع مجموعة الأحرف utf-8 بتفسير المصفوفة وفقًا لهذه القواعد وينجح في الحصول على تسلسلات صالحة. بالنسبة إلى غير صالح، فإنه يُبلغ عن خطأ.

يستخدم برنامج التشفير ووحدة فك التشفير Base64 برنامج TextDecoder مع علامة الوضع الصارم الحقيقية. وهذا يعني أن UTF-8 غير صالح يؤدي إلى حدوث خطأ بدلاً من إدراج أحرف بديلة بصمت (U+FFFD). إذا تم فك ترميز سلسلة Base64 إلى وحدات بايت غير صالحة UTF-8، فسيتم طرح الوضع الصارم بدلاً من الاستمرار في النص المشوه. هذا هو اختيار التصميم: الحمولات الثنائية (الصور والمفاتيح والبيانات المضغوطة) ليست نصًا ولا يجب فك تشفيرها كنص.

التعرف على النمط: Á، †و †— كيفية التمييز بين مشكلة Base64 ومشكلة مجموعة الأحرف

إذا حاولت فك تشفير JPEG كـ Base64، فلن يمثل تدفق البايت UTF-8 صالحًا، وسيرفضه فك التشفير الصارم. توفر الأداة عرضًا سداسيًا عشريًا لمثل هذه الحمولات: يمكنك رؤية وحدات البايت الأولية دون التظاهر بأنها نص. يتضمن التعرف على أخطاء فك التشفير UTF-8 النظر إلى البايتات في السياق. هل هم عدد فردي حيث يتوقع تسلسل متعدد البايت؟

هل البايت الأول من التسلسل المحتمل غير صالح (يبدأ بـ 10xxxxxx)؟ هل البايتات المستمرة مفقودة؟ يوفر زر إخراج البايت أنظف شوكة في التحقيق. إذا ظهر الرقم السداسي عشر ولكن فشل فك تشفير النص، فهذا يعني نجاح تحليل Base64 وتكون الحمولة إما ثنائية أو تالفة أو مشفرة بمجموعة أحرف مختلفة. لا يمكن أن يؤدي تغيير علامات الترقيم Base64 إلى إصلاح عدم تطابق مجموعة الأحرف بعد ظهور البايتات الصحيحة بالفعل.

ما لا يغطيه هذا — UTF-16 الحمولات، والمخرجات الثنائية مثل الصور ومعالجة البايت غير الصالح

الأنماط متسقة. البايت الواحد 0xFF غير صالح أبدًا في UTF-8؛ لا يمكن أن يكون ASCII بايت (فقط 0–127 هي ASCII) ولا يمكن أن يكون بايت أولي (البايتات الأولية هي 0xC0–0xFD، و0xFF محجوزة). لا يمكن للبدائل الوحيدة (UTF-16 المفهوم) أن تظهر في UTF-8؛ إذا رأيت تسلسل البايت 0xED 0xA0 0x80 (الذي يشفر البديل U+D800 بأسلوب UTF-8)، فهو غير صالح UTF-8.

أحد الحلول التاريخية هو btoa(unescape(encodeURIComponent(text))). يقوم encodeURIComponent بتحويل المقهى إلى %C3%A9 (تشفير النسبة المئوية UTF-8 بايت)، وعمليات إعادة حزم unescape كوحدات تعليمات برمجية، ويقوم btoa بتشفير وحدات التعليمات البرمجية. يعمل هذا مع معظم النصوص ولكنه هش عند استخدام البدائل الوحيدة ويصعب قراءته. أصبح خط الأنابيب الحديث — TextEncoder إلى بايت، ثم base64 — أكثر وضوحًا وقياسيًا. تم دمج TextEncoder في جميع المتصفحات الحديثة وNode.js، مما يجعله الاختيار الصحيح. UTF-16، تتطلب الترميزات القديمة أحادية البايت ومحتويات الملفات العشوائية وحدة فك ترميز محددة لتلك البايتات أو عارضًا ثنائيًا. ToolAcre لا يخمن بينهم عمدا. يمكن أن يؤدي التخمين إلى تحويل تسلسل غير صالح إلى نص مضلل، بينما يحافظ التفريغ السداسي على كل بايت لتفسير مستنير لاحقًا.

الوجبات الجاهزة: يمنحك Base64 وحدات البايت، ويمنحك UTF-8 نصًا - كيف يقوم برنامج التشفير ووحدة فك التشفير Base64 بكلتا الخطوتين بحيث يتطابق النص الذي تم فك تشفيره مع الإدخال تمامًا

عندما يكون لديك سلسلة Base64 وتريد نصًا UTF-8، فإن الخطوات الكاملة هي: فك تشفير Base64 إلى بايت (باستخدام مكتبة atob أو مكتبة Base64 لفك التشفير)، وإنشاء Uint8Array من البايتات، وتمرير الصفيف إلى TextDecoder باستخدام مجموعة الأحرف utf-8، وقراءة النتيجة كسلسلة.

إذا كان الإدخال عبارة عن بيانات ثنائية وليس نصًا، فتخطى TextDecoder وافحص البايتات مباشرةً. يوفر برنامج التشفير ووحدة فك التشفير Base64 عرض بايت سداسي عشري، مع الحفاظ على القيم التي قد يرفضها فك التشفير الصارم UTF-8. هذه الشوكة تشخيصية: البايتات الناجحة بالإضافة إلى النص الفاشل تعني أن تحليل Base64 يعمل، في حين أن الحمولة ثنائية أو تالفة أو مشفرة باستخدام مجموعة أحرف لا تستطيع هذه الأداة تخمينها.