أدوات المطور · التشفير ووحدة فك التشفير Base64
ما الذي يمثله atob وbtoa، ولماذا يفهمان اللغة اللاتينية فقط-1
· خلفية
base64 جافا سكريبت يونيكود
تاريخ atob وbtoa من Netscape والأسماء تعني "ASCII إلى ثنائي" و"ثنائي إلى ASCII". يغطي هذا المنشور من أين أتوا، وكيف تحددهم معايير WHATWG، ولماذا لم يتعلموا Unicode مطلقًا.
اسم دالة يبدو وكأنه خطأ مطبعي - الارتباك الذي تسببه الأسماء والإجابة المكونة من سطر واحد
atob وbtoa هما JavaScript من الوظائف المضمنة التي تم تقديمها في Netscape في التسعينيات. الأسماء عبارة عن اختصارات: btoa يرمز إلى ثنائي إلى ASCII ويرمز atob إلى ASCII إلى ثنائي. تعكس الأسماء عمرها وتصميمها: فقد تم إنشاؤها عندما كان الثنائي يعني سلسلة من قيم البايت (0-255) بدلاً من Uint8Array أو Buffer الأكثر حداثة. غالبًا ما يكون أسلوب التذكر الذي يُعطى للأسماء أقل أهمية من العقد القابل للملاحظة: تقوم إحدى الوظائف بتعيين سلسلة ثنائية إلى Base64 والأخرى تعكسها. لا يوثق هذا المستودع قرار التسمية الأصلي، لذا تتجنب المقالة تقديم التراث الشعبي كمصادر لتاريخ المتصفح.
تتوقع الوظائف سلسلة ثنائية: يجب أن تكون وحدة التعليمات البرمجية لكل حرف في النطاق 0-255، مما يمثل بايت واحد. إذا قمت بتمرير حرف بوحدة رمز أعلى من 255 (مثل رمز تعبيري أو حرف معلم من خارج اللغة اللاتينية-1)، فستطرح الدالة خطأ InvalidCharacterError أو تنتج مخرجات غير صحيحة بصمت. يقوم btoa (ثنائي إلى ASCII) بتشفير سلسلة ثنائية إلى base64.
ما تقترحه الأسماء وما يثبته عقد سلسلة البايت فعليًا
يجب أن يكون الإدخال عبارة عن سلسلة حيث يكون كل حرف عبارة عن بايت (وحدة التعليمات البرمجية 0-255). يقوم btoa(hello) بتشفير البايتات ASCII كـ base64 وإرجاع aGVsbG8=. يبدو أن btoa الذي يحتوي على الحرف e-acute يعمل لأن الحرف اللاتيني - 1 e-acute (U+00E9) المكون مسبقًا يحتوي على وحدة كود 233، والتي تقع ضمن 0-255. ومع ذلك، يقوم btoa بتشفيرها كبايت واحد، 0xE9، وليس UTF-8 بايت 0xC3 0xA9 التي يجب أن ينتجها e-acute. قبل أن تصبح المصفوفات المكتوبة حاوية البايت العادية، كانت واجهات برمجة التطبيقات JavaScript تستخدم السلاسل التي تمثل وحدات التعليمات البرمجية الخاصة بها وحدات البايت. يظل هذا النموذج مرئيًا لأن btoa يرفض وحدات التعليمات البرمجية الأعلى من 255. لم يتم تحديد التسلسل الزمني الدقيق للمنتج بواسطة هذه الملفات؛ يتم تحديد حدود الفشل عن طريق الاختبارات القابلة للتنفيذ.
وهذا الفساد الصامت أخطر من الخطأ: فالنتيجة تبدو جيدة ولكنها خاطئة. يقوم atob (ASCII إلى ثنائي) بفك تشفير base64 مرة أخرى إلى سلسلة ثنائية. atob(aGVsbG8=) يُرجع مرحبًا. الإخراج عبارة عن سلسلة ثنائية حيث وحدة التعليمات البرمجية لكل حرف هي 0-255، مما يمثل بايت واحد. إذا كنت تريد تحويل هذا إلى نص Unicode مناسب، فستحتاج إلى تفسير البايتات على أنها UTF-8 وفك تشفيرها باستخدام TextDecoder.
نموذج السلسلة الثنائية القديم — سلوك يمكن ملاحظته دون مطالبة بسجل المتصفح لم يتم التحقق منها
بالنسبة إلى ASCII، هذه الخطوة الإضافية غير ضرورية (ASCII هي مجموعة فرعية من UTF-8)، ولكن بالنسبة لأي بايت غير ASCII، فهي ضرورية. أتوب لا يفعل هذا التفسير. تقوم بإرجاع البايتات الأولية كسلسلة ثنائية.
تحدد معايير WHATWG (المعايير المعيشية لواجهات برمجة تطبيقات الويب) atob وbtoa في مواصفات HTML. يتضمن التعريف خوارزمية فك تشفير Base64 المتسامحة لـ atob: فهي تتخطى المسافات البيضاء وتقبل الحشو المفقود، مما يجعل Base64 في العالم الحقيقي (بما في ذلك MIME-base64 المغلف مع فواصل الأسطر) قابلاً لفك التشفير. ToolAcre يقوم بتطبيع المسافة البيضاء، URL- علامات الترقيم الآمنة والحشو المفقود قبل استدعاء وحدة فك ترميز المتصفح. ثم يقوم بعد ذلك بنسخ وحدات التعليمات البرمجية التي تم إرجاعها إلى Uint8Array ويطبق وحدة فك ترميز UTF-8 القاتلة. يفصل هذا المزيج بين بناء جملة Base64 المتسامح والتفسير الصارم للنص.
السلوك الحالي في هذا التنفيذ — التسامح مع تطبيع الحروف الأبجدية وفك تشفير النص الصارم UTF-8
لم يتغير توقيع الوظيفة، ولكن تعريف المعايير هو السلطة لما تفعله الوظيفة. لماذا يقبل atob وbtoa فقط اللغة اللاتينية-1؟ لأنه عندما تم تصميمها في التسعينيات، لم يكن لدى JavaScript طريقة لتمثيل البايتات مباشرة (لا يوجد Uint8Array أو ArrayBuffer). كانت الطريقة الوحيدة لتمرير البايتات إلى دالة هي استخدام سلسلة حيث يمثل كل حرف بايتًا واحدًا.
وهذا ما يسمى سلسلة ثنائية وهو مربك بالمعايير الحديثة. السلسلة JavaScript هي نص Unicode، وليست سلسلة من البايتات. يدمج التصميم بين الاثنين: السلسلة التي تكون فيها كل وحدة تعليمات برمجية 0-255 هي سلسلة ثنائية. تعكس التسمية العصر: ASCII في btoa تعني حرفيًا سبع بتات للنص ASCII، لكن التنفيذ يقبل أي بايت (0-255). إن إضافة وضع Unicode مباشرةً إلى btoa سيؤدي إلى تغيير عقد سلسلة البايت طويل الأمد والتوافق مع المخاطر. بدلاً من ذلك، يقوم المصدر الذي تمت مراجعته بتكوين TextEncoder قبل التشفير. يمكن لهذه المقالة التحقق من هذا التكوين؛ فهو يحذف الادعاءات المتعلقة بدوافع لجنة المعايير غير المسجلة في المستودع.
مثال عملي: تتبع forgiving-base64 على سلسلة تحتوي على مسافات وحشوة مفقودة - ما يقبله atob ويرفضه برنامج فك التشفير الصارم
تتجنب البدائل الحديثة نموذج السلسلة الثنائية. يوفر التشفير API لـ TextEncoder إمكانية تحويل النص إلى UTF-8 بايت، وTextDecoder لتحويل UTF-8 بايت إلى نص مرة أخرى.
تم الآن تحديد تشفير وفك تشفير Base64 في مواصفات HTML لكل من السلاسل (atob وbtoa) والمصفوفات المكتوبة. تستخدم أداة التشفير وفك التشفير Base64 TextEncoder وTextDecoder حول atob وbtoa، بحيث يمكنك تشفير نص Unicode وفك تشفيره بأمان دون القيود اللاتينية 1. تنجح القيمة المتباعدة أو غير المبطنة لأن التسوية تزيل المسافة البيضاء وتستعيد طول الكتلة المطلوب. يتم رفض القيمة التي يترك طولها المنظف الباقي واحدًا قبل atob. يوضح هذا التمييز ما يعنيه "التسامح" هنا: يتم قبول التنسيق القابل للاسترداد، ولا يتم قبول الإدخال المستحيل من الناحية الهيكلية.
تعمل المعايير الأحدث على Base64 للمصفوفات المكتوبة - موصوفة نوعيًا، مع ملاحظة للتحقق من دعم المتصفح الحالي
يتطلب التعامل مع Unicode باستخدام btoa تشفير النص إلى UTF-8 بايت أولاً. كان الحل القديم هو btoa(unescape(encodeURIComponent(text)))، وهو أمر مربك ولكنه يعمل: يقوم encodeURIComponent بتشفير النسبة المئوية UTF-8 بايت، ويحول unescape ثلاثة توائم مرة أخرى إلى أحرف، ويقوم btoa بتشفير السلسلة الثنائية الناتجة. يعمل هذا ولكنه يعتمد على الوظائف المهملة ويصعب قراءته. يجب أن تستخدم التعليمات البرمجية الحديثة TextEncoder(text).map(byte => String.fromCharCode(byte)) متبوعة بـ btoa، أو الأفضل من ذلك، قم بالتحويل مباشرة إلى Uint8Array واستخدم التشفير API.
أتوب لا يعطيك نصًا تلقائيًا؛ يعطيك ثنائي. atob(Y2Fmw6kg8J+YgA==) يُرجع سلسلة ثنائية تحتوي على بايتات النص المشفر UTF-8 مع لهجة caf والرموز التعبيرية. لاستعادة النص، قم بتحويل السلسلة الثنائية إلى Uint8Array وتمريرها إلى TextDecoder(utf-8). تقوم أداة التشفير وفك التشفير Base64 بذلك تلقائيًا: تقوم بلصق النص، وتقوم بترميزه إلى UTF-8 بايت، ثم إلى base64. تتطور واجهات برمجة التطبيقات Base64 ذات المصفوفة المكتوبة عبر المتصفحات، لكن هذا المصدر لا يستخدمها. اعتمادًا على أحدهما، يتطلب الأمر فحص التوافق الحالي والخطة الاحتياطية. يظل التحويل الصريح لمصفوفة البايت الخاص بـ ToolAcre قابلاً للفحص ومغطى بمجموعة الاختبار الحالية الخاصة به.
تتطور بدائل المصفوفات المكتوبة — تحقق من دعم المتصفح الحالي قبل الاعتماد عليها
تقوم بلصق base64، ويتم فك التشفير إلى UTF-8 بايت، ثم إلى نص. خطوة السلسلة الثنائية المتوسطة مخفية لأنها تفاصيل تنفيذ في التسعينيات API. يعد فهم atob وbtoa مفيدًا لتصحيح أخطاء التعليمات البرمجية القديمة أو العمل مع واجهات برمجة التطبيقات القديمة التي توفر لك سلاسل ثنائية. يجب أن تتجنب معظم التعليمات البرمجية الجديدة نموذج السلسلة الثنائية تمامًا.
إذا كنت بحاجة إلى تشفير Base64 أو فك تشفيره، فإن أداة التشفير وفك التشفير Base64 تتعامل مع Unicode بشكل صحيح. إذا كنت تقوم بإنشاء API، فاقبل Uint8Array أو عرض مصفوفة مكتوبة، أو قم بتوثيق ما إذا كان base64 الخاص بك هو UTF-8 أو لاتيني-1. عند مراجعة التعليمات البرمجية التي تستخدم btoa مع نص غير ASCII بدون TextEncoder، يكون هناك خطأ: يقوم الإخراج بتشفير البايتات الخاطئة. تحدد أوقات تشغيل Node Buffer وغير المتصفح واجهات برمجة التطبيقات وقواعد القبول المختلفة. لقد تم استبعادهم عمدا. تتعلق المطالبات الواردة في هذه المقالة ببدائل المتصفح والمغلف المطبق في apps/dev, وليس كل وظيفة تسمى atob أو btoa في كل بيئة.
الوجبات الجاهزة: وظيفتان من التسعينيات بعقد سلسلة بايت - كيف يقوم برنامج التشفير ووحدة فك التشفير Base64 بالتنقل حولهما بحيث يتنقل UTF-8 حولهما بحيث يتم استخدام اللكنات وCJK والرموز التعبيرية ذهابًا وإيابًا
تعد الأسماء atob وbtoa من القطع الأثرية الغريبة للحوسبة في التسعينيات. ستكون التسمية الحديثة هي base64Encode وbase64Decode، وستقبل واجهات برمجة التطبيقات Uint8Array أو السلاسل ذات إعلانات التشفير الصريحة. لكن atob وbtoa يستمران في المتصفحات من أجل التوافق مع الإصدارات السابقة. إن فهم ما يقصدونه (وما لا يمكنهم فعله) يساعدك على تجنب الفساد الصامت عند تشفير نص Unicode.
تعمل أداة التشفير وفك التشفير Base64 على سد الفجوة: فهي تتحدث اللغتين UTF-8 وbase64 التي تحتاجها التعليمات البرمجية الحديثة. النمط القوي تركيبي: قم بتشفير النص إلى UTF-8 بايت، وتحويل البايتات إلى عقد سلسلة ثنائية، ثم استدعاء btoa؛ عكس تلك الخطوات حول أتوب. جرّب استخدام اللكنة وCJK من الأحرف والرموز التعبيرية، ثم اطلب أن يتطابق النص الذي تم فك ترميزه مع كل نقطة رمز أصلية.