التخطي إلى المحتوى
Toova
جميع الأدوات

فهم ترميز Base64 — الدليل الشامل للمطور

Toova

يظهر ترميز Base64 في كل مكان تقريبًا في تطوير الويب — رموز JWT، وعناوين URI للبيانات، ومرفقات البريد الإلكتروني، وحمولات API، والتوقيعات التشفيرية، وملفات الإعدادات. على الرغم من انتشاره الواسع، كثيرًا ما يُساء فهمه: أحيانًا يخلط المطورون بينه وبين التشفير، أو يستخدمونه في سياقات تجعل الأمور أسوأ. يشرح هذا الدليل بالتفصيل كيف يعمل Base64، ومتى ينبغي استخدامه، ومتى يجب تجنبه، وكيفية استخدامه بشكل صحيح في JavaScript.

ما هو ترميز Base64 (وما الذي ليس هو)

Base64 هو نظام ترميز ثنائي إلى نصي. مهمته الوحيدة هي تحويل البيانات الثنائية العشوائية إلى سلسلة من أحرف ASCII القابلة للطباعة. لا يضغط البيانات، ولا يشفرها، ولا يتحقق منها. إنه مجرد تحويل في التمثيل — يأخذ بايتات قد تحتوي على بايتات صفرية أو أحرف تحكم أو قيمًا تكسر البروتوكولات النصية، ويحوّلها إلى مجموعة أحرف آمنة.

جاءت التسمية من 64 حرفًا تُشكّل أبجدية الترميز: A–Z (26 حرفًا)، وa–z (26 حرفًا)، و0–9 (10 أحرف)، إضافةً إلى + و/ (حرفان). يُستخدم الحرف = للحشو. إذ تحتمل كل خانة 64 قيمة و2^6 = 64، فإن كل حرف Base64 يُشفّر 6 بتات بالضبط من البيانات الأصلية.

كيف يعمل Base64 — مثال خطوة بخطوة بـ "Hello"

أفضل طريقة لفهم Base64 هي تتبع مثال ملموس. لنرمّز السلسلة Hello.

الخطوة 1: التحويل إلى بايتات

كل حرف في Hello يُعيَّن لرمزه في ASCII، ثم يُعبَّر عنه بنظام ثنائي (8 بتات لكل بايت):

H  e  l  l  o
72 65 6C 6C 6F   (ASCII / hex)
01001000 01100101 01101100 01101100 01101111   (binary)

الخطوة 2: التجميع في مقاطع 6 بتات

نسلسل جميع البتات: 0100100001100101011011000110110001101111 (40 بت). يعالج Base64 3 بايتات (24 بت) في المرة الواحدة ويعيّنها لـ 4 أحرف Base64 (4 × 6 = 24 بت). نجمّع 40 بت في مجموعات من 6 بتات، مع حشو المجموعة الأخيرة بأصفار لإكمالها:

010010 000110 010101 101100 011011 000110 1111
18     6      21     44     27     6      (last group padded to 6 bits: 111100 = 60)

الخطوة 3: التعيين على أبجدية Base64

كل قيمة من 6 بتات تُعيَّن لحرف في أبجدية Base64 (A=0، B=1، ... Z=25، a=26، ... z=51، 0=52، ... 9=61، +=62، /=63). بما أن 5 بايتات ليست من مضاعفات 3، يُضاف حرف حشو واحد =:

Index: 18  6   21  44  27  6   60
Char:  S   G   V   s   b   G   8
Result: SGVsbG8=   (= is padding)

النتيجة

"Hello" → "SGVsbG8="

يمكنك التحقق من ذلك فورًا باستخدام مشفر/مفكك Base64 في Toova — الصق Hello، اضغط Encode، وستحصل على SGVsbG8=. اضغط Decode لعكس العملية.

التكلفة الإضافية بنسبة 33٪ في الحجم

يزيد ترميز Base64 دائمًا حجم البيانات بنسبة 33٪ تقريبًا. الحساب بسيط: 3 بايتات من المدخلات (24 بت) تنتج 4 أحرف Base64 (24 بت مُشفَّرة في 4 مجموعات من 6 بتات). هذه نسبة 4/3، أو 33.3٪ تكلفة إضافية. مع إضافة أحرف الحشو، تتراوح التكلفة الفعلية بين 33٪ و36٪ حسب طول المدخلات.

هذا مهم بشكل ملحوظ للأداء. صورة بحجم 1 ميغابايت مضمّنة كعنوان URI للبيانات بصيغة Base64 في HTML تصبح 1.37 ميغابايت تقريبًا. واجهة برمجية ترمّز جميع الحمولات الثنائية بـ Base64 ترسل 33٪ بيانات إضافية غير ضرورية. للقيم الصغيرة مثل الرموز القصيرة أو مجاميع التحقق، التكلفة الإضافية ضئيلة. للملفات الكبيرة، هي تكلفة حقيقية.

المتغير الآمن للروابط

يستخدم Base64 القياسي + و/ كآخر حرفين في الأبجدية. كلاهما إشكالي في عناوين URL:

  • يُفسَّر + كحرف مسافة في سلاسل الاستعلام
  • يُعدّ / فاصلًا للمسار في عناوين URL

يستبدل Base64 الآمن للروابط (المعروف بـ Base64url، المعرَّف في القسم 5 من RFC 4648) + بـ - و/ بـ _. عادةً ما يُحذف الحشو (=) في السياقات الآمنة للروابط لأن بعض محللات عناوين URL قد تسيء تفسيره.

تستخدم رموز JWT البنية Base64url بدون حشو. عند فك ترميز ترويسة JWT أو حمولتها يدويًا، يجب معالجة استبدال الأحرف والحشو المفقود معًا. إليك كيفية القيام بذلك في JavaScript:

// URL-safe Base64 (replace + with - and / with _)
function toBase64Url(base64) {
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

function fromBase64Url(base64url) {
  const padded = base64url.padEnd(
    base64url.length + (4 - base64url.length % 4) % 4,
    '='
  );
  return atob(padded.replace(/-/g, '+').replace(/_/g, '/'));
}

يدعم مشفر/مفكك Base64 في Toova المتغيرَين القياسي والآمن للروابط بمفتاح تبديل واحد.

Base64 في JavaScript

المتصفح: btoa() وatob()

توفر المتصفحات دالتين مدمجتين: btoa() (من ثنائي إلى ASCII، أي الترميز) وatob() (من ASCII إلى ثنائي، أي فك الترميز). رغم تسميتهما المربكة، فقد توفرتا في المتصفحات منذ أكثر من عقد.

// Browser — atob / btoa (strings only, ASCII-safe)
const encoded = btoa("Hello");
console.log(encoded); // "SGVsbG8="

const decoded = atob("SGVsbG8=");
console.log(decoded); // "Hello"

قيد مهم: تقبل btoa() فقط السلاسل التي تحتوي على أحرف في النطاق Latin-1 (نقاط الكود 0–255). إذا أدخلت سلسلة تحتوي على أحرف Unicode كالرموز التعبيرية أو أحرف CJK، ستُطلق DOMException. لترميز البيانات الثنائية العشوائية، حوّلها إلى Uint8Array أولًا:

// Browser — encoding arbitrary binary (Uint8Array)
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
const encoded = btoa(String.fromCharCode(...bytes));
console.log(encoded); // "SGVsbG8="

لترميز سلاسل عشوائية قد تحتوي على أحرف Unicode، الأسلوب الحديث الموصى به هو استخدام TextEncoder للحصول على Uint8Array أولًا، ثم الترميز كما هو موضح أعلاه.

Node.js: Buffer

يوفر Node.js فئة Buffer التي تتعامل مع البيانات الثنائية بشكل صحيح وتدعم ترميزات متعددة بما فيها Base64 وBase64url:

// Node.js — Buffer (handles binary safely)
const encoded = Buffer.from('Hello').toString('base64');
console.log(encoded); // "SGVsbG8="

const decoded = Buffer.from('SGVsbG8=', 'base64').toString('utf8');
console.log(decoded); // "Hello"

// URL-safe variant in Node.js
const urlSafe = Buffer.from('Hello').toString('base64url');
console.log(urlSafe); // "SGVsbG8" (no padding)

يتعامل خيار الترميز base64url (المتاح منذ Node.js 16) مع استبدال الأحرف وحذف الحشو تلقائيًا، مما يجعله أسهل بكثير من إجراء التحويل يدويًا.

لبيئات المتصفح التي تحتاج إلى التعامل مع ملفات ثنائية كبيرة، تُشفّر الطريقة FileReader.readAsDataURL الملف كعنوان URI للبيانات بصيغة Base64 دون تحميل كل شيء في الذاكرة دفعةً واحدة.

متى تستخدم Base64

تضمين البيانات الثنائية في البروتوكولات النصية فقط

كان الاستخدام الأصلي لـ Base64 ترميز مرفقات البريد الإلكتروني الثنائية في SMTP، وهو بروتوكول يدعم فقط نص ASCII من 7 بتات. ينطبق نفس المبدأ في أي مكان تحتاج فيه إلى تضمين بيانات ثنائية في تنسيق لا يدعم البايتات الخام: حمولات JSON في واجهات برمجية، ومستندات XML، وسمات HTML، وقيم CSS، وترويسات HTTP.

عناوين URI للبيانات للأصول الصغيرة

تسمح CSS وHTML بتضمين الصور والخطوط ورسوم SVG كعناوين URI للبيانات بصيغة Base64. هذا يلغي رحلة HTTP إضافية للأصول الصغيرة مثل الأيقونات ويلغي ظهور محتوى غير منسَّق للصور الحيوية فوق الطية.

<!-- Inline SVG icon as Base64 data URI -->
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0c..." alt="icon" />

<!-- Inline CSS background -->
.icon {
  background-image: url("data:image/png;base64,iVBORw0KGgo...");
}

المقايضة: لا يمكن تخزين عناوين URI للبيانات بصيغة Base64 مؤقتًا بشكل منفصل عن ملف HTML/CSS الذي يحتويها. إذا لم تتغير الصورة أبدًا لكن HTML المحيط به يتغير، فسيُعيد المتصفح تنزيل بيانات الصورة في كل تحديث للصفحة. استخدم عناوين URI للبيانات فقط للأصول الصغيرة (يُفضَّل أقل من 4 كيلوبايت) حيث تفوق فائدة تجنب رحلة إضافية عقوبة التخزين المؤقت.

ترميز البيانات الثنائية لـ JSON أو معاملات URL

JSON هو تنسيق نصي — لا يمكنه تمثيل البايتات الثنائية الخام مباشرةً. عندما تحتاج واجهة برمجية إلى نقل بيانات ثنائية (صور مصغّرة، توقيعات تشفيرية، بيانات مضغوطة)، فإن Base64 هو الطريقة المعيارية لتضمينها في حمولة JSON. بالمثل، إذا احتجت إلى تمرير بيانات ثنائية في معامل استعلام URL، فإن ترميز Base64url يضمن سلامة البيانات عبر ترميز النسب المئوية دون تلف.

JWT وتنسيقات الرموز الأخرى

تستخدم رموز JWT البنية Base64url لترميز أقسام الترويسة والحمولة. هذا يجعل الرمز سلسلة قابلة للطباعة وآمنة للروابط يمكن تمريرها في ترويسات HTTP أو ملفات تعريف الارتباط أو معاملات URL. الترميز ليس لأغراض أمنية (الحمولة قابلة للقراءة من قبل أي شخص يمتلك الرمز) — إنه فقط للنقل الآمن.

متى لا تستخدم Base64

الأمان والسرية

لا يوفر Base64 أي أمان. إنه قابل للعكس بسهولة في أجزاء من الثانية. لا تستخدمه "لإخفاء" كلمات المرور أو مفاتيح API أو قيم الإعدادات الحساسة. أي مطور يرى سلسلة Base64 سيفك ترميزها فورًا. إذا كنت بحاجة إلى سرية، استخدم التشفير.

تخزين كلمات المرور

تخزين كلمات المرور المُرمَّزة بـ Base64 يعادل تخزينها كنص عادي — الترميز قابل للعكس فورًا. يجب تجزئة كلمات المرور باستخدام دالة تجزئة مناسبة مثل bcrypt أو Argon2 أو scrypt.

الملفات الثنائية الكبيرة

ترميز ملف بحجم 10 ميغابايت بـ Base64 ينتج سلسلة بحجم 13.7 ميغابايت. إذا خزّنت ذلك في عمود قاعدة بيانات أو بحثت فيه أو أرسلته عبر واجهة برمجية، فستدفع التكلفة الإضافية بنسبة 33٪ في كل مرة. للبيانات الثنائية الكبيرة، استخدم التخزين الثنائي المخصص: أعمدة BLOB/BYTEA في قاعدة البيانات، أو تخزين الكائنات مثل S3 أو GCS، أو دفق البيانات الثنائية مباشرةً.

الحالات التي يمكنك فيها استخدام البيانات الثنائية مباشرةً

إذا كان بروتوكولك أو تنسيقك يدعم البيانات الثنائية الخام — مثل WebSocket بنوع رسائل ثنائي، أو رفع HTTP بنوع multipart/form-data، أو تنسيق ملف ثنائي — فاستخدم البيانات الثنائية مباشرةً. Base64 ضروري فقط عندما لا يستطيع وسيط النقل التعامل مع البايتات الخام.

الأخطاء الشائعة

الخلط بين الترميز والتشفير

هذا هو الخطأ الأكثر شيوعًا. Base64 مرئي. إنه ليس آلية أمان. تعليقات الكود من قبيل "كلمة المرور مُخزَّنة بترميز Base64 للأمان" تشير إلى سوء فهم جسيم ينبغي اكتشافه في مراجعة الكود.

استخدام btoa() مع سلاسل Unicode

استدعاء btoa() على سلسلة تحتوي على أحرف بنقاط كود تتجاوز 255 يُطلق DOMException: Failed to execute 'btoa': The string to be encoded contains characters outside of the Latin1 range. حوّل دائمًا إلى Uint8Array عبر TextEncoder قبل ترميز السلاسل التي قد تحتوي على أحرف Unicode.

نسيان الحشو عند فك الترميز

يجب أن تكون أطوال سلاسل Base64 من مضاعفات 4. إذا أُنشئت سلسلة Base64 بدون حشو (شائع في الترميز الآمن للروابط)، يجب إضافة العدد الصحيح من أحرف = قبل فك الترميز. سلسلة Base64 بطول n تحتاج إلى (4 - n % 4) % 4 أحرف حشو. نسيان هذا يسبب أخطاء فك ترميز يصعب تشخيصها.

الترميز المزدوج

سلسلة Base64 هي نفسها ASCII صالحة، لذا يعمل btoa(btoa(data)) دون أخطاء لكنه ينتج إخراجًا مُشفَّرًا مرتين. عند تمرير قيم Base64 عبر طبقات تسلسل متعددة (JSON داخل JSON مثلًا)، من السهل ترميز نفس البيانات مرتين. افك الترميز دائمًا بعدد المرات التي رمّزت فيها بالضبط.

مرجع سريع: Base64 في التطبيق العملي

لترميز وفك ترميز بدون كتابة كود في المتصفح، يعمل مشفر/مفكك Base64 في Toova كليًا داخل متصفحك — بدون رحلة إلى خادم. يدعم المتغيرَين القياسي والآمن للروابط، ورفع الملفات لترميز الملفات الثنائية، وإخراجًا نصيًا وسداسيًا للبيانات المُفكَّكة.

إذا كنت تعمل مع محتوى مُشفَّر داخل عناوين URL، فإن مُشفِّر/مُفكِّك URL يتعامل مع الترميز بالنسب المئوية بشكل منفصل عن Base64. لكيانات HTML، يتعامل محوّل كيانات HTML مع الهروب من الأحرف في سياقات HTML. هذه أنظمة ترميز مستقلة — لكل منها حالة استخدام محددة.

المرجع المعياري لـ Base64 هو RFC 4648، الذي يحدد Base64 القياسي (القسم 4) وBase64url (القسم 5) وBase32 (الأقسام 6–7). لواجهتَي برمجة المتصفح btoa() وatob()، توفر توثيقات MDN لـ btoa() تفاصيل التوافق مع المتصفحات وقيد Unicode بالتفصيل.

ملخص

يحوّل ترميز Base64 البيانات الثنائية إلى ASCII قابل للطباعة باستخدام أبجدية مكونة من 64 حرفًا. يزيد حجم البيانات بنسبة 33٪، وهو قابل للعكس تمامًا، ولا يوفر أي أمان. استخدمه عندما تحتاج إلى تضمين بيانات ثنائية في تنسيق نصي — حمولات JSON، وعناوين URI للبيانات بصيغة HTML، ورموز JWT، ومرفقات البريد الإلكتروني، ومعاملات URL. تجنبه عندما تحتاج إلى أمان، أو عندما يدعم النقل البيانات الثنائية مباشرةً، أو عندما تكون التكلفة الإضافية بنسبة 33٪ مهمة على نطاق واسع.

فهم ما هو Base64 وما الذي ليس هو يمنع الأخطاء الأكثر شيوعًا: استخدامه للأمان، وتطبيقه على الملفات الكبيرة دون ضرورة، والخلط بينه وبين أنظمة ترميز أخرى مثل ترميز URL أو كيانات HTML. كل نظام ترميز يحل مشكلة محددة. Base64 يحل مشكلة واحدة بالضبط: جعل البيانات الثنائية آمنة للقنوات النصية فقط.

هل أنت مستعد للترميز أو فك الترميز؟ جرب مشفر/مفكك Base64 في Toova — الصق النص أو أسقط ملفًا، بدّل بين المتغيرَين القياسي والآمن للروابط، وانسخ النتيجة. بدون حساب، بدون خادم، بدون حدود.