TripleDES:Der angegebene Schlüssel ist ein bekanntermaßen schwacher Schlüssel für „TripleDES“ und kann nicht verwendet werden

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

Frage

Ich verwende die .NET 3.0-Klasse System.Security.Cryptography.MACTripleDES Klasse, um einen MAC-Wert zu generieren.Leider arbeite ich mit einem Hardwaregerät, das „1111111111111111" (als Hex) als DES-Schlüssel einfacher Länge.Der System.Security.Cryptography Die Bibliothek führt eine Plausibilitätsprüfung des Schlüssels durch und gibt eine Ausnahme zurück, wenn Sie versuchen, einen kryptografisch schwachen Schlüssel zu verwenden.

Zum Beispiel:

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);
}

löst eine Ausnahme aus

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

Ich weiß, dass dies kein sicherer Schlüssel ist.In der Produktion wird das Gerät mit einem neuen, sicheren Schlüssel geflasht.Gibt es in der Zwischenzeit eine Möglichkeit, das Auslösen dieser Ausnahme zu verhindern?Vielleicht ein app.config oder Registry-Einstellung?

Bearbeiten:Der Schlüssel wäre eigentlich 101010...aufgrund des Algorithmus, der eine ungerade Parität erzwingt.Ich bin mir nicht sicher, ob dies universell für den DES-Algorithmus gilt oder nur eine Anforderung bei der Zahlungsabwicklung, die ich erledige.

Bearbeiten 2:Daniels Antwort unten enthält einige sehr gute Informationen zum Hacken von .NET.Leider konnte ich mein Problem mit dieser Technik nicht lösen, aber es gibt trotzdem einige interessante Lektüre dazu.

War es hilfreich?

Lösung

Statt MACTripleDES mit dem DES-Schlüssel wiederholt zu fälschen einem einzigen DES CBC-MAC verwenden, können Sie nur CBC-MAC, dich oben auf DESCryptoServiceProvider .

<1111111111111111> ist kein schwacher DES-Schlüssel.

Dies wird eine DES CBC-MAC berechnen:

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;
    }

Andere Tipps

Ich würde es nicht wirklich empfehlen, aber Sie sollten in der Lage sein, den IL-Code zu ändern, der nach schwachen Schlüsseln sucht Reflektor und das Add-in ReflexIL

bearbeiten:

Tut mir leid, es hat eine Weile gedauert, bis ich alles in meine virtuelle Maschine (mit Ubuntu) geladen habe, und ich wollte mich nicht mit Mono anlegen.

  • Installieren Sie das ReflexIL-Add-in:Ansicht -> Add-Ins -> Hinzufügen
  • Offenes ReflexIL:Extras -> ReflexIL v0.9
  • Suchen Sie die Funktion IsWeakKey().(Sie können die Suche verwenden:F3)
  • Es werden zwei Funktionen angezeigt. Doppelklicken Sie auf die Funktion in System.Security.Cryptography.TripleDES
  • ReflexIL hätte auch auftauchen sollen.Scrollen Sie auf der Registerkarte „Anweisungen“ ganz nach unten bis zur Zeile 29 (Versatz 63).
  • Ändern Sie ldc.i4.1 in ldc.i4.0, das bedeutet, dass die Funktion immer false zurückgibt.

In Ihrem Assemblies-Bereich (links) können Sie nun nach oben scrollen und auf „Common Language Runtime Library“ klicken. Im ReflexIL-Bereich haben Sie die Möglichkeit, sie zu speichern.

Wichtige Notizen:

  • Sichern Sie zuerst Ihre Originalbaugruppe!(mscorlib.dll)
  • mscorlib.dll ist eine signierte Assembly und Sie benötigen das .NET SDK (sn.exe-Tool) für ReflexIL, damit die Überprüfung übersprungen wird.Ich habe das gerade selbst überprüft. Sie sollten es bereits mit installiertem Visual C# haben.Klicken Sie einfach auf „Zum Überspringen der Verifizierung registrieren (auf diesem Computer)“, wenn Sie dazu aufgefordert werden.
  • Ich glaube nicht, dass ich Ihnen sagen muss, dass Sie dies nur auf Ihrem Entwicklungscomputer verwenden sollen :)

Viel Glück!Wenn Sie weitere Anleitungen benötigen, nutzen Sie gerne das Kommentarfeld.

edit2:

Ich bin verwirrt!

Ich habe die IsWeakKey-Prüfung vollständig aus der Funktion set_Key in der mscorlib-Assembly entfernt.Ich bin absolut sicher, dass ich die richtige Funktion geändert und richtig gemacht habe.Der Disassembler von Reflector zeigt den Scheck nicht mehr an.Das Lustige ist jedoch, dass Visual C# immer noch dieselbe Ausnahme auslöst.

Dies lässt mich glauben, dass mscorlib irgendwie noch irgendwo zwischengespeichert sein muss.Das Umbenennen von mscorlib.dll in mscorlib.dll_ führt jedoch zum Absturz von MSVC#, sodass es weiterhin von der ursprünglichen DLL abhängig sein muss.

Das ist ziemlich interessantes Zeug, aber ich glaube, ich bin an einem Punkt angelangt, an dem ich keine Ahnung mehr habe, was los ist, es ergibt einfach keinen Sinn mehr!Siehe beigefügtes Bild.:(

edit3:

Mir fällt bei Olly auf, dass im Gegensatz zu Assemblys wie mscoree, mscorsec und mscorwks;mscorlib.dll befindet sich tatsächlich nicht in:c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\

Sondern an einem scheinbar nicht existierenden Ort:C:\WINDOWS\assembly ativeImages_v2.0.50727_32\mscorlib\6d667f19d687361886990f3ca0f49816\mscorlib.ni.dll

Ich glaube, ich übersehe hier etwas :) Ich werde das noch genauer untersuchen.

edit4:

Auch nachdem ich ALLES in IsWeakKey gepatcht und mit dem Entfernen und Generieren neuer nativer Images (x.ni.dll) von mscorlib.dll mit „ngen.exe“ zu öffnen, erhalte ich die gleiche Ausnahme.Ich muss beachten, dass auch nach der Deinstallation der nativen mscorlib-Images immer noch mscorlib.ni.dll verwendet wird ...Meh.

Ich gebe auf.Ich hoffe, jemand kann antworten, was zum Teufel los ist, denn ich weiß es ganz sicher nicht.:) :)

Ich habe herausgefunden, was Sie tun müssen.Glücklicherweise gibt es eine Methode, die ICryptoTransforms erstellt, die nicht nach schwachen Schlüsseln sucht.Sie müssen auch auf die Basisklasse achten, da diese auch Plausibilitätsprüfungen durchführt.Rufen Sie über die Reflektion einfach die _NewEncryptor-Methode auf (Sie müssen etwas mehr Reflektion durchführen, aber das ist die Idee).

Glücklicherweise verfügt MACTripleDES über ein Feld vom Typ TripleDES. Leiten Sie also von MACTripleDES ab und ersetzen Sie es durch Reflektion in den Konstruktoren.Ich habe die ganze Arbeit für Sie erledigt.

Ich kann nicht überprüfen, ob der richtige MAC generiert wird, aber es werden keine Ausnahmen ausgelöst.Darüber hinaus möchten Sie möglicherweise den Code dokumentieren und eine Ausnahmebehandlung durchführen (Reflexionsfehler – z. B.wenn die Felder/Methoden nicht vorhanden sind) - aber das ist SO;also habe ich mich nicht darum gekümmert.

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);
        }
    }
}

Leider kann das Verhalten nicht außer Kraft gesetzt werden.

Es gibt einen großen Vorschlag Reflexion in den MSDN-Foren

Ich bin kein Sicherheitsexperte, sondern würde Ihre Schlüssel mit einem anderen Wert nicht XORing genug sein, um die Plausibilitätsprüfung zu befriedigen? Man könnte dies für Ihre Debug-Version tun (mit dem richtigen IFDEF), so können Sie die richtige Kontrolle tun und es für Ihre Freigabe oder Produktionsversion entfernen, wo der Schlüssel stark genug sein würde.

Die Reflexion basierte Lösungen erhalten Sie das Problem, aber sie sind schmutzig und böse ist. Bisher hat noch niemand eine sehr nützliche Methode: TripleDES.IsWeakKey

Ich habe dieses Problem habe und löste es mit einem sehr einfachen Programm, das ich sofort verwenden, bevor ich den Schlüssel auf meinem Cryptoserviceprovider setzen:

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

Wenn Sie es jederzeit anrufen Sie einen Verschlüssler oder Entschlüsselungsvorrichtung machen, sollten sie den Absturz verhindern und geben Sie immer einen sicheren Schlüssel.

Ganz einfach (Nach dem Code von GitHub suchen)

static bool TripleDES.IsWeakKey (Byte [] rgbKey)

Da es sich statisch - es einfach ist Ihr Schlüssel dagegen zu testen

  1. Größe muss entweder 16 oder 24 Bytes sein (???) Warum können sie es nicht in der Dokumentation setzen
  2. Die Codeprüfung für einige einfache Wiederholungen Erstellen Sie einfach zufällig enuogh Werte

Siehe Code an: https://github.com/mono/mono/blob/master/mcs/class/corlib/System.Security.Cryptography/TripleDES.cs

Dekel

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top