لماذا كلمة سيئة تسبب "الحشو غير صالح ولا يمكن إزالتها"?

StackOverflow https://stackoverflow.com/questions/11762

  •  08-06-2019
  •  | 
  •  

سؤال

أنا في حاجة إلى بعض بسيطة سلسلة التشفير ، لذلك كتبت البرمجية التالية (مع قدر كبير من "إلهام" من هنا):

    // create and initialize a crypto algorithm
    private static SymmetricAlgorithm getAlgorithm(string password) {
        SymmetricAlgorithm algorithm = Rijndael.Create();
        Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
            password, new byte[] {
            0x53,0x6f,0x64,0x69,0x75,0x6d,0x20,             // salty goodness
            0x43,0x68,0x6c,0x6f,0x72,0x69,0x64,0x65
        }
        );
        algorithm.Padding = PaddingMode.ISO10126;
        algorithm.Key = rdb.GetBytes(32);
        algorithm.IV = rdb.GetBytes(16);
        return algorithm;
    }

    /* 
     * encryptString
     * provides simple encryption of a string, with a given password
     */
    public static string encryptString(string clearText, string password) {
        SymmetricAlgorithm algorithm = getAlgorithm(password);
        byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);
        MemoryStream ms = new MemoryStream();
        CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write);
        cs.Write(clearBytes, 0, clearBytes.Length);
        cs.Close();
        return Convert.ToBase64String(ms.ToArray());
    }

    /*
     * decryptString
     * provides simple decryption of a string, with a given password
     */
    public static string decryptString(string cipherText, string password) {
        SymmetricAlgorithm algorithm = getAlgorithm(password);
        byte[] cipherBytes = Convert.FromBase64String(cipherText);
        MemoryStream ms = new MemoryStream();
        CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
        cs.Write(cipherBytes, 0, cipherBytes.Length);
        cs.Close();            
        return System.Text.Encoding.Unicode.GetString(ms.ToArray());
    }

رمز يبدو للعمل بشكل جيد, إلا أنه عندما فك تشفير البيانات مع مفتاح غير صحيح, أحصل على CryptographicException - "الحشو غير صالح ولا يمكن إزالتها" - على cs.Close() خط في decryptString.

رمز المثال:

    string password1 = "password";
    string password2 = "letmein";
    string startClearText = "The quick brown fox jumps over the lazy dog";
    string cipherText = encryptString(startClearText, password1);
    string endClearText = decryptString(cipherText, password2);     // exception thrown

سؤالي هو هل هذا هو المتوقع ؟ أنا أعتقد أن فك تشفير مع كلمة مرور خاطئة من شأنه أن يؤدي فقط في هراء الانتاج بدلا من استثناء.

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

المحلول

على الرغم من أن هذا قد أجبت أعتقد أنه سيكون فكرة جيدة لشرح لماذا فمن المتوقع.

بطانة مخطط تطبق عادة لأن معظم التشفير المرشحات لا لغويا آمنة لمنع بعض أشكال cryptoatacks.على سبيل المثال, عادة في RSA على OAEP الحشو هو النظام المستخدم الذي يمنع بعض أنواع الهجمات (مثل اختيار عادي هجوم أو المسببة للعمى).

بطانة مخطط إلحاق بعض (عادة) بشكل عشوائي القمامة إلى الرسالة m قبل إرسال الرسالة.في OAEP طريقة اثنين على سبيل المثال ، الايحاءات تستخدم (هذا هو شرح مبسط):

  1. وبالنظر إلى حجم معامل لك ومبطن الجدرا k1 بت مع 0 و k0 بت مع عدد عشوائي.
  2. ثم من خلال تطبيق بعض التحول إلى الرسالة يمكنك الحصول على مبطن الرسالة اللي تبونه مشفرة أرسلت.

التي توفر لك مع العشوائية على الرسائل مع وسيلة لاختبار إذا كانت الرسالة القمامة أو لا.كما الحشو المخطط هو عكسها ، عند فك تشفير الرسالة بينما لا يمكنك أن تقول أي شيء عن سلامة الرسالة نفسها يمكن في الواقع جعل بعض التأكيد حول الحشو وهكذا يمكنك أن تعرف إذا كانت الرسالة قد تم بشكل صحيح فك أو كنت تفعل شيئا خاطئا (أنا.هـ شخصا ما قد عبث رسالة أو كنت تستخدم مفتاح خاطئ)

نصائح أخرى

لقد شهدت مماثلة "الحشو غير صالح ولا يمكن إزالتها." استثناء, ولكن في حالتي المفتاح الرابع و الحشو كانت صحيحة.

اتضح أن فلاشينغ التشفير تيار كل ما كان في عداد المفقودين.

مثل هذا:

            MemoryStream msr3 = new MemoryStream();
            CryptoStream encStream = new CryptoStream(msr3, RijndaelAlg.CreateEncryptor(), CryptoStreamMode.Write);
            encStream.Write(bar2, 0, bar2.Length);
            // unless we flush the stream we would get "Padding is invalid and cannot be removed." exception when decoding
            encStream.FlushFinalBlock();
            byte[] bar3 = msr3.ToArray();

إذا كنت ترغب في استخدام الخاص بك أن تكون صحيحة ، يجب إضافة المصادقة إلى النص المشفر بحيث يمكنك التحقق من أنه هو الصحيح pasword أو أن النص المشفر لم يتم تعديلها.الحشو كنت تستخدم ISO10126 فقط رمي استثناء إذا كان البايت الأخير لا فك تشفير باعتبارها واحدة من 16 القيم الصالحة من أجل الحشو (0x01-0x10).بحيث يكون لديك 1/16 فرصة لا رمي استثناء مع مرور خاطئة ، حيث إن مصادقة لديك القطعية طريقة لمعرفة إذا فك التشفير الخاص بك صالحة.

باستخدام تشفير api في حين تبدو سهلة ، هو في الواقع وليس من السهل أن يخطئ.على سبيل المثال يمكنك استخدام ثابت الملح بالنسبة لك المفتاح الرابع الاشتقاق ، هذا يعني أن كل المشفر المشفرة مع نفس كلمة المرور إعادة استخدام الأمر الرابع مع ذلك المفتاح الذي يكسر الدلالي الأمن مع CBC الوضع الرابع يجب أن يكون على حد سواء لا يمكن التنبؤ بها و فريدة من نوعها على مفتاح معين.

لهذا السبب من السهل أن يخطئ ، لدي البرمجية المتكررة التي أحاول الحفاظ على مراجعة ما يصل إلى التاريخ (تعليقات القضايا موضع ترحيب):

أمثلة حديثة من متماثل مصادقة التشفير من سلسلة C#.

إذا كنت تستخدم الأمر AESThenHMAC.AesSimpleDecryptWithPassword(ciphertext, password) عند مرور خاطئة تستخدم ، null هو عاد ، إذا كان النص المشفر أو الرابع تم تعديل وظيفة التشفير null هو عاد ، سوف أبدا الحصول على البيانات غير المرغوب فيه مرة أخرى ، أو الحشو استثناء.

إذا كنت قد استبعد مفتاح-عدم تطابق ، ثم إلى جانب FlushFinalBlock() (انظر يانيف الجواب) ، داعيا Close() على CryptoStream سوف يكون كافيا أيضا.

إذا كنت تنظيف الموارد بدقة using كتل ، تأكد من عش كتلة CryptoStream نفسها:

using (MemoryStream ms = new MemoryStream())
using (var enc = RijndaelAlg.CreateEncryptor())
{
  using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write))
  {
    encStream.Write(bar2, 0, bar2.Length);
  } // implicit close
  byte[] encArray = ms.ToArray();
}

لقد تم عضك من قبل (أو مشابهة):

using (MemoryStream ms = new MemoryStream())
using (var enc = RijndaelAlg.CreateEncryptor())
using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write))
{
  encStream.Write(bar2, 0, bar2.Length);
  byte[] encArray = ms.ToArray();
} // implicit close -- too late!

نعم, هذا أمر متوقع ، أو على الأقل ، بالضبط ما يحدث عندما التشفير إجراءات الحصول على غير decryptable البيانات

سبب آخر من الاستثناء قد يكون حالة سباق بين العديد من المواضيع باستخدام التشفير المنطق - تطبيقات الأم من ICryptoTransform هي لا مؤشر الترابط-الآمن (مثلا ، SymmetricAlgorithm) ، لذلك يجب أن يكون وضع قسم خاص مثلاباستخدام قفل.يرجى الرجوع هنا لمزيد من التفاصيل: http://www.make-awesome.com/2011/07/system-security-cryptography-and-thread-safety/

قد يكون هناك بعض المقروءة بايت في CryptoStream.إغلاق قبل قراءة تيار تماما كان يسبب خطأ في البرنامج.

كان لي مشكلة مماثلة ، مشكلة في فك تشفير طريقة تهيئة ذاكرة فارغة تيار.عندما عملت عندما تهيئة مع النص المشفر صفيف بايت مثل هذا:

MemoryStream ms = new MemoryStream(cipherText)

الجواب تحديث من قبل المستخدم "atconway" عملت بالنسبة لي.

المشكلة ليست مع الحشو ولكن المفتاح الذي كان مختلفا خلال التشفير و فك التشفير.المفتاح الرابع ينبغي أن يكون نفسه خلال encypting و فك تشفير نفس القيمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top