شرح ترميز النص في Dart والفرق بين تبديل المحارف وUnicode والتشفير الحقيقي، مع نموذج Base64 لا يدعي حماية البيانات.
استبدال الأحرف ليس تشفيرًا آمنًا
تحويل t إلى 505 أو زيادة codeUnit بمقدار ثابت يمكن عكسه بسهولة، ولا يقدم سرية أو توثيقًا. كما أن سلسلة replaceAll قد تسبب تصادمًا إذا دخل ناتج استبدال ضمن قاعدة تالية، وقد لا تكون عملية فكها وحيدة. استعمل هذه الأفكار كلغز أو تجربة تمثيل فقط ولا تحفظ بها كلمة مرور أو بيانات مستخدم حساسة.
Unicode والترميز والنقل
codeUnitAt يتعامل وحدات UTF-16، لا كل حرف مرئي؛ قد تمتد بعض الرموز إلى زوج وحدات أو عدة محارف مركبة. لتبادل نص عربي عبر Base64 حول UTF-8 إلى بايتات ثم شفرها بـbase64Encode، واعكس بالترتيب الصحيح مع معالجة FormatException. Base64 مكشوف المحتوى أيضًا؛ إذا احتجت حماية فعلية اتبع درس التشفير الموثق وإدارة المفاتيح.
ترميز قابل للعكس دون سر
Base64 يمثل البايتات بمحارف ملائمة لبعض بروتوكولات النقل؛ أي شخص يملك النص يستطيع فكها دون مفتاح. لهذا ليس مناسبًا وحده لحماية token أو كلمة مرور أو ملف خاص. كذلك تغيير الحروف وفق جدول معلن لا يبني خوارزمية أمنية جديدة. إن كان هدفك تمرينًا تعليميًا فسمّه استبدالًا أو ترميزًا واشرح حدود عملية الفك بدل وعد المستخدم أن البيانات أصبحت محمية.
النص والبايتات خطوتان منفصلتان
String في Dart تمثل نصًا، أما Base64 فتعمل على bytes. استعمل utf8.encode للنص ثم base64Encode، وعند الرجوع فك Base64 ثم utf8.decode. هذه الخطوات تحافظ على العربية والرموز عند صحة المدخل، وتختلف عن الاعتماد على codeUnitAt لكل موضع ثم افتراض أن رقمًا واحدًا يساوي حرفًا مرئيًا. لا تغير البايتات لتوافق لغة الواجهة، ولا تضف مسافات أو تنسيق HTML داخل قيمة منقولة يتوقعها خادم حرفيًا.
فشل الإدخال والحدود
قد يصل نص ليس Base64 صالحًا أو بايتات ليست UTF-8، فيجب أن تتعامل مع FormatException وفق مصدر البيانات. ضع حدًا لحجم مدخل قادم من مستخدم أو شبكة قبل فكّه حتى لا تخصص ذاكرة كبيرة دون داع. ارفض الحقول المفقودة في عقد الرسالة بدل إرجاع String فارغة تخفي السبب. base64Url له أبجدية مناسبة لسياقات URL، لكن الاتفاق مع الطرف الآخر مهم ولا تجعل استبدال المحارف طريقة لمعالجة رابط دون قراءة صيغة البروتوكول.
متى تحتاج تشفيرًا؟
عند الحاجة للسرية والتوثيق اختر تصميمًا بمكتبة تشفير موثوقة وإدارة مفاتيح صحيحة، وليس مجرد دالة تحويل نص. الخوارزمية وحدها لا تحل أين يحتفظ التطبيق بالمفتاح أو كيف يعرف هوية الخادم أو يمنع إعادة إرسال رسالة. أمثلة RSA وAES-GCM المرتبطة تناقش هذا النطاق الآخر. اختبر round trip لنص فارغ وعربي ورمز خارج BMP ومدخل غير صالح، ثم اختبر التعديل والرفض في بروتوكول التشفير إن كان منتجك يستخدمه. لا تسجل النص الحساس لمجرد تسهيل تجربة فك الترميز.
مقارنة مفيدة للدرس
يمكنك رؤية الفرق عمليًا: النص المرمز يُفك دون كلمة سر، بينما بروتوكول تشفير صحيح يرفض فك حمولة معدلة حتى إذا عُرفت الخوارزمية. معرفة الخوارزمية ليست نقطة الضعف بحد ذاتها؛ إخفاء طريقة استبدال بسيطة لا يجعلها قوية. أبق أمثلة الترميز خالية من بيانات حقيقية ثم استخدمها لتعلم انتقال النص إلى bytes والعكس، وحدد في واجهة المنتج هل الإجراء ترميز تصدير أو حماية سرية حتى لا يفهم المستخدم وعدًا غير موجود.
مثال الشفرة بعد المراجعة
اقرأ التعليقات ومتطلبات الإعداد قبل النقل إلى مشروعك. أمثلة الواجهات ذات main مستقلة، أما العقود والمقاطع الأصلية وملفات الإعداد فموضح نطاقها داخل المثال.
import 'dart:convert';
void main() {
const input = 'مرحبا Flutter 👋';
final encoded = base64Encode(utf8.encode(input));
final decoded = utf8.decode(base64Decode(encoded));
assert(decoded == input);
print(encoded); // Encoding for transport; not encryption.
try {
base64Decode('not valid base64!');
} on FormatException {
print('Invalid encoded input');
}
}الصور والفيديو التوضيحي
قد تعرض الوسائط إصدارًا أقدم. اعتمد الخطوات النصية المصححة عند اختلاف إعدادات المنصة أو أسماء الواجهات.


مرجع للتنفيذ
راجع التوثيق الخاص بهذا الموضوع وطابق إعداداته مع إصدار أدوات مشروعك. اختبر السلوك المستهدف وحالة الفشل قبل إدماج المثال في تطبيق منشور.
كيف يرتبط الترميز بالتخزين؟
JSON وUTF-8 وBase64 تمثيلات للبيانات وليست حدودًا للأمان. يمكن حفظ نموذج JSON في التفضيلات عندما لا يكون حساسًا، بينما رمز الجلسة يحتاج سياسة تخزين ومصادقة منفصلة. لا تضع مفتاح التشفير في المكان نفسه مع النص المشفر وتفترض أن ذلك يحميه من استخراج التطبيق. عند اختبار العربية والرموز المركبة قارن النص الكامل بعد فك الترميز بدل افتراض أن طول String يساوي عدد الحروف المرئية.
لإكمال هذا الجزء، انتقل إلى تخزين البيانات الحساسة في Flutter باستخدام flutter_secure_storage، ثم طبّق الربط الذي يناسب بنية مشروعك.






