ثلاث مرات: المفتاح المحدد هو مفتاح ضعيف معروف ل "ثلاث مرات" ولا يمكن استخدامه

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

سؤال

أنا أستخدم فئة .NET 3.0 System.Security.Cryptography.MACTripleDES فئة لتوليد قيمة ماك. لسوء الحظ، أنا أعمل مع جهاز الأجهزة يستخدم "1111111111111111"(كماثة) ككل مفتاح واحد طول. ال System.Security.Cryptography تقوم المكتبة بتسجيل بعض المعاقين في المفتاح وإرجاع استثناء إذا حاولت استخدام مفتاح ضعيف تشفيريا.

علي سبيل المثال:

byte[] key = new byte[24];
for (int i = 0; i < key.Length; i++)
  key[i] = 0x11;

byte[] data = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] computedMac = null;
using (MACTripleDES mac = new MACTripleDES(key))
{
  computedMac = mac.ComputeHash(data);
}

يلقي استثناء

System.Security.Cryptography.CryptographicException : Specified key is a known weak key for 'TripleDES' and cannot be used.

أعلم أن هذا ليس مفتاح آمن. في الإنتاج، سيتم تومض الجهاز مع مفتاح جديد آمن جديد. في الوقت نفسه، هل هناك أي طريقة لمنع هذا الاستثناء من إلقاؤها؟ ربما an. app.config أو إعداد التسجيل؟

تحرير: سيكون المفتاح بالفعل 101010 ... بسبب الخوارزمية التي تجبر التكافؤ الفردي. لست متأكدا مما إذا كان هذا عالميا لخلع الخوارزمية أو مجرد شرط في أعمال معالجة الدفع أفعل.

تحرير 2: إجابة دانيال أدناه لديها بعض المعلومات جيدة جدا حول القرصنة .NET. لسوء الحظ، لم أتمكن من حل مشكلتي باستخدام هذه التقنية، ولكن لا يزال هناك بعض القراءة المثيرة للاهتمام هناك.

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

المحلول

بدلا من استخدام MacTripledes باستخدام Key Key المتكرر لإزاحة DES CBC-Mac المزيفة، يمكنك فقط تطبيق CBC-Mac بنفسك على رأس descryptoserviceProvider..

<11111111111111111> ليس مفتاح des ضعيف.

سيؤدي ذلك إلى حساب DES CBC-MAC:

public static byte[] CalcDesMac(byte[] key, byte[] data){
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
        des.Key = key;
        des.IV = new byte[8];
        des.Padding = PaddingMode.Zeros;
        MemoryStream ms = new MemoryStream();
        using(CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)){
          cs.Write(data, 0, data.Length);
        }
        byte[] encryption = ms.ToArray();
        byte[] mac = new byte[8];
        Array.Copy(encryption, encryption.Length-8, mac, 0, 8);
        PrintByteArray(encryption);
        return mac;
    }

نصائح أخرى

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

تعديل:

آسف، استغرق الأمر بعض الوقت لتحميل كل ذلك في جهازي الظاهري (تشغيل أوبونتو) ولم يرغب في الفوضى مع أحادي.

  • تثبيت reflexil الوظيفة الإضافية: عرض -> الوظائف الإضافية -> إضافة
  • فتح Reflexil: أدوات -> Reflexil V0.9
  • العثور على وظيفة isweakkey (). (يمكنك استخدام البحث: F3)
  • ستأتي وظيفتان، doubleclick واحد موجود في system.security.cryptography.trepledes
  • يجب أن يأتي رد الفعل أيضا. في علامة التبويب "التعليمات"، قم بالتمرير طوال الطريق إلى السطر 29 (Offset 63).
  • تغيير LDC.I4.1 إلى LDC.I4.0، وهذا يعني أن الوظيفة ستظهر دائما خطأ.

في جزء التجميعات الخاصة بك (يسارا واحدا)، يمكنك الآن التمرير وانقر فوق "مكتبة وقت تشغيل اللغة الشائعة"، سيمنحك جزء Reflexil خيارا لحفظه.

ملاحظات هامة:

  • نسخ احتياطي التجميع الأصلي الخاص بك أولا! (mscorlib.dll)
  • mscorlib.dll هي تجميع موقعة وستحتاج إلى .NET SDK (أداة SN.EXE) لرفادة الانعكاس لجعلها تخطي التحقق. لقد قمت بالتحقق من هذا بنفسي، يجب أن يكون لديك بالفعل هذا مع تثبيت Visual C #. فقط انقر فوق "تسجيله للتحقق من تخطي (على هذا الكمبيوتر)" عند طلب ذلك.
  • لا أعتقد أن علي أن أخبرك باستخدام هذا فقط على جهاز التطوير الخاص بك :)

حظ سعيد! إذا كنت بحاجة إلى تعليمات إضافية، فلا تتردد في استخدام علبة التعليق.

Edit2:

انا مرتبك!

أزلت تماما فحص ISWECKEY من وظيفة SET_KEY في تجميع MSCORLIB. أنا متأكد تماما من أنني قمت بتعديل الوظيفة الصحيحة، وأنا فعلت ذلك بشكل صحيح. Disassembler العاكس لم يعد يظهر الشيك. ومع ذلك، فإن الشيء المضحك، أن المرئي C # لا يزال يلقي نفس الاستثناء.

هذا يقودني للاعتقاد بأن mscorlib يجب أن تظل بطريقة أو بأخرى مخزنة في مكان ما. ومع ذلك، إعادة تسمية mscorlib.dll إلى mscorlib.dll_ يؤدي تحطم msvc # لتعطل، لذلك يجب أن تظل تعتمد على DLL الأصلي.

هذه أشياء مثيرة للاهتمام للغاية، لكنني أعتقد أنني وصلت إلى النقطة حيث ليس لدي أدنى فكرة عما يحدث، إلا أنه لا معنى له! انظر الصورة المرفقة. :(

Edit3:

لاحظت في Olly، على عكس التجميعات مثل MScoree و Mscorsec و Mscorwks؛ mscorlib.dll لم يكن موجودا بالفعل في: c: windows microsoft.net framework v2.0.50727

ولكن بدلا من ذلك، في ما يبدو أنه موقع غير موجود: C: Windows Assembly Nativeimages_v2.0.50727_32 mscorlib 6d667f19d687361886990f3ca0f49816 mscorlib.ni.dll

أعتقد أنني في عداد المفقودين شيئا هنا :) سوف التحقيق في هذا أكثر من ذلك.

Edit4:

حتى بعد أن تم تصحيح كل شيء في ISWeakkey، ولعب مع كل من إزالة الصور الأصلية وتوليد الصور الأصلية (X.ني.dll) من mscorlib.dll باستخدام "ngen.exe"، أحصل على نفس الاستثناء. يجب الإشارة إلى أنه حتى بعد إلغاء تثبيت صور MSCorlib الأصلية، لا يزال يستخدم mscorlib.ni.dll ... مه.

أستسلم. آمل أن يكون شخص ما قادرا على الإجابة ما يجري بحق الجحيم لأنني متأكد من أنني لا أعرف. :)

اكتشفت ما تحتاج إلى القيام به. لحسن الحظ، هناك طريقة تتوفر تقوم بإنشاء icryptotranforms التي لا تحقق من مفاتيح ضعيفة. تحتاج أيضا إلى مراقبة الفصل الأساسي كما يفعل أيضا الشيكات المعنية. عبر التفكير ببساطة اتصل بطريقة _NewEncryptor (تحتاج إلى القيام بتفكير بسيط، ولكن هذه هي الفكرة).

لحسن الحظ يحتوي MacTripledes على حقل ثلاث مرات، وبالتالي استدعاء من MacTripledes واستبدله عن طريق الانعكاس في المنشئين. لقد فعلت كل العمل بالنسبة لك.

لا يمكنني التحقق من إنشاء جهاز Mac الصحيح، ولكن لا يتم إلقاء أي استثناءات. علاوة على ذلك، قد ترغب في قيام Doc بتعليق الرمز والتعامل مع استثناء (فشل الانعكاس - على سبيل المثال إذا كانت الحقول / الطرق ليست موجودة) - ولكن هذا كذلك؛ لذلك لم أزعجك.

using System;
using System.Reflection;
using System.Security.Cryptography;
using System.IO;

namespace DesHack
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] key = new byte[24];
            for (int i = 0; i < key.Length; i++)
                key[i] = 0x11;

            byte[] data = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] computedMac = null;
            using (MACTripleDES mac = new MACTripleDESHack(key))
            {
                computedMac = mac.ComputeHash(data);
            }
        }
    }

    class MACTripleDESHack : MACTripleDES
    {
        TripleDES _desHack = new DesHack();

        static FieldInfo _cspField = typeof(MACTripleDES).GetField("des", BindingFlags.Instance | BindingFlags.NonPublic);

        public MACTripleDESHack()
            : base()
        {
            RewireDes();
        }

        public MACTripleDESHack(byte[] rgbKey)
            : base(rgbKey)
        {
            RewireDes();
        }

        private void RewireDes()
        {
            _cspField.SetValue(this, _desHack);
        }

    }

    class DesHack : TripleDES
    {
        TripleDESCryptoServiceProvider _backing = new TripleDESCryptoServiceProvider();

        static MethodInfo _newEncryptor;
        static object _encrypt;
        static object _decrypt;

        public override int BlockSize
        {
            get
            {
                return _backing.BlockSize;
            }
            set
            {
                _backing.BlockSize = value;
            }
        }

        public override int FeedbackSize
        {
            get
            {
                return _backing.FeedbackSize;
            }
            set
            {
                _backing.FeedbackSize = value;
            }
        }

        // For these two we ALSO need to avoid
        // the base class - it also checks
        // for weak keys.
        private byte[] _iv;
        public override byte[] IV
        {
            get
            {
                return _iv;
            }
            set
            {
                _iv = value;
            }
        }

        private byte[] _key;
        public override byte[] Key
        {
            get
            {
                return _key;
            }
            set
            {
                _key = value;
            }
        }

        public override int KeySize
        {
            get
            {
                return _backing.KeySize;
            }
            set
            {
                _backing.KeySize = value;
            }
        }

        public override KeySizes[] LegalBlockSizes
        {
            get
            {
                return _backing.LegalBlockSizes;
            }
        }

        public override KeySizes[] LegalKeySizes
        {
            get
            {
                return _backing.LegalKeySizes;
            }
        }

        public override CipherMode Mode
        {
            get
            {
                return _backing.Mode;
            }
            set
            {
                _backing.Mode = value;
            }
        }

        public override PaddingMode Padding
        {
            get
            {
                return _backing.Padding;
            }
            set
            {
                _backing.Padding = value;
            }
        }


        static DesHack()
        {
            _encrypt = typeof(object).Assembly.GetType("System.Security.Cryptography.CryptoAPITransformMode").GetField("Encrypt").GetValue(null);
            _decrypt = typeof(object).Assembly.GetType("System.Security.Cryptography.CryptoAPITransformMode").GetField("Decrypt").GetValue(null);
            _newEncryptor = typeof(TripleDESCryptoServiceProvider).GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance);
        }

        public DesHack()
        {            
        }

        public override ICryptoTransform CreateDecryptor()
        {
            return CreateDecryptor(_key, _iv);
        }

        public override ICryptoTransform CreateEncryptor()
        {
            return CreateEncryptor(_key, _iv);
        }

        public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)
        {
            // return this._NewEncryptor(rgbKey, base.ModeValue, rgbIV, base.FeedbackSizeValue, CryptoAPITransformMode.Decrypt);
            return (ICryptoTransform) _newEncryptor.Invoke(_backing,
                new object[] { rgbKey, ModeValue, rgbIV, FeedbackSizeValue, _decrypt });
        }

        public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)
        {
            // return this._NewEncryptor(rgbKey, base.ModeValue, rgbIV, base.FeedbackSizeValue, CryptoAPITransformMode.Encrypt);
            return (ICryptoTransform) _newEncryptor.Invoke(_backing,
                new object[] { rgbKey, ModeValue, rgbIV, FeedbackSizeValue, _encrypt });
        }

        public override void GenerateIV()
        {
            _backing.GenerateIV();
        }

        public override void GenerateKey()
        {
            _backing.GenerateKey();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
                ((IDisposable) _backing).Dispose();
            base.Dispose(disposing);
        }
    }
}

لسوء الحظ، لا يمكن تجاوز السلوك.

هناك اقتراح كبير باستخدام انعكاس في منتديات MSDN

أنا لست خبيرا أمنيا، لكنني لن Xoring المفتاح الخاص بك مع قيمة أخرى تكون كافية لإرضاء التحقق من العقل؟ يمكنك القيام بذلك لإصدار Debug الخاص بك (مع IFDEF المناسبة) حتى تتمكن من إجراء فحص مناسب وإزالته لإصدار الإصدار أو الإنتاج حيث يكون المفتاح قويا بما فيه الكفاية.

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

لقد تلقيت هذه المشكلة وحلها مع فائدة بسيطة للغاية يمكنني استخدامها مباشرة قبل تعيين المفتاح على CryptoServiceProvider:

private void MakeSecureKey(byte[] key)
{
    while(TripleDES.IsWeakKey(key))
    {
        var sha = SHA256Managed.Create().ComputeHash(key);
        Array.Copy(sha,key,key.Length);
    }
}

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

بسيطة للغاية (بعد النظر إلى الكود من Github)

bool ثابت tripledes.isweakkey (البايت [] RGBKEY)

لأنه ثابت - من السهل اختبار مفتاحك ضده

  1. يجب أن يكون الحجم إما 16 أو 24 بايت (؟؟؟) لماذا لا يمكنهم وضعه في الوثائق
  2. الشفرة الشفرة للحصول على عدد قليل من التكرار البسيط فقط إنشاء قيم enuogh عشوائية

انظر التعليمات البرمجية في: https://github.com/mono/mono/blob/master/mcs/class/corlib/system.security.cryptography/Tripledes.cs.

دكلم

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