Lezioni apprese e idee sbagliate riguardanti la crittografia e la crittologia

La crittologia è un argomento così vasto che persino i programmatori esperti commettono quasi sempre errori le prime volte. Tuttavia la crittografia è un argomento così importante, spesso non possiamo permetterci di avere questi errori.

L'intento di questa domanda è identificare ed elencare ciò che non fare con un dato algoritmo o API. In questo modo possiamo imparare dalle esperienze degli altri e prevenire la diffusione di cattive pratiche.

Per mantenere questa domanda costruttiva, per favore

  1. Includere un esempio "errato"
  2. Spiega cosa c'è di sbagliato in quell'esempio
  3. Fornire un'implementazione corretta (se applicabile).
  4. Per il meglio delle tue possibilità, fornisci i riferimenti ai punti 2 e 3 sopra.
posta random65537 19.02.2011 - 20:25
fonte

21 risposta

Non eseguire il rollpoint della tua crittografia.

Non inventare il proprio algoritmo o protocollo di crittografia; questo è estremamente soggetto a errori. Come ama dire Bruce Schneier,

"Anyone can invent an encryption algorithm they themselves can't break; it's much harder to invent one that no one else can break".

Gli algoritmi di crittografia sono molto complessi e richiedono un'intensa attività di controllo per essere sicuri che siano sicuri; se inventi il tuo, non lo otterrai, ed è molto facile finire con qualcosa di insicuro senza rendersene conto.

Utilizzare invece un algoritmo e un protocollo crittografico standard. Le probabilità sono che qualcun altro abbia già riscontrato il tuo problema e progettato un algoritmo appropriato a tale scopo.

Il tuo caso migliore è utilizzare uno schema ben curato di alto livello: per la sicurezza delle comunicazioni, usa TLS (o SSL); per i dati a riposo, utilizzare GPG (o PGP). Se non riesci a farlo, utilizza una libreria crittografica di alto livello, ad esempio cryptlib , GPGME, Keyczar , o NaCL , invece di uno di basso livello, come OpenSSL, CryptoAPI, JCE, ecc. Grazie a Nate Lawson per questo suggerimento.

    
risposta data 20.02.2011 - 04:52
fonte

Non utilizzare la crittografia senza l'autenticazione dei messaggi

È un errore molto comune crittografare i dati senza anche autenticarli.

Esempio: lo sviluppatore desidera mantenere un messaggio segreto, quindi crittografa il messaggio con la modalità AES-CBC. L'errore: questo non è sufficiente per la sicurezza in presenza di attacchi attivi, attacchi di replica, attacchi di reazione, ecc. Esistono noti attacchi alla crittografia senza autenticazione dei messaggi e gli attacchi possono essere piuttosto seri. La correzione è di aggiungere l'autenticazione del messaggio.

Questo errore ha comportato gravi vulnerabilità nei sistemi distribuiti che utilizzavano la crittografia senza autenticazione, tra cui ASP.NET , XML crittografia , Amazon EC2 , Facce JavaServer, Ruby on Rails, OWASP ESAPI , IPSEC , WEP , ASP.NET di nuovo e SSH2 . Non vuoi essere il prossimo in questa lista.

Per evitare questi problemi, è necessario utilizzare l'autenticazione dei messaggi ogni volta che si applica la crittografia. Hai due scelte su come farlo:

  • Probabilmente la soluzione più semplice è utilizzare uno schema di crittografia che fornisce crittografia autenticata , ad es., GCM, CWC, EAX, CCM, OCB. (Vedi anche: 1 .) Lo schema di crittografia autenticato gestisce questo per te, quindi non hai a pensarci.

  • In alternativa, puoi applicare l'autenticazione del tuo messaggio, come segue. In primo luogo, crittografare il messaggio utilizzando uno schema di crittografia a chiave simmetrica appropriato (ad esempio, AES-CBC). Quindi, prendere l'intero testo cifrato (compresi eventuali IV, non-valori o altri valori necessari per la decrittografia), applicare un codice di autenticazione del messaggio (ad esempio, AES-CMAC, SHA1-HMAC, SHA256-HMAC) e aggiungere il digest MAC risultante al testo cifrato prima della trasmissione. Dal lato ricevente, controlla che il digest MAC sia valido prima di decodificare. Questo è noto come la costruzione di cifrare e quindi autenticare. (Vedi anche: 1 , 2 .) Anche questo funziona bene, ma richiede un po 'più di attenzione da parte tua.

risposta data 20.02.2011 - 04:36
fonte

Fai attenzione quando concateni più stringhe, prima dell'hashing.

Un errore a volte vedo: le persone vogliono un hash delle stringhe S e T. Le concatenano per ottenere una singola stringa S || T, poi l'hash per ottenere H (S || T). Questo è difettoso.

Il problema: la concatenazione lascia ambiguo il confine tra le due stringhe. Esempio: builtin || securely = built || insecurely . In altre parole, l'hash H (S || T) non identifica in modo univoco le stringhe S e T. Pertanto, l'attaccante potrebbe essere in grado di modificare il limite tra le due stringhe, senza modificare l'hash. Ad esempio, se Alice volesse inviare le due stringhe builtin e securely , l'utente malintenzionato potrebbe cambiarle nelle due stringhe built e insecurely senza invalidare l'hash.

Problemi simili si applicano quando si applica una firma digitale o un codice di autenticazione del messaggio a una concatenazione di stringhe.

La correzione: anziché una semplice concatenazione, usa una codifica che è decifrabile in modo inequivocabile. Ad esempio, invece di calcolare H (S || T), è possibile calcolare H (length (S) || S || T), dove length (S) è un valore a 32 bit che denota la lunghezza di S in byte. Oppure, un'altra possibilità è usare H (H (S) || H (T)), o anche H (H (S) || T).

Per un esempio reale di questo difetto, vedi questo difetto in Amazon Web Services o questo difetto in Flickr [pdf].

    
risposta data 20.02.2011 - 06:29
fonte

Assicurati di generare generatori di numeri casuali con sufficiente entropia.

Assicurati di utilizzare generatori di numeri pseudocasuali di crittografia per cose come generare chiavi, scegliere IV / nonce, ecc. Non utilizzare rand() , random() , drand48() , ecc.

Assicurati di seminare il generatore di numeri pseudocasuali con sufficiente entropia. Non seminarlo con l'ora del giorno; è probabile.

Esempi: srand(time(NULL)) è pessimo. Un buon modo per inizializzare il tuo PRNG è di afferrare 128 bit o numeri true-random, ad es. Da /dev/urandom , CryptGenRandom o simili. In Java, usa SecureRandom, non Random. In .NET, utilizzare System.Security.Cryptography.RandomNumberGenerator, non System.Random. In Python, usa random.SystemRandom, non casuale. Grazie a Nate Lawson per alcuni esempi.

Esempio di mondo reale: vedi questo difetto nelle prime versioni del browser di Netscape , che ha permesso a un utente malintenzionato di interrompere SSL.

    
risposta data 20.02.2011 - 05:06
fonte

Non riutilizzare nonces o IV

Molte modalità di funzionamento richiedono una IV (Vettore di inizializzazione). Non devi mai riutilizzare lo stesso valore per un IV due volte; così facendo puoi annullare tutte le garanzie di sicurezza e causare una catastrofica violazione della sicurezza.

  • Per le modalità operative di cifratura in streaming, come la modalità CTR o la modalità OFB, riutilizzare una IV è un disastro di sicurezza. Può far sì che i messaggi crittografati siano banalmente recuperabili.

  • Per altri modi operativi, come la modalità CBC, riutilizzare una IV può anche facilitare in alcuni casi attacchi di ripristino del testo normale.

Indipendentemente dalla modalità di utilizzo che usi, non dovresti riutilizzare la IV. Se ti stai chiedendo come farlo nel modo giusto, la specifica NIST fornisce informazioni dettagliate documentazione su come utilizzare correttamente le modalità di cifratura a blocchi.

Il progetto Tarsnap fornisce un buon esempio di questa trappola. Tarsnap crittografa i dati di backup dividendolo in blocchi e quindi crittografando ogni blocco con AES in modalità CTR. Nelle versioni dalla 1.0.22 alla 1.0.27 di Tarsnap, lo stesso IV è stato inavvertitamente riutilizzato, consentendo il ripristino del testo normale.

Come è successo? Per semplificare il codice di Tarsnap - e nella speranza di ridurre il potenziale di bug - Colin Percival ha colto l'opportunità di "refactoring" del codice AES-CTR in un nuovo file (lib / crypto / crypto_aesctr.c nel codice sorgente di Tarsnap ) e modificato i luoghi esistenti in cui è stato utilizzato AES-CTR per trarre vantaggio da queste routine. Il nuovo codice ha questo aspetto:

        /* Encrypt the data. */
-       aes_ctr(&encr_aes->key, encr_aes->nonce++, buf, len,
-           filebuf + CRYPTO_FILE_HLEN);
+       if ((stream =
+           crypto_aesctr_init(&encr_aes->key, encr_aes->nonce)) == NULL)
+               goto err0;
+       crypto_aesctr_stream(stream, buf, filebuf + CRYPTO_FILE_HLEN, len);
+       crypto_aesctr_free(stream);

Durante il refactoring, encr_aes->nonce++ è stato convertito inavvertitamente in encr_aes->nonce e di conseguenza lo stesso valore nonce è stato usato ripetutamente . In particolare, il valore nonce CTR non viene incrementato dopo che ciascun blocco è stato crittografato. (Il contatore CTR viene incrementato correttamente dopo l'elaborazione di ogni 16 byte di dati, ma questo contatore viene azzerato per ogni nuovo blocco.) I dettagli completi sono descritti da Colin Percival in: link

    
risposta data 19.02.2011 - 21:11
fonte

Non utilizzare la stessa chiave per la crittografia e l'autenticazione. Non utilizzare la stessa chiave per la crittografia e la firma.

Una chiave non deve essere riutilizzata per più scopi; questo potrebbe aprire vari attacchi sottili.

Ad esempio, se hai una coppia di chiavi pubbliche / private RSA, non dovresti usarla per la crittografia (crittografare con la chiave pubblica, decifrare con la chiave privata) e per firmare (firmare con la chiave privata, verificare con la chiave pubblica): scegli un singolo scopo e usalo per un solo scopo. Se hai bisogno di entrambe le abilità, genera due coppie di chiavi, una per la firma e una per la crittografia / decrittografia.

Allo stesso modo, con la crittografia simmetrica, è necessario utilizzare una chiave per la crittografia e una chiave indipendente separata per l'autenticazione dei messaggi. Non riutilizzare la stessa chiave per entrambi gli scopi.

    
risposta data 20.02.2011 - 04:50
fonte

Non utilizzare un codice di blocco con ECB per la crittografia simmetrica

(Si applica a AES, 3DES, ...)

Ecco un post e molto simile < a href="http://support.microsoft.com/kb/317535"> Articolo di Microsoft KB su come la modalità ECB produce codice non crittografato.

Vedi anche questo post simile da Rook

Messaggio di testo normale:

LostessomessaggiocrittografatoconlamodalitàECB(nonimportaqualecifrausi):

Lo stesso messaggio ESATTO usando la modalità CBC (di nuovo, non importa quale cifra usi):

Laviasbagliata

publicstaticstringEncrypt(stringtoEncrypt,stringkey,booluseHashing){byte[]keyArray=UTF8Encoding.UTF8.GetBytes(key);byte[]toEncryptArray=UTF8Encoding.UTF8.GetBytes(toEncrypt);if(useHashing)keyArray=newMD5CryptoServiceProvider().ComputeHash(keyArray);vartdes=newTripleDESCryptoServiceProvider(){Key=keyArray,Mode=CipherMode.ECB,Padding=PaddingMode.PKCS7};ICryptoTransformcTransform=tdes.CreateEncryptor();byte[]resultArray=cTransform.TransformFinalBlock(toEncryptArray,0,toEncryptArray.Length);returnConvert.ToBase64String(resultArray,0,resultArray.Length);}

L'erroreènellarigaseguente

{Key=keyArray,Modalità=CipherMode.ECB,Padding=PaddingMode.PKCS7};

Laviagiusta

IbraviragazzidiMicrosoftmihannoinviatoilseguentecodicepercorreggerel'articolodellaKnowledgeBasecollegatoinprecedenza.Questoèriferitonelcaso#111021973179005

QuestocodicediesempioutilizzaAESpercrittografareidatielachiaveperlacrittografiaAESèilcodicehashgeneratodaSHA256.AESèl'algoritmoAdvancedEncryptionStandard(AES).L'algoritmoAESèbasatosupermutazioniesostituzioni.Lepermutazionisonoriarrangiamentideidatielesostituzionisostituisconoun'unitàdidaticonun'altra.AESeseguepermutazioniesostituzioniusandodiversetecnichediverse.PerulterioridettaglisuAES,consultarel'articolo"Proteggi i tuoi dati con il nuovo standard avanzato di crittografia" su MSDN Magazine all'indirizzo link .

SHA è Secure Hash Algorithm. SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512) è ora raccomandato. Per informazioni più dettagliate sui valori hash in .NET Framework, fai riferimento al link .

Il valore predefinito della modalità per l'operazione dell'algoritmo simmetrico per AesCryptoServiceProvider è CBC. CBC è la modalità Cipher Block Chaining. Introduce feedback. Prima che ogni blocco di testo normale sia crittografato, viene combinato con il testo cifrato del blocco precedente mediante un'operazione OR esclusiva bit a bit. Ciò garantisce che, anche se il testo semplice contiene molti blocchi identici, verranno crittografati ciascuno in un diverso blocco di testo cifrato. Il vettore di inizializzazione è combinato con il primo blocco di testo normale mediante un'operazione OR esclusiva per bit prima che il blocco venga crittografato. Se un singolo bit del blocco di testo cifrato viene manomesso, anche il corrispondente blocco di testo in chiaro viene alterato. Inoltre, un pezzettino nel blocco successivo, nella stessa posizione del morso storpiato, verrà distrutto. Per informazioni più dettagliate su CipherMode , fai riferimento a link .

Ecco il codice di esempio.

// This function is used for encrypting the data with key and iv.
byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
    // Create an AESCryptoProvider.
    using (var aesCryptoProvider = new AesCryptoServiceProvider())
    {
        // Initialize the AESCryptoProvider with key and iv.
        aesCryptoProvider.KeySize = key.Length * 8;
        aesCryptoProvider.IV = iv;
        aesCryptoProvider.Key = key;

        // Create encryptor from the AESCryptoProvider.
        using (ICryptoTransform encryptor = aesCryptoProvider.CreateEncryptor())
        {
            // Create memory stream to store the encrypted data.
            using (MemoryStream stream = new MemoryStream())
            {
                // Create a CryptoStream to encrypt the data.
                using (CryptoStream cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
                    // Encrypt the data.
                    cryptoStream.Write(data, 0, data.Length);

                // return the encrypted data.
                return stream.ToArray();
            }
        }
    }
}

// This function is used for decrypting the data with key and iv.
byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
    // Create an AESCryptoServiceProvider.
    using (var aesCryptoProvider = new AesCryptoServiceProvider())
    {
        // Initialize the AESCryptoServiceProvier with key and iv.
        aesCryptoProvider.KeySize = key.Length * 8;
        aesCryptoProvider.IV = iv;
        aesCryptoProvider.Key = key;

        // Create decryptor from the AESCryptoServiceProvider.
        using (ICryptoTransform decryptor = aesCryptoProvider.CreateDecryptor())
        {
            // Create a memory stream including the encrypted data.
            using (MemoryStream stream = new MemoryStream(data))
            {
                // Create a CryptoStream to decrypt the encrypted data.
                using (CryptoStream cryptoStream = new CryptoStream(stream, decryptor, CryptoStreamMode.Read))
                {
                    // Create a byte buffer array.
                    byte[] readData = new byte[1024];
                    int readDataCount = 0;

                    // Create a memory stream to store the decrypted data.
                    using (MemoryStream resultStream = new MemoryStream())
                    {
                        do
                        {
                            // Decrypt the data and write the data into readData buffer array.
                           readDataCount = cryptoStream.Read(readData, 0, readData.Length);
                            // Write the decrypted data to resultStream.
                            resultStream.Write(readData, 0, readDataCount);
                        }
                        // Check whether there is any more encrypted data in stream.
                        while (readDataCount > 0);
                        // Return the decrypted data.
                        return resultStream.ToArray();
                    }
                }
            }
        }
    }
}



// This function is used for generating a valid key binary with UTF8 encoding and SHA256 hash algorithm.
byte[] GetKey(string key)
{
    // Create SHA256 hash algorithm class.
    using (SHA256Managed sha256 = new SHA256Managed())

    // Decode the string key to binary and compute the hash binary of the key.
    return sha256.ComputeHash(Encoding.UTF8.GetBytes(key));
}

Per maggiori dettagli sulle classi nel codice di esempio, fai riferimento ai seguenti link:

· Classe AesCryptoServiceProvider

· SHA256Gestione gestita

· Classe CryptoStream

Inoltre, ci sono diversi articoli che possono aiutare a comprendere meglio la crittografia in .NET Framework, fare riferimento ai collegamenti seguenti:

· Servizi di crittografia

· Modello di crittografia di .NET Framework

· Una semplice guida alla crittografia

· Crittografia senza segreti

    
risposta data 23.05.2017 - 14:40
fonte

Principio di Kerckhoffs: un criptosistema dovrebbe essere sicuro anche se tutto ciò che riguarda il sistema, ad eccezione della chiave, è di dominio pubblico

Un esempio errato: Hash di LANMAN

Gli hash di LANMAN sarebbero difficili da capire se nessuno conoscesse l'algoritmo, tuttavia una volta che l'algoritmo era noto, ora è molto semplice da decifrare.

L'algoritmo è il seguente ( da wikipedia ):

  1. La password ASCII dell'utente viene convertita in maiuscolo.
  2. Questa password è completata da null a 14 byte
  3. La password "a lunghezza fissa" è divisa in due metà a sette byte.
  4. Questi valori vengono utilizzati per creare due chiavi DES, una per ogni metà di 7 byte
  5. Ciascuna delle due chiavi viene utilizzata per crittografare DES la stringa ASCII costante "KGS! @ # $%", risultante in due valori di testo cifrato a 8 byte.
  6. Questi due valori di testo cifrato sono concatenati per formare un valore di 16 byte, che è l'hash LM

Poiché ora conosci il testo cifrato di questi fatti, ora puoi facilmente rompere il testo cifrato in due testi cifrati che sai essere in maiuscolo, risultando in un insieme limitato di caratteri che la password potrebbe essere.

Un esempio corretto: crittografia AES

  • Algoritmo noto
  • Bilancia con tecnologia. Aumenta la dimensione della chiave quando hai bisogno di più grinta crittografica
risposta data 25.06.2012 - 13:46
fonte

Cerca di evitare l'uso delle password come chiavi di crittografia.

Una debolezza comune in molti sistemi è l'uso di una password o frase d'accesso, o un hash di una password o frase d'accesso, come chiave di crittografia / decrittografia. Il problema è che questo tende ad essere molto suscettibile agli attacchi di ricerca di chiavi offline. La maggior parte degli utenti sceglie password che non hanno sufficiente entropia per resistere a tali attacchi.

La soluzione migliore è utilizzare una chiave di crittografia / decrittazione veramente casuale, non una generata in maniera deterministica da una password / frase di accesso.

Tuttavia, se è necessario utilizzare uno basato su una password / passphrase, utilizzare uno schema appropriato per rallentare la ricerca di chiavi esaustiva. Raccomando PBKDF2 , che usa un hashing iterativo (lungo la linea di H (H (H (... .H (password) ...)))) per rallentare la ricerca del dizionario. Disporre di un numero sufficiente di iterazioni per fare in modo che questo processo, ad esempio, sia di 100ms sul computer dell'utente per generare la chiave.

    
risposta data 20.02.2011 - 06:39
fonte

In un protocollo crittografico: Rendi riconoscibile ogni messaggio autenticato: non ci sono due messaggi che dovrebbero apparire uguali

Una generalizzazione / variante di:

  • Fai attenzione quando concateni più stringhe, prima dell'hashing.
  • Non riutilizzare le chiavi.
  • Non riutilizzare nonces.

Durante una serie di protocolli crittografici è possibile scambiare molti messaggi che non possono essere contraffatti senza un segreto (chiave o nonce). Questi messaggi possono essere verificati dal destinatario perché conosce una chiave pubblica (firma) o perché solo lui e il mittente conoscono una chiave simmetrica, o nonce. Questo assicura che questi messaggi non siano stati modificati.

Ma questo non si assicura che questi messaggi siano stati emessi durante la stessa esecuzione del protocollo: un avversario potrebbe aver catturato questi messaggi in precedenza, o durante un'esecuzione concomitante del protocollo. Un avversario può avviare molte esecuzioni concorrenti di un protocollo crittografico per acquisire messaggi validi e riutilizzarli non modificati.

Riesaminando intelligentemente i messaggi, potrebbe essere possibile attaccare un protocollo senza compromettere alcuna chiave primaria, senza attaccare nessun RNG, qualsiasi cifra, ecc.

Rendendo ogni messaggio autenticato del protocollo chiaramente distinto per il ricevitore, le opportunità di riprodurre i messaggi non modificati sono ridotte (non eliminate).

    
risposta data 28.09.2011 - 06:03
fonte

Non utilizzare la stessa chiave in entrambe le direzioni.

Nelle comunicazioni di rete, un errore comune è usare la stessa chiave per la comunicazione nella direzione A- > B come per la direzione B- > A. Questa è una cattiva idea, perché spesso consente attacchi di replay che riproducono qualcosa A inviato a B, torna ad A.

L'approccio più sicuro consiste nel negoziare due chiavi indipendenti, una per ciascuna direzione. In alternativa, puoi negoziare una singola chiave K, quindi utilizzare K1 = AES (K, 00..0) per una direzione e K2 = AES (K, 11..1) per l'altra direzione.

    
risposta data 20.02.2011 - 04:48
fonte

Non utilizzare lunghezze delle chiavi non sicure.

Assicurati di utilizzare algoritmi con un tasto sufficientemente lungo.

Per la crittografia a chiave simmetrica, consiglierei almeno una chiave a 80 bit e, se possibile, una chiave a 128 bit è una buona idea. Non utilizzare la crittografia a 40 bit; è insicuro e facilmente interrotto dai dilettanti, semplicemente provando esaustivamente ogni possibile chiave. Non utilizzare DES a 56 bit; non è banale da rompere, ma è alla portata di attaccanti dedicati a rompere il DES. Un algoritmo a 128 bit, come AES, non è sensibilmente più lento della crittografia a 40 bit, quindi non hai scuse per usare crypto crypto.

Per la crittografia a chiave pubblica, le raccomandazioni sulla lunghezza delle chiavi dipendono dall'algoritmo e dal livello di sicurezza richiesto. Inoltre, l'aumento delle dimensioni della chiave danneggia le prestazioni, quindi un massiccio overkill non è economico; quindi, ciò richiede un po 'più di pensiero rispetto alla selezione delle dimensioni delle chiavi a chiave simmetrica. Per RSA, El Gamal o Diffie-Hellman, raccomanderei che la chiave sia almeno 1024 bit, come minimo assoluto; tuttavia, le chiavi da 1024 bit sono sul bordo di ciò che potrebbe diventare crackable nel breve termine e generalmente non sono raccomandate per l'uso moderno, quindi se possibile, raccomanderei le chiavi da 1536 o anche da 2048 bit. Per la crittografia a curva ellittica, i tasti a 160 bit appaiono adeguati e le chiavi a 224 bit sono migliori. Puoi anche fare riferimento alle linee guida pubblicate che stabiliscono equivalenze approssimative tra le dimensioni delle chiavi simmetriche e a chiave pubblica .

    
risposta data 20.02.2011 - 04:44
fonte

Utilizza la modalità corretta

Allo stesso modo, non fare affidamento sulle impostazioni predefinite della libreria per essere sicuro. Nello specifico, molte librerie che implementano AES implementano l'algoritmo descritto in FIPS 197, che è la cosiddetta modalità ECB (Electronic Code Book), che è essenzialmente una semplice mappatura di:

AES(plaintext [32]byte, key [32]byte) -> ciphertext [32]byte

è molto insicuro. Il ragionamento è semplice, mentre il numero di possibili chiavi nello spazio delle chiavi è piuttosto grande, il collegamento debole qui è la quantità di entropia nel messaggio. Come sempre, xkcd.com descrive è meglio di link

È molto importante usare qualcosa come CBC (Cipher Block Chaining) che fondamentalmente rende ciphertext [i] una mappatura:

ciphertext[i] = SomeFunction(ciphertext[i-1], message[i], key)

Solo per evidenziare alcune librerie linguistiche in cui questo tipo di errore è facile da fare: link fornisce un AES implementazione che, se usata in modo ingenuo, darebbe come risultato la modalità ECB.

La libreria pycrypto imposta automaticamente la modalità ECB durante la creazione di un nuovo oggetto AES.

OpenSSL, ha ragione. Ogni chiamata AES è esplicita sulla modalità di funzionamento. La cosa più sicura IMO è semplicemente provare a non fare crypto di basso livello come questo te stesso. Se sei costretto a farlo, procedi come se stessi camminando su vetri rotti (attentamente), e cerca di assicurarti che i tuoi utenti siano giustificati a riporre la loro fiducia in te per salvaguardare i loro dati.

    
risposta data 08.09.2012 - 18:55
fonte

Non riutilizzare la stessa chiave su molti dispositivi.

Più è ampia la condivisione di una chiave crittografica, meno è probabile che sarai in grado di mantenerla segreta. Alcuni sistemi distribuiti hanno riutilizzato la stessa chiave simmetrica su ogni dispositivo del sistema. Il problema è che prima o poi qualcuno estrae la chiave da un singolo dispositivo e quindi sarà in grado di attaccare tutti gli altri dispositivi. Quindi, non farlo.

Vedi anche "Simmetric Encryption Do not # 6: Non condividere una singola chiave su molti dispositivi" in questo articolo del blog . Crediti per Matthew Green.

    
risposta data 17.10.2012 - 16:57
fonte

Un one-time pad non è un one-time pad se la chiave è allungata da un algoritmo

L'identificatore "one-time pad" (noto anche come codice Vernam) viene spesso applicato in modo errato a varie soluzioni crittografiche nel tentativo di rivendicare la sicurezza indissolubile. Ma per definizione, un codice Vernam è sicuro se e solo se sono soddisfatte tutte e tre queste condizioni:

  • Il materiale chiave è davvero imprevedibile; AND
  • Il materiale chiave ha la stessa lunghezza del testo in chiaro; AND
  • Il materiale chiave non viene mai riutilizzato.

Qualsiasi violazione di tali condizioni significa che non è più un codice a una tantum.

L'errore comune è che una chiave breve viene allungata con un algoritmo. Questa azione viola la regola dell'imprevedibilità (non importa la regola della lunghezza della chiave.) Una volta eseguita questa operazione, il blocco temporaneo viene trasformato matematicamente nell'algoritmo di estensione della chiave. La combinazione della chiave breve con i byte casuali modifica solo lo spazio di ricerca necessario per forzare la forza brusca all'algoritmo di allungamento della chiave. Allo stesso modo, l'utilizzo di byte "generati casualmente" trasforma l'algoritmo del generatore di numeri casuali nell'algoritmo di sicurezza.

Ecco un semplice esempio. Ho un messaggio che crittograferò usando un "one-time pad" che usa una funzione crittograficamente protetta come generatore di chiavi. Ho scelto una chiave segreta, quindi ho aggiunto un numero casuale per garantire che non venga riutilizzata. Poiché non sto riutilizzando la chiave, non c'è modo di attaccare il testo cifrato sottraendo un messaggio da un altro.

          plaintext : 1234567890123456789012345678901234567890
       key material : 757578fbf23ffa4d748e0800dd7c424a46feb0cc
OTP function (xor)  : ----------
         ciphertext : 67412E83622DCE1B0C1E1A348B04D25872A8C85C

Il materiale chiave è stato generato in modo sicuro utilizzando SHA-1 per cancellare la mia password segreta (più casuale) per allungarla. Ma qualsiasi attaccante che conosca l'algoritmo di stretching * usato è SHA-1, può attaccarlo provando vari input in SHA-1 e XORando l'output con il testo cifrato. Indovinare il tasto "OTP" ora non è più difficile di indovinare gli input combinati all'algoritmo crittografico. Questa proprietà è valida indipendentemente da quale algoritmo crittografico di base viene scelto, quali misure di complessità detiene, o come è implementato o seminato.

Potresti avere un ottimo algoritmo di allungamento della chiave. Potresti anche avere un generatore di numeri casuali molto sicuro. Tuttavia, il tuo algoritmo non è per definizione un blocco temporaneo e quindi non ha la proprietà unbreakable di un pad singolo.

* L'applicazione del principio di Kerckhoff significa che devi presupporre che l'attaccante possa sempre determinare gli algoritmi utilizzati.

    
risposta data 15.05.2013 - 19:04
fonte

Non fidarti degli standard.

Esistono molti standard nella crittografia e talvolta è necessario utilizzarli. Ma non dare per scontato che le persone che scrivono le norme comprendessero adeguatamente la crittografia di cui avevano bisogno. Ad esempio, EAX è stato rielaborato in uno standard di rete. EAX ha una prova di sicurezza. La versione rielaborata no.

MD5 è uno standard. Ora è rotto. Chip e PIN sono stati interrotti ripetutamente molte volte, grazie all'abbondanza di funzioni pericolose. GPG supporta ancora le chiavi DSA che sono troppo corte per il comfort. SSL ha opzioni che non dovrebbero essere usate e richiede attenzione per evitarli.

Cosa si può fare a riguardo? Stare attenti, capire i rischi noti e stare al passo con la ricerca di nuovi.

    
risposta data 08.09.2012 - 18:05
fonte

Non utilizzare una crittografia OTP o streaming nella crittografia del disco

Esempio 1

Supponiamo che due file vengano salvati usando un codice di flusso / OTP. Se il file viene nuovamente salvato dopo una modifica minore, un utente malintenzionato può vedere che solo alcuni bit sono stati modificati e dedurre informazioni sul documento. (Immagina di cambiare il saluto "Caro Bob" a "Cara Alice").

Esempio 2

Non c'è integrità nell'output: un utente malintenzionato può modificare il testo cifrato e modificare il contenuto dei dati semplicemente eseguendo XOR dei dati.

Take away: le modifiche al testo cifrato non vengono rilevate e hanno un impatto prevedibile sul testo in chiaro.

Soluzione

Utilizza un codice a blocchi per queste situazioni che include i controlli di integrità dei messaggi

    
risposta data 20.05.2013 - 17:47
fonte

Non utilizzare mai un One Time Pad (OTP) o una chiave di codifica di streaming più di una volta

Un OTP applicato due volte significa che i dati crittografati con "segretezza perfetta" saranno decodificati e in chiaro. Questo succede perché i dati sono XOR due volte.

Esempio

Supponi di riutilizzare un OTP / o stream con la stessa chiave.

Un utente malintenzionato raccoglie un sacco di dati inviati da un client a un server e XOR un insieme di due pacchetti insieme finché i due pacchetti non decrittografano a vicenda (o sottoinsieme).

La codifica ASCII ha una ridondanza sufficiente che significa che con un testo cifrato sufficiente, i messaggi originali potrebbero essere decodificati (insieme alla chiave OTP segreta).

Esempi di mondo reale

  • Progetto Verona (1941-46) per un esempio di un OTP usato dai russi e successivamente decifrato dall'agenzia di intelligence statunitense

  • PPTPv1 di Microsoft sia il client che il server crittografano i dati utilizzando la stessa chiave.

  • WEP riutilizza la stessa chiave quando vengono inviati 2 ^ 24 pacchetti o se viene ripristinata una scheda NIC. Il primo problema è dovuto al fatto che l'IV è lungo 24 bit, risultando che dopo 16 milioni di fotogrammi vengono trasmessi due tempi. Il secondo problema si verifica nelle implementazioni hardware dove, dopo un ciclo di spegnimento, l'IV si azzera, risultando in un time pad. Questo problema è facile da vedere poiché l'IV viene inviato in chiaro.

Suggerimento

  • Dovrebbe essere creata una nuova chiave per ogni sessione (ad esempio TLS).

  • Il client deve utilizzare un OTP (o stream cipher w / PRG) con il server e il server deve utilizzare una chiave diversa quando crittografa i dati sul client

  • Piuttosto che generare molte molte chiavi, è possibile espandere una singola chiave in un lungo flusso usando un PRG (supponendo che tu abbia fiducia nel PRG) e utilizzare ogni segmento di tale espansione come chiave.

  • Sappi che non tutti i PRG sono fatti per funzionare in modalità incrementale, e può essere richiesto un input casuale. (RC4 ha questo problema in modalità incrementale)

risposta data 20.05.2013 - 18:08
fonte

Utilizza processori stream moderni che funzionano in modo appropriato in Hardware o Software

Non tutti i codici di flusso sono progettati per essere implementati in hardware o software. Il registro di spostamento lineare dei feedback (LFSR) è un esempio di un codice hardware ampiamente distribuito che può essere facilmente rotto.

LFSR è usato in:

  • Codifica DVD (nota anche come CSS) 2 LFSR
  • Crittografia GSM (A5 / 1.2) 3 LSFR
  • Bluetooth (E0): 4 LFSR

L'hardware di cui sopra è ampiamente implementato e quindi difficile da aggiornare o portare a standard moderni. Tutti i precedenti sono gravemente danneggiati e non dovrebbero essere considerati attendibili per comunicazioni sicure.

Attacco:

Poiché la chiave è suddivisa in due sezioni durante la crittografia (17 bit e 25 bit) e quei bit sono usati per crittografare lo stesso testo cifrato, è possibile usare la conoscenza del formato MPEG e bruteforce una chiave a 17 bit per estrapolare cosa la chiave a 25 bit è.

Questo è appena nuovo, ma FOSS è facile da trovare che dimostra questo problema.

Soluzione:

Il progetto eStream (nel 2008) ha qualificato 5 codici di flusso che dovrebbero essere utilizzati. Una differenza notevole è che invece di usare una chiave con una IV, i cifrari usano una chiave, un nonce e un contatore. Salsa20 funziona in questo modo ed è progettato per essere utilizzato facilmente in hardware e software. In particolare, è incluso nel set di istruzioni SSE2 x86.

Oltre

I codici moderni non sono solo più sicuri, ma sono anche più veloci:

PRG          Speed (MB/sec)
RC4              126         (obsolete)
Salsa20/12       643         (modern)
Sosemaunk        727         (modern)
    
risposta data 20.05.2013 - 18:49
fonte

Non utilizzare RC4

RC4 è stato progettato nel 1987 per essere utilizzato come codice di flusso. È utilizzato in HTTPS e WEP.

Ci sono punti deboli

  1. C'è bias nell'output iniziale: Pr [2nd byte = 0] = 2/256
  2. La probabilità di sedici bit uguale a zero è 1/256 ^ 2 + 1/256 ^ 3. Ciò si verifica dopo che numerosi dati di dati sono stati crittografati.
  3. Vulnerabile ai relativi attacchi chiave, in cui solo l'IV cambia ma la chiave rimane la stessa.

Take away Se devi usare RC4, ignora i primi 256 byte perché sono di parte. Se si utilizza RC4 per le date di dati, il bias di RC4 consentirà attacchi di tutti i dati crittografati precedenti.

    
risposta data 20.05.2013 - 18:26
fonte

Usa solo MAC che non sono vulnerabili agli attacchi dell'estensione del messaggio

Un MAC è un codice hash che garantisce l'integrità del messaggio (senza modifiche, ecc.) di un dato testo normale. Molte implementazioni e standard pubblicati non riescono a proteggere un MAC da un utente malintenzionato che aggiunge ulteriori dati al MAC.

La soluzione per questo è che l'implementazione MAC utilizzi una seconda (diversa) chiave e ricodifichi l'output finale.

ECBC e NMAC sono esempi di cifrari che impediscono correttamente l'attacco all'estensione del messaggio.

Soluzione:

  • Utilizza Encrypted CBC (ECBC) anziché raw CBC
  • Utilizza NMAC anziché cascade
risposta data 23.05.2013 - 06:42
fonte

Leggi altre domande sui tag