التوثيق
/
وصفات عملية
/

جلب مفتاح مصفوفة البايت كود من الخادم الخلفي

جلب مفتاح مصفوفة البايت كود من الخادم الخلفي

Pro
v7.3.0+

أبقِ مفتاح فك تشفير بايت كود VM بعيدًا عن العميل: اجلبه من خادمك الخلفي عند التحميل عبر دالة جلب مفتاح غير متزامنة، محميّة خلف المصادقة بحيث تصبح الحزمة المسروقة عديمة الجدوى.

المشكلة

يشفّر vmBytecodeArrayEncoding بايت كود VM بمفتاح. وإذا شُحن ذلك المفتاح داخل الحزمة، فإن أي شخص يملك الملف يملك كل ما يلزم لفك تشفيره. تتيح vmBytecodeArrayEncodingKeyGetter أن يقيم المفتاح في مكان آخر ويُنتَج أثناء التشغيل — لكن دالة الجلب المتزامنة لا يمكنها قراءة إلا ما هو موجود بالفعل على العميل (متغير عام أو ملف تعريف ارتباط أو localStorage). ولجلب المفتاح من خادمك — بحيث يمكنك حمايته خلف المصادقة وإبطاله — يجب أن تكون دالة الجلب غير متزامنة.

الحل

فعّل vmAsyncExecutor (الإصدار 7.3.0 فما فوق). فمع المنفِّذ غير المتزامن يمكن لدالة جلب المفتاح أن تعيد Promise، فتتمكن من fetch المفتاح من خادمك الخلفي قبل تشغيل الآلة الافتراضية. وتعمل ثلاثة خيارات معًا:

  • vmBytecodeArrayEncoding: true — تشفير مصفوفة البايت كود.
  • vmBytecodeArrayEncodingKey — المفتاح المستخدم وقت الترجمة (يبقى على خادمك، لا في الحزمة).
  • vmBytecodeArrayEncodingKeyGetter — تعبير JS يعيد المفتاح نفسه أثناء التشغيل. ومع تفعيل vmAsyncExecutor يمكنه أن يعيد Promise؛ أما بدونه فيجب أن تعيد دالة الجلب المفتاح بشكل متزامن.

إعداد تشويش العميل

JavaScriptObfuscator.obfuscate(sourceCode, {
    vmObfuscation: true,
    vmAsyncExecutor: true,
    vmBytecodeArrayEncoding: true,
    vmBytecodeArrayEncodingKey: process.env.VM_KEY,            // e.g. 'mySecretKey123'
    vmBytecodeArrayEncodingKeyGetter:
        'fetch("/api/vm-key", { credentials: "include" }).then((res) => res.text())'
});

يُضمَّن تعبير دالة الجلب حرفيًا ويُقيَّم في المتصفح. أبقِ مفتاح وقت الترجمة vmBytecodeArrayEncodingKey خارج مستودع العميل لديك — احقنه من متغير بيئة أو سرّ وقت البناء، وقدّم النص نفسه بالضبط من نقطة النهاية أدناه.

كيف يعمل المفتاحان

لا يُستخدم مفتاحك بمفرده أبدًا — فعلى الجانبين يُمزَج بمفتاح داخلي يتحكم فيه المشوِّش:

  • وقت الترجمة. يُدمَج vmBytecodeArrayEncodingKey مع مفتاح داخلي يشتقّه المشوِّش، وتُرمَّز مصفوفة البايت كود بالمفتاح الممزوج الناتج.
  • وقت التشغيل. القيمة التي تُحلّ إليها vmBytecodeArrayEncodingKeyGetter — والتي يعيدها خادمك — تُدمَج مع المفتاح الداخلي نفسه، الذي يُعاد بناؤه على العميل من عوامل تشغيل متعددة، لفك ترميز البايت كود.

ولأن كلا الجانبين يمزج مفتاحك بالمفتاح الداخلي، يجب أن تُحلّ دالة الجلب إلى النص نفسه تمامًا الذي مرّرته بوصفه vmBytecodeArrayEncodingKey. ولا يكفي أي جزء بمفرده: فمفتاحك دون المفتاح الداخلي لا يمكنه فك ترميز البايت كود، والمفتاح الداخلي عديم الفائدة دون مفتاحك — ولهذا فإن تقديم مفتاحك للمستدعين المصادَق عليهم فقط يُبقي الحزمة المسروقة عديمة الجدوى.

جانب الخادم

تقرر نقطة النهاية أي مفتاح تعيد بناءً على ما يثق به تطبيقك — جلسة صالحة، أو قيمة Origin أو Referer متوقعة، أو فحص ترخيص، وهكذا. والحيلة هنا: بدلًا من رفض المستدعين غير الموثوقين، أعِد مفتاحًا خاطئًا. فيُفكّ ترميز البايت كود عندئذ إلى بيانات لا معنى لها ويفشل الكود المحمي من تلقاء نفسه، وهو أخفى من 401 صريح يخبر المهاجم بالضبط بما ينبغي تجاوزه.

// Express example — the exact checks depend on your app
app.get('/api/vm-key', (req, res) => {
    const origin = req.get('origin');
    const trusted =
        req.session?.user &&                       // a valid session, and
        origin === 'https://app.example.com';      // the expected production origin

    res.type('text/plain').send(
        // Real key for valid users; a decoy for everyone else
        // (no session, or a localhost / unexpected origin).
        trusted ? process.env.VM_KEY : process.env.VM_DECOY_KEY
    );
});