سؤال

مرحبًا ، هذا هو نفس السؤال ، الذي تم طرحه قبل عامين:Java/JCE: فك تشفير رسالة "طويلة" مشفرة بـ RSA

كان لدي مجموعة كبيرة من البايت و RSA Keypair ، التي بدأت بالقيمة 1024. باستخدام تشفير RSA والحجم المحدد للمفتاح هو متطلب قوي ، لا يمكنني تغييره. لذلك لا يمكنني استخدام التشفير المتماثل مع مفتاح التشفير غير المتماثل. لا يمكنني استخدام أي مفاتيح أخرى. كان لدي صفيف بايت وأحتاج إلى مجموعة بايت مشفرة ليتم إرجاعها. أتساءل عما إذا كان هناك أي أداة جاهزة ، يمكن أن تدير هذه المشكلة؟

آسف لمثل هذا السؤال الهواة ، لكنني بحاجة حقًا إلى مساعدة.

هل كانت مفيدة؟

المحلول

كما ذكر ، سؤالك له إجابة واحدة ، وهذا "لا". تشفير RSA هو خوارزمية تشفر الرسائل بحجم معين ، والذي يعتمد على حجم المفتاح ؛ مع مفتاح RSA 1024 بت ، و RSA كما المعيار يصفه ، الحد الأقصى للحجم هو 117 بايت ، لا أكثر. لا توجد طريقة لتشفير رسالة أكبر مع RSA وحدها ، وهذا يقين محدد ورياضي.

إذا كنت بحاجة حقًا إلى معالجة الرسائل لفترة أطول ، فأنت أنت بالضرورة يجب أن تضيف شيئًا آخر. في هذه الحالة ، من فضلك ، من فضلك, ، لا تحاول أن تفعل أي شيء يتوهم من ابتكارك مع بعض تقسيم البيانات إلى كتل صغيرة وما شابه. هذا المسار يؤدي إلى الموت. قد تنتج شيئًا ما يبدو لتجميع وتشغيل ، ولكن سيكون ضعيفًا دائمًا بطريقة ما ، مثل كل التباين المحلي تقريبًا في التشفير. ذلك لأنه لا يمكن اختبار الأمن: إنها ليست حالة من "الأعمال" أو "لا تعمل".

إن المسار المدمر جيدًا للتشفير غير المتماثل يسير على هذا النحو:

  1. يمكنك تحديد تسلسل عشوائي من بايت من بعض الطول المناسب ، على سبيل المثال 128 بت (هذا هو 16 بايت). دعنا نسميها ك.
  2. أنت تشفير ك مع مفتاح RSA العام ؛ هذه العوائد ه.
  3. يمكنك تشفير الرسالة مع ك باستخدام خوارزمية التشفير المتماثل ("AES/CBC/PKCS5Padding"). نظرًا لأن هذا مفتاح واحد ، يمكنك استخدام All-Zeros IV. هذا يعطي مجموعة من البايتات ، دعنا نسميها F.
  4. الرسالة المشفرة هي بعد ذلك تسلسل ه و F.

عائدات فك التشفير بالترتيب العكسي: يتم استخدام مفتاح RSA الخاص للاسترداد ك من ه, ، ومن بعد ك يستخدم لفك التشفير F في الرسالة الأصلية. المفتاح ك لا يتم تخزينه أبدًا في أي مكان ، و مفتاح جديد ك يتم إنشاؤه في كل مرة (حتى لو قمت بتشفير نفس الرسالة مرتين). هذا مهم ، لا تغير ذلك إلا إذا فهمت ما تفعله (وإذا قمت بذلك ، فأنت تعرف ذلك بالفعل).

بالنظر إلى ما تقوله حول مشكلتك ، أنت لديك لفعل شيء آخر غير "RSA". الإجراء الذي أصفه أعلاه يدور حول أفضل "شيء آخر" الذي يمكن أن توصل إليه ، من الناحية الأمنية.

يعد تجميع بعض عناصر التشفير في مثل هذا البروتوكول عملية محفوفة بالمخاطر ، لذا قد يكون لديك حظ أفضل باستخدام تنسيق ودعم محدد بالفعل. تنسيقان شائعان للتشفير غير المتماثل CMS و OpenPGP. مكتبة تدعم كليهما ولديها سمعة طيبة نطاط القلعة.

نصائح أخرى

إذا كنت بحاجة إلى تشفير/فك تشفير الأوتار الطويلة باستخدام RSA ، فيمكنك تقسيم البايت إلى "قطع" أصغر ومعالجة كل جزء من البايتات عبر الشفرة في وقت واحد أثناء تخزين النتائج في البايت.

التشفير:

byte[] encData = null;
try {

    // create public key
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(key);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PublicKey pk = kf.generatePublic(publicKeySpec);

    Cipher pkCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    pkCipher.init(Cipher.ENCRYPT_MODE, pk);

    int chunkSize = 117; // 1024 / 8 - 11(padding) = 117
    int encSize = (int) (Math.ceil(data.length/117.0)*128);
    int idx = 0;
    ByteBuffer buf = ByteBuffer.allocate(encSize);
    while (idx < data.length) {
        int len = Math.min(data.length-idx, chunkSize);
        byte[] encChunk = pkCipher.doFinal(data, idx, len);
        buf.put(encChunk);
        idx += len;
    }

    // fully encrypted data     
    encData = buf.array();
} catch (Exception e) {
    e.printStackTrace();

فك التشفير

Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.DECRYPT_MODE, rsaPk);

int chunkSize = 128;
int idx = 0;
ByteBuffer buf = ByteBuffer.allocate(data.length);
while(idx < data.length) {
    int len = Math.min(data.length-idx, chunkSize);
    byte[] chunk = rsaCipher.doFinal(data, idx, len);
    buf.put(chunk);
    idx += len;
}

// fully decrypted data
byte[] decryptedData = buf.array();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top