
محرك تشفير ملفات متعدد الخيوط بسرعة جيجابايت في الثانية. يحقق إنتاجية فائقة باستخدام خط أنابيب io_uring ثلاثي التخزين المؤقت وخالٍ من الأقفال، وتقطيع متوازي عبر Rayon، وطرق تشفير AEAD مسرّعة بالأجهزة (AES-256-GCM / ChaCha20).
محرك تشفير AEAD متعدد الخيوط مكتوب بلغة Rust. يقوم بتشفير وفك تشفير الملفات بمعدل نقل يصل إلى غيغابايت في الثانية باستخدام خط أنابيب io_uring ثلاثي التخزين المؤقت، ومعالجة القطع المتوازية عبر Rayon، وأصفار محسّنة على مستوى التجميع عبر ring.
⚠️ إخلاء مسؤولية: برنامج تجريبي ⚠️
هذا المشروع جديد جدًا وحاليًا غير موصى به للاستخدام الإنتاجي أو المهام الحيوية. على الرغم من أن الأساسيات التشفيرية (AES-256-GCM و ChaCha20-Poly1305 عبر ring) وتصميم التنسيق سليمة، إلا أن قاعدة الكود لم تخضع لتدقيقات أمنية رسمية أو اختبارات موسعة في العالم الحقيقي. استخدمه على مسؤوليتك الخاصة. لحماية البيانات الحساسة، فكر في استخدام أدوات مُختبرة مثل GnuPG أو age أو OpenSSL حتى ينضج هذا المشروع.
ring (مُحسَّن على مستوى التجميع)--memory)seal_in_place_separate_tag / open_in_place عبر ring يقلل من التخصيص في الحلقة الساخنةO_DIRECT، متجاوزة ذاكرة التخزين المؤقت للنواة للقراءة/الكتابة بسرعة DMA على أقراص NVMe. تستخدم مجموعات المخازن المؤقتة std::alloc مع محاذاة 4096 بايتتم قياسه باستخدام cargo bench (Criterion، 10 عينات لكل قياس). تم استبعاد اشتقاق المفتاح - الأرقام تعكس فقط إنتاجية التشفير الخالص.
العتاد:
ملاحظة حول I/O: يكتب Criterion الملفات المؤقتة إلى /tmp، وهو على هذا النظام tmpfs (مدعوم بالذاكرة العشوائية). مع O_DIRECT، لا تستطيع النواة استخدام DMA غير متزامن حقيقي على tmpfs، لذا تعكس هذه الأرقام إنتاجية التشفير + حمل io_uring بدون فوائد تجاوز DMA. على قرص NVMe حقيقي من الجيل الرابع، يؤدي O_DIRECT إلى إلغاء التخزين المؤقت المزدوج لصفحة الذاكرة وتمكين DMA مباشرة إلى مجموعات المخازن المؤقتة المحاذية، مما يجب أن يحقق إنتاجية أعلى بكثير.
| حجم الملف | تشفير AES-256-GCM | تشفير ChaCha20 | فك تشفير AES-256-GCM | فك تشفير ChaCha20 |
|---|---|---|---|---|
| 64 KiB | 244 MiB/s | 233 MiB/s | 233 MiB/s | 234 MiB/s |
| 1 MiB | 1.08 GiB/s | 882 MiB/s | 1010 MiB/s | 876 MiB/s |
| 16 MiB | 1.10 GiB/s | 923 MiB/s | 1.06 GiB/s | 988 MiB/s |
| 64 MiB | 984 MiB/s | 935 MiB/s | 988 MiB/s | 973 MiB/s |
| 256 MiB | 1.00 GiB/s | 1015 MiB/s | 1.01 GiB/s | 1.02 GiB/s |
فحص حجم القطعة (AES-256-GCM، ملف بحجم 64 MiB):
| حجم القطعة | الإنتاجية |
|---|---|
| 64 KiB | 1.01 GiB/s |
| 256 KiB | 1.05 GiB/s |
| 1 MiB | 1.07 GiB/s |
| 4 MiB | 988 MiB/s |
| 8 MiB | 988 MiB/s |
| 16 MiB | 1.00 GiB/s |
يستخدم المحرك ring (AES-NI / NEON / ARMv8-CE المُحسَّنة على مستوى التجميع) لعمليات الصفار وخط أنابيب io_uring ثلاثي التخزين المؤقت لـ I/O. ثلاث مجموعات عازلة مخصصة مسبقًا تدور عبر خط الأنابيب: بينما تكتمل عمليات كتابة المجموعة A في النواة، تكون المجموعة B قيد التشفير بواسطة Rayon على وحدة المعالجة المركزية، وتكون المجموعة C قيد قراءة I/O المقدمة إلى النواة. هذا يتداخل بين زمن استجابة I/O وحساب التشفير.
لماذا AES-256-GCM أسرع من ChaCha20-Poly1305 على الملفات الصغيرة:
الخلفية الخلفية لـ AES-GCM في ring تستغل تعليمات AES-NI + CLMUL العتادية المتاحة على x86-64، مما يمنحها ميزة عتادية على ChaCha20 (وهو صفار برمجي). عند الأحجام الأكبر يتقارب الصفّاران إلى حوالي 1.0 GiB/s، مما يشير إلى أن عنق الزجاجة ينتقل من إنتاجية الصفار إلى حمل تقديم I/O.
لماذا ذروة الإنتاجية عند 1-16 MiB وليس 256 MiB: الملفات الصغيرة (1-16 MiB) تحتوي على عدد قليل من القطع، لذا تكون توازية Rayon فعالة وتناسب مجموعة العمل في الذاكرة المخبئية. عند 64-256 MiB، يكون خط أنابيب io_uring نشطًا بالكامل (ثلاث مجموعات في الطيران)، لكن حمل تقديم SQE وجمع CQE يتناسب مع عدد القطع. يضمن التصميم ثلاثي التخزين المؤقت تداخل I/O والتشفير، مما يخفي هذه التكلفة جزئيًا.
لماذا ~1.0 GiB/s وليس أكثر من 10 GiB/s: يمكن لـ AES-NI الحديثة دفع 2-4 GiB/s لكل نواة. مع 12 خيطًا، قد تتجاوز إنتاجية الصفار الخام 10 GiB/s. ثلاثة عوامل تفسر الفجوة:
PIPELINE_DEPTH=3، تدور ثلاث مجموعات فقط عبر خط الأنابيب في أي وقت. يتطلب التداخل الثابت عند الحالة المستقرة ثلاث مجموعات على الأقل؛ الملفات التي تناسب مجموعة أو مجموعتين لا تستفيد من خط الأنابيب.دورة حياة المخازن المؤقتة والأمان:
يتم تخصيص مجموعات المخازن المؤقتة مرة واحدة عبر std::alloc::alloc_zeroed مع Layout::from_size_align(size, 4096) قبل إنشاء حلقة io_uring، ويتم إعادة استخدامها عبر جميع تكرارات خط الأنابيب دون إعادة تخصيص. تُحشى كل قطعة مشفرة بالأصفار إلى محاذاة القطاع قبل كتابة O_DIRECT. يتم إسقاط الحلقة صراحةً قبل مجموعات المخازن المؤقتة، مما يضمن أن النواة لا تشير أبدًا إلى ذاكرة محررة (لا UAF).
git clone https://github.com/frogsnot/concryptor.git
cd concryptor
cargo build --release
سيكون الملف الثنائي في target/release/concryptor.