TripleDES: chiave Specificata è un noto debole chiave per ‘TripleDES’ e non può essere utilizzato

Sto usando il .NET 3.0 classe System.Security.Cryptography.MACTripleDES classe per generare un valore di MAC. Purtroppo, sto lavorando con un dispositivo hardware che utilizza “1111111111111111” (hex) come una singola lunghezza chiave DES. Il System.Security.Cryptography libreria po ‘ di sanità mentale controllo sulla chiave e restituisce un’Eccezione se si tenta di utilizzare una chiave di crittografia debole.

Per esempio:

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

genera un’eccezione

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

So che questa non è una chiave di sicurezza. In produzione, il dispositivo verrà aggiornata con una nuova chiave di sicurezza. Nel frattempo, c’è un modo per inibire questa Eccezione da buttare? Forse un app.config o impostazione del registro di sistema?

Edit: La chiave potrebbe essere effettivamente 101010… a causa dell’algoritmo di forzare parità dispari. Non sono sicuro se questo è universale per l’algoritmo DES o solo un requisito nel pagamento di elaborazione del lavoro che ho fatto.

Edit 2: Daniel risposta ha seguito alcuni molto buono informazioni sull’hacking .NET. Purtroppo, non ero in grado di risolvere il mio problema con questa tecnica, ma c’è ancora qualche lettura interessante c’.

  • (Re: la vostra modifica) DES e 3DES utilizza solo i primi 7 bit di ogni byte della chiave. Il bit meno significativo di solito è usato come un bit di parità.
  • Vorrei a casa in modo. Sembra strano che qualcosa di simile a questo sarebbe stato applicato a livello di raccolta. Persone che utilizzano la crittografia deve sapere per l’utilizzo di difficile indovinare i tasti e la libreria non deve essere in esecuzione queste cose.
  • Un debole chiave in questo contesto non significa “difficile”. Significa che una chiave per la quale l’algoritmo specificato presenta alcuni degenerare comportamento che la indebolisce.
  • Circa la parità: L’ultimo bit di ogni byte non viene effettivamente utilizzato dall’algoritmo, in modo che davvero non importa. È comune l’uso di esso come un bit di parità, ma che potrebbe ogni implementazione di fare come vuole.

 

8 Replies
  1. 1

    Invece di utilizzare MACTripleDES con la chiave DES ripetuto per falso in un unico DES CBC-MAC, si potrebbe implementare CBC-MAC te in cima DESCryptoServiceProvider.

    <1111111111111111> non è un debole chiave DES.

    Questo calcola un 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;
        }
    • Questo funziona bene. Penso di essere stato solo concentrato sul MACTripleDES classe, che se avessi pensato, è molto utilizzato per Triple DES e non di singolo DES. Vorrei che non aveva preso me, un anno per me leggere la tua risposta! Avevo finito di attuazione CBC-MAC a mano.
  2. 6

    Non vorrei davvero raccomandare esso, ma si dovrebbe essere in grado di modificare il codice che controlla la presenza di chiavi deboli utilizzando Riflettore e l’Add-in ReflexIL

    edit:

    Mi dispiace, ci sono voluti un po ‘ per me per caricare il tutto nella mia Macchina Virtuale (Ubuntu) e non si vuole pasticciare con Mono.

    • Installare il ReflexIL Add-in: Visualizza -> Add-ins -> Aggiungi
    • Aprire ReflexIL: Strumenti -> ReflexIL v0.9
    • Trovare il IsWeakKey() funzione. (Si può utilizzare Ricerca: F3)
    • Due funzioni di venire, di doubleclick per il Sistema.Di sicurezza.Crittografia.TripleDES
    • ReflexIL dovrebbe venire troppo. Nelle Istruzioni della scheda, scorrere tutta la strada fino alla linea 29 (offset 63).
    • Cambiare ldc.i4.1 di ldc.i4.0, questo significa che la funzione restituisce sempre false.

    In assembly riquadro (a sinistra), è ora possibile scorrere verso l’alto e fare clic su “Common Language Runtime Library”, il ReflexIL riquadro vi darà un’opzione per salvarlo.

    Note importanti:

    • Eseguire il BACKUP originale assieme! (mscorlib.dll)
    • mscorlib.dll è un assembly firmato e sarà necessario il .NET SDK (sn.exe strumento) per ReflexIL per farlo saltare la verifica. Ho appena controllato il manuale, si dovrebbe già avere questo con Visual C# installato. Basta cliccare su “Registra per l’omissione della verifica (su questo computer)” quando gli viene chiesto.
    • Non credo di dire di usare solo questo sul computer di sviluppo 🙂

    Buona fortuna! Se avete bisogno di ulteriori istruzioni, sentitevi liberi di utilizzare il commentbox.

    edit2:

    Sono confuso!

    TripleDES: chiave Specificata è un noto debole chiave per 'TripleDES' e non può essere utilizzato

    Ho rimosso completamente il IsWeakKey controllare dal set_Key funzione in mscorlib assemblea. Sono assolutamente certo che ho modificato il corretto funzionamento, e che l’ho fatto correttamente. Riflettore del disassembler non visualizza più il controllo. La cosa divertente è, però, che Visual C# ancora butta la stessa eccezione.

    Questo mi porta a credere che mscorlib deve in qualche modo essere ancora in cache da qualche parte. Tuttavia, la ridenominazione mscorlib.dll per mscorlib.dll_ porta MSVC# in crash, quindi deve ancora essere dipendenti la dll originale.

    Questo è abbastanza interessante, ma credo di aver raggiunto il punto in cui non ho idea di cosa sta succedendo, semplicemente non ha alcun senso! Vedi immagine allegata. 🙁

    edit3:

    Ho notato che nella Olly, che, a differenza di gruppi come mscoree, mscorsec e mscorwks; mscorlib.dll non è in realtà si trova in:
    c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\

    Ma, invece, in quello che sembra essere un inesistente posizione:
    C:\WINDOWS\assembly\NativeImages_v2.0.50727_32\mscorlib\6d667f19d687361886990f3ca0f49816\mscorlib.ni.dll

    Penso che mi manca qualcosa qui 🙂 per indagare ancora un po’.

    edit4:

    Anche dopo aver patchato il TUTTO in IsWeakKey, e suonato in giro con sia per la rimozione e la generazione di nuove immagini native (x.ni.dll) di mscorlib.dll utilizzando “ngen.exe” io sono sempre la stessa eccezione. Devo essere notato che, anche dopo aver disinstallato il nativo mscorlib immagini, è ancora utilizzando mscorlib.ni.dll… Meh.

    Mi arrendo. Spero che qualcuno sarà in grado di rispondere a ciò che il diavolo sta succedendo, perché io di sicuro non lo so. 🙂

    • Piuttosto interessante soluzione! Ho patchato il mio mscorlib.dll ma non c’è nessun cambiamento nel comportamento della funzione. È presente nella cache della dll da qualche parte? Tutto sto cambiando ….\Microsoft.NET\Framework\v2.0.50737\mscorlib.dll.
    • Ho appena provato il codice, hai ragione. Voglio indagare e riferire 🙂
    • Questo è strano per non dire altro. Ora ho modificato l’attuale IsWeakKey controllare set_Key(), e si sta facendo la stessa cosa. Deve essere memorizzato nella cache da qualche parte. Mi deve indagare alcuni di più 🙂
    • Io non sono a conoscenza di questa porzione .NET interne. Ho pensato C:\WINDOWS\assembly era il luogo dove gli assembly nella global assembly cache vissuto. Utilizzo di Process Explorer, vedo che la mia app ha un handle aperto mscorlib.ni.dll. C’è un vecchio blog blogs.msdn.com/junfeng/archive/2004/11/11/256122.aspx..
    • Sì, sì, sì. L’utilizzo di un immagine nativa di mscorlib.dll che può essere generato utilizzando il ngen.exe strumento (ngen.exe installare mscorlib.dll). La prima volta che si esegue non dirò l’immagine nativa è già aggiornato. (che non è). Anche quando si rimuove l’immagine nativa di caricare mscorlib.ni.dll.
    • E la disinstallazione, e poi cercando di installare mscorlib.dll (modificato dal riflettore) alla fine mi dà gli stessi risultati.. viene generata Un’eccezione, anche se tale controllo è stato completamente tolto.
    • Sono abbastanza sicuro che il sottostante CryptoAPI di attuazione impone la debole chiave di restrizione, troppo. Così di patch advapi32.dll anche (che non mi raccomando).
    • secondo il debugger, l’eccezione viene generata dal Sistema.Di sicurezza.Crittografia.TripleDES.set_Key… io non sono a conoscenza .NETTE interne di me (inferno, io non ho mai toccato C#/VB/ASP), quindi scusa se ti chiedo perché considerando quanto sopra, l’eccezione è ancora gettato da quella posizione?
    • Se l’eccezione viene generata da set_Key, poi si sono probabilmente giusto che il problema è ancora causato dal .NET IsWeakKey()-controllo. Il mio commento era più al punto che, anche se hai il codice per utilizzare il patch assemblea, il codice di esito ancora negativo quando ha raggiunto la CryptoAPI chiamata.
    • Ah sì. Non vorrei davvero conoscere che, per essere onesti. 🙂 Credo che questa era ancora qualcosa di interessante da fare, purtroppo non potevo rispondere compiutamente David questione.
    • Apprezzo lo sforzo che mettete in questo. Penso che sarà sufficiente utilizzare l’open source, non gestito crypto biblioteche e di interoperabilità in esso. Il Riflettore strumento è abbastanza interessante (e spaventoso? Forse dovrei iniziare a correre il obfuscator dopo tutto…)
    • Ancora una volta devo notare che io non sono molto familiare con l’ .NET framework, ma ‘dotfuscator’ (fornito di default in MSVS credo?) solo offuscare classe-nomi di funzione-nomi di variabile nomi, eccetera. Detto questo, anche con il 3 ° partito obfuscators è una questione di tempo prima che il tuo codice è invertito
    • Io l’ho guardato prima di postare che non era possibile (credo che dovrebbe avere dichiarato: “senza la modifica del sistema di assemblee”). L’eccezione viene generata nel TripleDESCryptoServiceProvider classe immediatamente prima di chiamare il suo privato _NewEncryptor (o qualcosa di simile), di metodo, di conseguenza, in mancanza di set_Key

  3. 4

    Ho scoperto che cosa dovete fare. Fortunatamente c’è un metodo che disponibili che crea il ICryptoTranforms che non controlla chiavi deboli. È inoltre necessario guardare fuori per la classe di base come anche controlli di integrità. Attraverso la riflessione è sufficiente chiamare il _NewEncryptor metodo (è necessario fare un po ‘ di riflessione in più, ma l’idea).

    Per fortuna il MACTripleDES un campo di tipo TripleDES, in modo che derivano da MACTripleDES e sostituirlo via di riflessione nella classifica costruttori. Ho fatto tutto il lavoro per voi.

    Non riesco a verificare il corretto che il MAC è generato, ma non vengono generate eccezioni. Inoltre, si potrebbe desiderare di doc commentare il codice e non la gestione delle eccezioni (la riflessione guasti – ad esempio, se i campi/metodi non ci sono), ma questo è COSÌ, quindi non mi sono preoccupato.

    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);
            }
        }
    }
  4. 0

    Io non sono un esperto di sicurezza, ma non uno xor tra la chiave con un altro valore di essere in grado di soddisfare il test di sanità mentale? Si potrebbe fare questo per la tua versione di debug (con la giusta IFDEF) così si può fare un corretto controllo e rimuovere per il rilascio o la versione di produzione in cui la chiave dovrebbe essere abbastanza forte.

    • Che sarebbe davvero soddisfare il test di sanità mentale, ma l’hardware del dispositivo lavora con sarebbe ancora utilizzando la chiave originale.
    • Sì, sì, sì. Ho solo pensato che. Stavo solo pensando dal punto di vista del codice e non prendono nemmeno in considerazione l’hardware. Il Mio Male 🙂
  5. -1

    La riflessione soluzioni a base di farti risolvere il problema, ma sono sporchi e male. Nessuno ha ancora menzionato un metodo molto utile: TripleDES.IsWeakKey

    Ho avuto questo problema e risolto con una utility molto semplice che io uso immediatamente prima di impostare la Chiave sul mio CryptoServiceProvider:

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

    Se lo si può chiamare in qualsiasi momento fare una crittografia o decryptor, dovrebbe evitare l’incidente e di fornire una chiave di sicurezza.

    • Questo non so se è per interagire con un dispositivo che richiede una chiave specifica.
    • Sono abbastanza fiera. Ho pensato di aggiungere qui fin dalla sua il numero uno di google colpito per errore, e potrebbe essere utile a qualcuno in maniera leggermente diversa la situazione.
  6. -1

    Abbastanza semplice (Dopo aver guardato il codice da GitHub)

    static bool TripleDES.IsWeakKey(Byte[] rgbKey)

    Dal momento che è statico, è facile di testare la vostra chiave contro

    1. Dimensione deve essere di 16 o 24 byte (???)
      Perché non hanno messo la documentazione
    2. Il codice di controllo per un paio di semplici ripetizioni
      Basta creare casuale enuogh valori

    Vedere codice: https://github.com/mono/mono/blob/master/mcs/class/corlib/System.Security.Cryptography/TripleDES.cs

    Dekel

Lascia un commento