Domanda:
Lezioni apprese e idee sbagliate riguardanti la crittografia e la crittografia
goodguys_activate
2011-02-20 01:25:34 UTC
view on stackexchange narkive permalink

La crittoologia è un argomento così ampio che anche i programmatori esperti quasi sempre commetteranno errori le prime volte. Tuttavia la crittografia è un argomento così importante, spesso non possiamo permetterci di avere questi errori.

Lo scopo di questa domanda è identificare ed elencare cosa non fare con un determinato 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. Includi un esempio "sbagliato"
  2. Spiega cosa c'è di sbagliato in questo esempio
  3. Fornisci un'implementazione corretta (se applicabile).
  4. Al meglio delle tue capacità, fornisci i riferimenti relativi ai punti 2 e 3 sopra.
Gli errori più comuni non sono errori nel codice, ma piuttosto idee sbagliate su come usare la crittografia. In altre parole, lo sviluppatore probabilmente commetterebbe lo stesso errore in qualsiasi lingua. Pertanto, consiglio di ampliare la domanda in modo che non sia così concentrata sul codice; la maggior parte degli errori sono errori concettuali, non difetti di codifica.
Anche se viene accettata una risposta, continua ad aggiungere le lezioni apprese. Per lo meno sarà educativo.
Inoltre, breve e facile presentazione di Colin Percival (tarsnap): http://www.bsdcan.org/2010/schedule/attachments/135_crypto1hr.pdf
Non eseguire la crittografia se hai bisogno di leggere gli elenchi "non fare". Chiedi a un ingegnere della sicurezza specializzato in crittografia di aiutarti. :)
Meta discussione correlata: [Chiarimento tra "implementare la propria crittografia" e "implementare uno standard"] (http://meta.security.stackexchange.com/q/1119/396)
Nella maggior parte dei casi non eseguire la crittografia se pensi di non aver bisogno di una lista "non fare" pronta (https://en.wikipedia.org/wiki/Dunning%E2%80%93 Kruger Effect) - Dave era sicuro che la sua implementazione fosse sicura.
Anche se questa domanda copre alcune questioni molto importanti, il suo formato non è molto adatto per i siti SE, poiché fondamentalmente sta cercando una "lista di X" che non funziona bene.
21 risposte:
#1
+76
D.W.
2011-02-20 09:52:34 UTC
view on stackexchange narkive permalink

Non eseguire il rollio della tua crittografia.

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

"Chiunque può inventare un algoritmo di crittografia che non può rompere da solo; è molto più difficile inventarne uno che nessun altro possa rompere".

Gli algoritmi di crittografia sono molto complessi e necessitano di un controllo approfondito per essere sicuri che siano sicuri; se inventi il ​​tuo, non lo otterrai ed è molto facile finire con qualcosa di insicuro senza rendertene conto.

Utilizza invece un algoritmo e un protocollo crittografici standard. È probabile che qualcun altro abbia già riscontrato il tuo problema e abbia progettato un algoritmo appropriato a tale scopo.

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

In realtà, questa dovrebbe essere la regola numero 1, che invaliderebbe tutte le nostre altre regole. Probabilmente ci sono solo poche centinaia di persone al mondo che dovrebbero progettare o implementare criptovalute. Il resto di noi dovrebbe semplicemente usare la sua (sana) API.
Qual è l'opzione migliore per uno sviluppatore .NET? Eventuali tutorial o esempi? È difficile per un non esperto di crittografia determinare informazioni errate da ciò che è valido.
È particolarmente allettante per l'ingegnere creativo che ha risolto problemi difficili in passato lasciare la crittografia a qualcun altro. Ci sono ancora molti problemi difficili e istruttivi da risolvere al di fuori della crittografia. Guarda gli esempi di persone che hanno commesso errori critici nella crittografia e risolvono qualcos'altro.
+1 L'API Crypto offre troppa flessibilità che può mettere nei guai lo sviluppatore laico. Ci sono molti esempi su Internet (e sul sito di supporto di MSFT) che violano almeno una delle lezioni apprese in questa pagina. Alcuni sviluppatori dimenticano di considerare cose come il modo in cui le chiavi vengono scambiate, convalidate e revocate. È qui che le cose si fanno spinose. Dove vengono tenute le chiavi? Come vengono pubblicate le chiavi? Come vengono convalidate le chiavi? Come viene eseguita la rotazione delle chiavi? Anche se lo sviluppatore è abbastanza fortunato da ottenere la matematica giusta o una combinazione di funzionalità (CBC, Block, stream, ecc.), Il protocollo potrebbe essere rotto.
Per un'opzione di alto livello per .net ho portato [keyczar in C #] (http://jbtule.github.com/keyczar-dotnet/).
"usare TLS" senza stampe fini non è una buona idea, quando vediamo [questo] (http://www.isg.rhul.ac.uk/tls/)
Non può essere una regola di crittografia non inventare la crittografia e non è un uso improprio di alcune API o algoritmi esistenti.
#2
+47
D.W.
2011-02-20 09:36:29 UTC
view on stackexchange narkive permalink

Non utilizzare la crittografia senza l'autenticazione del messaggio

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

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

Questo errore ha portato a gravi vulnerabilità nei sistemi distribuiti che utilizzavano la crittografia senza autenticazione, inclusi ASP.NET, XML crittografia, Amazon EC2, JavaServer Faces, Ruby on Rails, OWASP ESAPI, IPSEC, WEP, di nuovo ASP.NET e SSH2. Non vuoi essere il prossimo in questo elenco.

Per evitare questi problemi, devi usare l'autenticazione del messaggio ogni volta che applichi 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 devi pensarci.

  • In alternativa, puoi applicare la tua autenticazione del messaggio, come segue. Innanzitutto, crittografa il messaggio utilizzando uno schema di crittografia a chiave simmetrica appropriato (ad esempio, AES-CBC). Quindi, prendi l'intero testo cifrato (inclusi eventuali IV, nonc o altri valori necessari per la decrittografia), applica un codice di autenticazione del messaggio (ad esempio, AES-CMAC, SHA1-HMAC, SHA256-HMAC) e aggiungi il digest MAC risultante al testo cifrato prima della trasmissione. Sul lato ricevente, controlla che il digest MAC sia valido prima di decrittografarlo. Questa è nota come costruzione crittografa e poi autentica. (Vedi anche: 1, 2.) Anche questo funziona bene, ma richiede un po 'più di attenzione da parte tua.

Gli utenti C # e Java dovrebbero consultare [BouncyCastle] (http://www.bouncycastle.org/csharp/)
La crittografia @makerofthings7: GCM è inclusa nel provider Oracle all'interno di Java 7. Viene proposta anche per la crittografia TLS (all'interno di un RFC) e XML v1.1. L'implementazione Bouncy è compatibile con quella all'interno del provider Sun (ad eccezione delle differenze riguardanti i dati autenticati e l'esatta eccezione generata).
Per coloro che sono nuovi alla crittografia (quindi leggendo questo post) "Autenticazione" non ha nulla a che fare con "Accesso" o utilizzando le proprie credenziali. È qualcosa come un checksum. In realtà è la combinazione di matematica e processi che alla fine fa molto di più che il semplice checksum dei dati. (@D.W. Cosa ne pensi di questa spiegazione profana?)
Ottima spiegazione di @makerofthings7,! Forse sarebbe più chiaro se l'articolo si riferisse all '"autenticazione del messaggio" piuttosto che alla semplice autenticazione generica. Farò quel cambiamento adesso.
#3
+36
D.W.
2011-02-20 11:29:57 UTC
view on stackexchange narkive permalink

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

A volte vedo un errore: le persone vogliono un hash delle stringhe S e T. Le concatenano per ottenere un stringa singola S || T, quindi hash per ottenere H (S || T). Questo è difettoso.

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

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

La correzione: piuttosto che una semplice concatenazione, utilizzare una codifica decodificabile in modo univoco. Ad esempio, invece di calcolare H (S || T), potresti 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].

Di solito ci lancio HMAC. Leggermente più costoso, ma almeno non ho bisogno di implementarlo da solo.
@CodeInChaos, questi problemi si applicano ugualmente anche a HMAC. HMAC non fa nulla per aiutare se si concatenano più stringhe prima di inviarle a HMAC.
Quello che volevo dire è che ne uso uno come chiave, l'altro come messaggio.
@CodeInChaos, bene, usa quello che funziona per te, se sei abbastanza sicuro delle tue capacità crittografiche da evitare i difetti. Personalmente, non consiglierei questo approccio ad altri. (1) Non è per questo che HMAC è stato progettato, quindi se è sicuro, "sei stato fortunato". (2) Questo è limitato al caso di due campi. Se hai tre campi, devi fare qualcosa di più complesso. Quindi potrebbe anche usare una difesa adeguata fin dall'inizio, come usare una codifica decodificabile in modo univoco (ad esempio, anteporre la lunghezza prima di ogni campo da concatenare).
Che ne dici di H (H (S) || H (T))? poiché l'output di H () è una lunghezza fissa, non saresti in grado di spostare il confine. Inoltre, l'utilizzo di hash come input per la concatenazione rende davvero difficile manipolare una stringa su un lato di uno degli input in un valore desiderato. L'unico aspetto negativo che vedo è che ora stai facendo 3 hash invece di uno. Ma ancora una volta, gli hash dovrebbero essere lenti, quindi forse non è una brutta cosa dopotutto;)
@Marcin, sì, questo è un altro modo ragionevole per farlo. Ho aggiunto il tuo suggerimento alla mia risposta. Grazie per il suggerimento! (Potrebbero esserci alcuni casi molto oscuri in cui questa non è una buona soluzione - ad esempio, dove S è un segreto, H (S) è di pubblico dominio, T è una sfida e lo scopo era di far provare al mittente la conoscenza di S inviando un hash di S e T, ma non mi preoccuperò di quei casi speciali molto rari.)
@Marcin "_hashes dovrebbe essere lento_" no, ** non ** dovrebbe essere lento, e ** non ** lento, neanche
Il requisito qui è conoscere il confine in modo inequivocabile: l'approccio hash-concatenate-hash richiede di eseguire l'hashing di almeno tutti gli elementi tranne uno: un elemento in una posizione nota può essere lasciato senza hash. Quindi puoi evitare di usare H (S) se questa è una quantità nota usata per l'autenticazione - invece usando S ma hashing tutti gli altri componenti. Fai attenzione, comunque, poiché la matematica sottostante può morderti sotto varianti di concatenazione e re-hashing.
Sono un crypto-n00b, quindi questa potrebbe essere una domanda stupida, ma se stai cercando di ottenere l'hash di due stringhe `builtin` e` secure`, perché non usare l'hash H (`builtin` || [somedelimiter ] || `in modo sicuro`)?
@Matt, sì, può funzionare! Tuttavia, dovrai eseguire l'escape di qualsiasi istanza del delimitatore in queste stringhe (altrimenti, inevitabilmente, qualcuno digiterà una stringa contenente il delimitatore e quindi questo approccio va in pezzi). Ciò aggiunge complessità non presente nelle alternative. E se lo consigli ad altri, inevitabilmente uno del tuo pubblico dimenticherà di sfuggire ai delimitatori. Se dimenticano di sfuggire al delimitatore, questo schema fallisce silenziosamente: non è sicuro, ma probabilmente non lo noteranno durante il normale funzionamento. Quindi, sì, funziona, ma potrebbe non essere la mia prima scelta.
`H (json_encode (array (" builtin "," securely ")))` potrebbe farlo. E @penguat. Realex Payments utilizza un hash di quella forma nell'elaborazione delle carte di credito: "H (H (varie) | segreto)".
Cosa ??? Questa risposta non ha senso. Se i dati sono ambigui, non deve esserci un utente malintenzionato. Alice non sa come interpretare "builtinsecurely" perché Bob non ha inserito uno spazio. Questa ambiguità non è un problema introdotto dall'aggressore, ma è piuttosto inerente alla rappresentazione dei dati scelta. Come possiamo digerire qualcosa se non riusciamo a catenare? Ogni messaggio più lungo è una catenazione.
@Kaz, la tua confusione sarebbe completamente valida se stessimo parlando della formattazione dell'input per la crittografia (dove il ricevitore decrittograferà e quindi cercherà di dare un senso al testo in chiaro). Ma non è questa la situazione qui. Qui stiamo parlando della formattazione dell'input in una funzione hash. Qui non esiste un analogo della decrittografia; il ricevitore non prende mai il testo in chiaro e poi cerca di analizzarlo. Invece, il destinatario rigenera lo stesso testo in chiaro, lo sottopone ad hashing e vede se corrisponde all'hash inviato dal mittente. Pertanto, il protocollo sembrerà funzionare correttamente in assenza di un utente malintenzionato.
@D.W. Ho detto crittografa? Volevo scrivere "digest". Ecco, risolto. Buona cosa s.e. ci consente di modificare i commenti ore dopo che sono stati scritti.
Ok, quindi abbiamo due stringhe "incorporate" e "sicure". Li abbiamo messi insieme in modo non v'è alcun confine "builtinsecurely". Dove risiede la divisione non è affatto rappresentato nel messaggio in alcun modo. Nessun bit o byte di framing, nessun campo di lunghezza, niente. E poi lo abbiamo hash. E così ora l'attaccante "cambia il confine". Come funziona l'attaccante * cambiamento * * ciò che non c'è *?
E se metto insieme due bit e li hash, non sto catenando le stringhe? Quindi dobbiamo eseguire l'hashing di ogni bit separatamente in modo che venga identificato. Non vorremmo che gli aggressori spostassero i confini tra i bit in modo che 00 1 diventi improvvisamente 0 11.
@Kaz, ecco un caso che ho visto più volte: il mittente invia un messaggio con due parti, "builtin" e "secure". Il messaggio è in chiaro e nel messaggio la divisione è resa esplicita. Per proteggerne l'integrità, il mittente aggiunge un MAC o un hash o una firma sulla concatenazione delle parti del messaggio. Il difetto: un man-in-the-middle può cambiare il messaggio incorporato / sicuro in costruito / insicuro; entrambi hanno lo stesso hash / firma / MAC, quindi il destinatario non può rilevarlo. Leggi i due esempi a cui mi collego (AWS e Flickr) per capire in modo più dettagliato come ciò possa accadere. Sì, * è * un vero difetto.
@DW Ebbene sì, poiché la divisione è esplicita nel messaggio, ma quei bit non sono inclusi nell'hash !!! Non eseguire l'hash del payload e tralascia l'intestazione oi metadati. Trasmetti l'intero messaggio. Questo non è un problema di catenazione. Tutto ciò che escludi da un hash non è protetto da esso indipendentemente da cosa sia. Campo della lunghezza che suddivide il carico utile in due parti, timestamp o qualsiasi altra cosa.
#4
+29
Alex Holst
2011-02-20 02:11:32 UTC
view on stackexchange narkive permalink

Non riutilizzare nonc o IV

Molte modalità operative richiedono un IV (vettore di inizializzazione). Non devi mai riutilizzare lo stesso valore per una flebo due volte; in tal modo si possono annullare tutte le garanzie di sicurezza e causare una violazione catastrofica della sicurezza.

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

  • Per altre modalità operative, come la modalità CBC, il riutilizzo di un IV può anche facilitare gli attacchi di ripristino del testo in chiaro in alcuni casi .

Non importa quale modalità di operazione usi, non dovresti riutilizzare IV. Se ti stai chiedendo come farlo correttamente, la specifica NIST fornisce una documentazione dettagliata su come utilizzare correttamente le modalità di funzionamento della cifratura a blocchi.

Il progetto Tarsnap fornisce un buon esempio di questa trappola. Tarsnap crittografa i dati di backup dividendoli 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 in chiaro.

Come è successo? Al fine di semplificare il codice 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:

 / * Crittografa i dati. * / - 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 inavvertitamente trasformato in encr_aes->nonce e, di conseguenza, lo stesso valore nonce è stato utilizzato ripetutamente . In particolare, il valore CTR nonce non viene incrementato dopo che ogni 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: http://www.daemonology.net /blog/2011-01-18-tarsnap-critical-security-bug.html

Poiché il problema è incentrato su un nonce, prova a intitolare questa risposta in tal senso (+1); D: un nonce di solito è ++ o dovrebbe essere casuale?
@makerofthings, dipende dall'algoritmo. Alcuni algoritmi e modalità di funzionamento richiedono nonce casuali (ad esempio, modalità CBC); altri richiedono solo che le nonce siano distinte, e quindi è sufficiente un contatore (ad esempio, modalità CTR). Si spera che la specifica per algoritmo / modalità di funzionamento descriva ciò che è richiesto.
Suggerisco di modificare la risposta per includere anche gli IV. L'uso corretto di IV / nonce sono idee molto simili.
Nonce è N una volta. Sì, usa la variabile N solo una volta. Singolare. Non ripetere. La forza dell'algoritmo associato viene danneggiata ripetendo N.
Ecco un esempio sbagliato: WEP ha implementato RC4 con un nonce a 24 bit che aumenta dopo ogni messaggio. Ciò ha introdotto due problemi: (1) dopo l'invio di 2 ^ 24 pacchetti, i nonce sono stati riutilizzati. (2) RC4 non è stato progettato per avere nonc "strettamente correlati" dove è noto che ogni cifra successiva era ++ il valore del precedente.
Ecco un esempio corretto: supponiamo che un designer di crittografia non voglia riutilizzare la stessa chiave per più messaggi. Una soluzione è generare una chiave ed espanderla utilizzando un PRG. Quindi usa solo ogni multiplo di bit "x" come chiave. Dove segmento 1 == chiave 1, segmento 2 == chiave 2.
#5
+29
D.W.
2011-02-20 10:06:23 UTC
view on stackexchange narkive permalink

Assicurati di seminare generatori di numeri casuali con sufficiente entropia.

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

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

Esempi: srand (time (NULL)) è pessimo. Un buon modo per seminare il tuo PRNG è prendere 128 bit o numeri veri casuali, ad esempio 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 random. Grazie a Nate Lawson per alcuni esempi.

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

Ricordo di aver imparato il Basic sulla mia Apple] [e. Stavo scrivendo un gioco e avevo bisogno di input casuali, quindi ho usato RND (1). Ho dovuto continuare a riavviare per eseguire il debug del gioco e ho notato che l'elemento casuale andava sempre nella stessa sequenza dopo l'avvio. È stato allora che ho imparato a conoscere i generatori di numeri pseudocasuali. Se hai bisogno di semi casuali, Random.org offre la generazione gratuita di numeri casuali basata sul rumore atmosferico.
Random.org è il migliore per la simulazione e altri scopi non di sicurezza. Random.org non è una buona base per un seme per un PRNG crittografico, perché non puoi fidarti che è sconosciuto agli altri.
#6
+20
goodguys_activate
2011-02-20 01:34:06 UTC
view on stackexchange narkive permalink

Non utilizzare un codice a blocchi con ECB per la crittografia simmetrica

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

Ecco un post e un articolo Microsoft KB molto simile relativo al modo in cui la modalità ECB produce codice non crittografato.

Vedi anche questo post simile da Rook

Messaggio di testo normale:

alt text

Lo stesso messaggio crittografato con la modalità ECB (non importa quale cifra usi): alt text

Lo stesso messaggio ESATTO usando la modalità CBC (di nuovo, non importa cosa cifratura che utilizzi): alt text

Il modo sbagliato

  stringa statica pubblica Encrypt (string toEncrypt, string key, bool useHashing) { byte [] keyArray = UTF8Encoding.UTF8.GetBytes (chiave); byte [] toEncryptArray = UTF8Encoding.UTF8.GetBytes (toEncrypt); if (useHashing) keyArray = new MD5CryptoServiceProvider (). ComputeHerviceProvider (). ) {Key = keyArray, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7}; ICryptoTransform cTransform = tdes.CreateEncryptor (); byte [] resultArray = cTransform.TransformFinalBlock (toEncryptArray, 0, toEncryptArtrray.Length) (resultArray, 0, resultArray.Length);}  

L'errore è nella riga seguente

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


La strada giusta

I bravi ragazzi di Microsoft mi hanno inviato il codice seguente per correggere l'articolo della KB collegato sopra. Viene fatto riferimento nel caso n. 111021973179005

Questo codice di esempio utilizza AES per crittografare i dati e la chiave per la crittografia AES è il codice hash generato da SHA256. AES è l'algoritmo Advanced Encryption Standard (AES). L'algoritmo AES si basa su permutazioni e sostituzioni. Le permutazioni sono riorganizzazioni di dati e le sostituzioni sostituiscono un'unità di dati con un'altra. AES esegue permutazioni e sostituzioni utilizzando diverse tecniche. Per maggiori dettagli su AES, fare riferimento all'articolo "Proteggi i tuoi dati con il nuovo standard di crittografia avanzata" su MSDN Magazine su http://msdn.microsoft.com/en-us/magazine/cc164055.aspx.

SHA è l'algoritmo di hash sicuro. SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512) è ora consigliato. Per informazioni più dettagliate sui valori hash in .NET Framework, fare riferimento a http://msdn.microsoft.com/en-us/library/92f9ye3s.aspx#hash_values ​​.

Il valore predefinito della modalità per il funzionamento dell'algoritmo simmetrico per AesCryptoServiceProvider è CBC. CBC è la modalità Cipher Block Chaining. Introduce feedback. Prima che ogni blocco di testo normale venga crittografato, viene combinato con il testo cifrato del blocco precedente mediante un'operazione OR esclusiva bit per bit. Ciò garantisce che, anche se il testo normale contiene molti blocchi identici, ciascuno di essi verrà crittografato in un diverso blocco di testo cifrato. Il vettore di inizializzazione viene combinato con il primo blocco di testo normale da un'operazione OR esclusivo bit per bit prima che il blocco venga crittografato. Se un singolo bit del blocco di testo cifrato viene alterato, verrà alterato anche il corrispondente blocco di testo normale. Inoltre, un po 'nel blocco successivo, nella stessa posizione dell'originale morso, verrà storpiato. Per informazioni più dettagliate su CipherMode , fare riferimento a http://msdn.microsoft.com/en-us/library/system.security.cryptography.ciphermode.aspx.

Ecco il codice di esempio.

  // Questa funzione viene utilizzata per crittografare i dati con chiave e iv.
byte [] Encrypt (byte [] data, byte [] chiave, byte [] iv) {// Crea un AESCryptoProvider. using (var aesCryptoProvider = new AesCryptoServiceProvider ()) {// Inizializza AESCryptoProvider con chiave e iv. aesCryptoProvider.KeySize = key.Length * 8; aesCryptoProvider.IV = iv; aesCryptoProvider.Key = chiave; // Crea un criptatore da AESCryptoProvider. using (ICryptoTransform encryptor = aesCryptoProvider.CreateEncryptor ()) {// Crea un flusso di memoria per archiviare i dati crittografati. using (MemoryStream stream = new MemoryStream ()) {// Crea un CryptoStream per crittografare i dati. using (CryptoStream cryptoStream = new CryptoStream (stream, encryptor, CryptoStreamMode.Write)) // Crittografa i dati. cryptoStream.Write (data, 0, data.Length); // restituisce i dati crittografati. return stream.ToArray (); }}}} // Questa funzione viene utilizzata per decrittografare i dati con chiave e iv.byte [] Decrypt (byte [] dati, byte [] chiave, byte [] iv) {// Crea un AESCryptoServiceProvider. using (var aesCryptoProvider = new AesCryptoServiceProvider ()) {// Inizializza AESCryptoServiceProvier con key e iv. aesCryptoProvider.KeySize = key.Length * 8; aesCryptoProvider.IV = iv; aesCryptoProvider.Key = chiave; // Crea decryptor da AESCryptoServiceProvider. using (ICryptoTransform decryptor = aesCryptoProvider.CreateDecryptor ()) {// Crea un flusso di memoria che includa i dati crittografati. using (MemoryStream stream = new MemoryStream (data)) {// Crea un CryptoStream per decrittografare i dati crittografati. using (CryptoStream cryptoStream = new CryptoStream (stream, decryptor, CryptoStreamMode.Read)) {// Crea un array di buffer di byte.
byte [] readData = nuovo byte [1024]; int readDataCount = 0; // Crea un flusso di memoria per archiviare i dati decrittografati. using (MemoryStream resultStream = new MemoryStream ()) {do {// Decrypt the data and write the data into readData buffer array. readDataCount = cryptoStream.Read (readData, 0, readData.Length); // Scrive i dati decrittografati in resultStream. resultStream.Write (readData, 0, readDataCount); } // Controlla se sono presenti altri dati crittografati nel flusso. while (readDataCount > 0); // Restituisce i dati decrittografati. return resultStream.ToArray (); }}}}}} // Questa funzione viene utilizzata per generare una chiave binaria valida con codifica UTF8 e algoritmo hash SHA256.byte [] GetKey (chiave stringa) {// Crea classe algoritmo hash SHA256. using (SHA256Managed sha256 = new SHA256Managed ()) // Decodifica la chiave della stringa in binario e calcola il binario hash della chiave. return sha256.ComputeHash (Encoding.UTF8.GetBytes (key));}  

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

· Classe AesCryptoServiceProvider

· Classe SHA256Managed

· Classe CryptoStream

Inoltre, sono disponibili diversi articoli che possono aiutare a ottenere una migliore comprensione della crittografia in .NET Framework, fare riferimento ai collegamenti seguenti:

· Servizi di crittografia

· .NET Framework Cryptography Model

· Una semplice guida alla crittografia

· Crittografia senza Segreti

Suggerisco di cancellare tutto dopo "Il modo giusto". La proposta di Coda Hale ha una serie di punti deboli. Fa diversi errori che ho documentato in altre risposte qui: utilizza la crittografia senza autenticazione del messaggio (un grave difetto), crea la chiave come hash di una password (un grave difetto), non fa alcun tentativo di rallentare la ricerca completa delle chiavi (un altro grave difetto). La mia raccomandazione per il modo giusto di gestire questo è descritta nell'ultimo paragrafo della mia risposta intitolato "Non lanciare la tua crittografia".
Suggerisco di eliminare tutto il materiale dopo "Disclaimer" e "alcuni punti salienti". Penso che la maggior parte di loro non sia rilevante per il tuo punto di alto livello sull'evitare la BCE e sono una distrazione. Sii conciso. Invece, suggerirei che il tuo consiglio per il modo giusto dovrebbe essere: Usa una modalità operativa sicura, come la modalità CBC o la modalità CTR. Non dimenticare di seguire gli altri consigli su questa pagina, incluso l'utilizzo dell'autenticazione del messaggio, la generazione di chiavi in ​​modo appropriato, ecc.
@D.W. Sì, sentiti libero di modificare una o tutte le risposte come CW. Il mio pensiero contro il fare l'intera domanda CW è di incentivare i poster, ma lascerò questa decisione a voi. Voglio solo imparare le cose giuste e disimparare le cattive pratiche
Nota che questo errore è ancora più facile da fare in Java, che utilizza / ECB / PKCS5Padding come predefinito (ad esempio `Cipher.getInstance (" AES ")`), e se passi a CBC, usa un IV azzerato (più o meno una NONCE, vedi la risposta a riguardo) anche per impostazione predefinita.
Come hai criptato l'immagine in quel modo ??
@Matt, quell'immagine è il risultato di un attacco riuscito. Dato un file denominato TUX.BMP, si supponga che l'autore dell'attacco proverà a esaminarlo ma scopre che è crittografato. Quindi visualizza i byte crittografati e, vedendo uno schema non casuale, sospetta CBC. Quindi sostituisce i primi due blocchi con un'intestazione di file BMP buona e nota e la modifica finché le righe e le colonne non si allineano. Ho visto un ricercatore usare uno strumento per farlo a Blackhat alcuni anni fa, penso che lo strumento si chiamasse rumint.
#7
+20
D.W.
2011-02-20 09:50:34 UTC
view on stackexchange narkive permalink

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

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

Ad esempio, se hai una coppia di chiavi privata / pubblica RSA, non dovresti usarla entrambi per la crittografia (crittografa con la chiave pubblica, decrittografa con la chiave privata) e per la firma (firma con la chiave privata, verifica con la chiave pubblica): scegli un unico scopo e usalo solo per quello 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, dovresti usare una chiave per la crittografia e una chiave indipendente separata per l'autenticazione del messaggio. Non riutilizzare la stessa chiave per entrambi gli scopi.

S / MIME funziona contro questa raccomandazione? AFAIK Ho solo una chiave e ho la possibilità di firmare e crittografare.
IMHO il problema più grande con l'utilizzo delle stesse chiavi per entrambi gli usi deriva da problemi di applicazione della legge. In molte giurisdizioni ora ti può essere chiesto di cedere le tue chiavi di crittografia e ciò significherebbe in pratica che possono firmare a tuo nome.
Sì, molti algoritmi utilizzano la stessa coppia di chiavi per la firma e la crittografia, PGP e S / MIME sono gli esempi ovvi. Non è necessariamente un problema matematico.
PGP ** non ** utilizza la stessa coppia di chiavi per la firma e la crittografia. Piuttosto, una chiave privata PGP è composta da una chiave principale, utilizzata per la firma, e da una o più sottochiavi, utilizzate per la crittografia. Le sottochiavi sono nascoste all'utente, da qui la confusione, ma puoi visualizzarle usando `gpg --list-secret-keys`.
#8
+17
Chris Dale
2012-06-25 16:46:15 UTC
view on stackexchange narkive permalink

Principio di Kerckhoffs: un sistema crittografico dovrebbe essere sicuro anche se tutto ciò che riguarda il sistema, tranne la chiave, è di dominio pubblico

Un esempio sbagliato: Hash LANMAN

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

L'algoritmo è il seguente ( da wikipedia):

  1. La password ASCII dell'utente viene convertita in maiuscolo.
  2. Questa password è riempita con null fino a 14 byte
  3. La password di "lunghezza fissa" è suddivisa in due metà di sette byte.
  4. Questi valori vengono utilizzati per creare due chiavi DES, una da ciascuna metà di 7 byte
  5. Ciascuna delle due chiavi viene utilizzata per crittografare con DES la stringa ASCII costante "KGS! @ # $%", ottenendo 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 puoi ora molto spezza facilmente il testo cifrato in due testi cifrati che sai essere maiuscoli risultando in un insieme limitato di caratteri che la password potrebbe eventualmente essere.

Un esempio corretto: crittografia AES

  • Algoritmo noto
  • Scala con la tecnologia. Aumenta la dimensione della chiave quando hai bisogno di più grinta crittografica
#9
+13
curiousguy
2011-09-28 09:03:50 UTC
view on stackexchange narkive permalink

In un protocollo crittografico: Rendi riconoscibile ogni messaggio autenticato: non esistono due messaggi uguali

Una generalizzazione / variante di:

  • Prestare attenzione quando si concatenano più stringhe, prima dell'hashing.
  • Non riutilizzare le chiavi.
  • Non riutilizzare nonce.

Durante un esecuzione di protocollo crittografico molti messaggi che non possono essere contraffatti senza un segreto (chiave o nonce) possono essere scambiati. Questi messaggi possono essere verificati dal ricevuto 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 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 simultanea del protocollo. Un avversario può avviare molte esecuzioni simultanee di un protocollo crittografico per acquisire messaggi validi e riutilizzarli senza modifiche.

Riproducendo in modo intelligente i messaggi, potrebbe essere possibile attaccare un protocollo senza compromettere alcuna chiave primaria, senza attaccare alcun RNG , qualsiasi cifra, ecc.

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

In realtà, un nonce non ha bisogno di essere un segreto, deve solo essere usato solo una volta (entro un certo lasso di tempo, ad esempio la validità della chiave segreta corrispondente).
@PaŭloEbermann Molti usi di un nonce non richiedono segretezza, ma alcuni formalismi di protocollo chiamano il * segreto * usato per autenticare i messaggi un "nonce" piuttosto che una chiave, perché non è usato come chiave di crittografia.
#10
+13
D.W.
2011-02-20 11:39:43 UTC
view on stackexchange narkive permalink

Cerca di evitare di utilizzare le password come chiavi di crittografia.

Un punto debole comune in molti sistemi è usare una password o una passphrase o un hash di una password o una passphrase, come la chiave di crittografia / decrittografia. Il problema è che questo tende ad essere altamente suscettibile agli attacchi di ricerca chiavi offline. La maggior parte degli utenti sceglie password che non hanno entropia sufficiente per resistere a tali attacchi.

La soluzione migliore è usare una chiave di crittografia / decrittografia veramente casuale, non una generata in modo deterministico da una password / passphrase.

Tuttavia, se è necessario utilizzarne uno basato su una password / passphrase, utilizzare uno schema appropriato per rallentare la ricerca completa delle chiavi. Raccomando PBKDF2, che utilizza l'hashing iterativo (sulla falsariga di H (H (H (.... H (password) ...)))) per rallentare la ricerca nel dizionario. Fai in modo di utilizzare un numero sufficiente di iterazioni per far sì che questo processo richieda, diciamo, 100 ms sulla macchina dell'utente per generare la chiave.

Da principiante, ammetto di averlo fatto. Se la chiave è casuale e quindi impossibile da ricordare, stai raccomandando di archiviare le chiavi da qualche parte in una forma fisica? Questo è l'unico modo che posso vedere per implementare un sistema con chiavi puramente casuali.
@AdamCross, * "Se la chiave è casuale e quindi impossibile da ricordare, stai raccomandando che le chiavi siano memorizzate da qualche parte in una forma fisica?" * - Beh, memorizzata da qualche parte, potrebbe essere in forma elettronica o fisica. La forma non elettronica non deve essere necessariamente privilegiata rispetto alla forma elettronica in tutte le situazioni. Per fare un esempio ... puoi usare SSL per connetterti a un sito web in modo sicuro. La chiave di sessione SSL che utilizzi non è archiviata in formato non elettronico da nessuna parte e non è derivata da una passphrase.
haha per chiarire, con "forma fisica" intendo un posto diverso dalla mia testa --- ma questo non aveva senso dal momento che anche la mia testa è fisica.
#11
+8
D.W.
2011-02-20 09:48:24 UTC
view on stackexchange narkive permalink

Non utilizzare la stessa chiave in entrambe le direzioni.

Nelle comunicazioni di rete, un errore comune è quello di utilizzare la stessa chiave per la comunicazione nella direzione A-> B come per la direzione B-> A. Questa è una cattiva idea, perché spesso abilita gli attacchi di replay che riproducono qualcosa che A ha inviato a B, poi di nuovo ad A.

L'approccio più sicuro è 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.

Oppure potresti avere un SSC, un contatore di sessioni sicure, aumentato per ogni crittografia (entro una comunicazione half duplex). Ho anche visto un esempio in cui l'ultimo blocco di testo cifrato dell'altra parte è stato utilizzato come IV per il blocco successivo, ma ciò potrebbe portare ad alcuni attacchi particolari.
@owlstead, Sì, l'utilizzo dell'ultimo blocco di testo cifrato come IV per il blocco successivo, insieme alla modalità CBC, ha portato all'attacco BEAST su SSL. P.S. Un SSC potrebbe funzionare per separare i due canali, ma dovresti stare attento con esso. Dovresti incrementarlo sia per l'invio che per la ricezione (usare due SSC, uno per ogni direzione, vanificherebbe lo scopo). Inoltre l'SSC richiederà la sincronizzazione di entrambi i lati e non tollererà la caduta di pacchetti, il che potrebbe essere problematico in alcune impostazioni. Potrebbe essere più semplice usare solo due chiavi indipendenti.
Interessante, conosco alcune schede di memoria che usano quello schema con l'ultima parte del blocco cifrato come IV per la successiva. Lo esaminerò. Grazie D.W, immagino che la mia impressione avesse ragione su questo.
Questo apre anche la porta per un attacco Two time pad, quel bit Microsoft PPTP. La prima versione di PPTP utilizzava la stessa chiave nel client e nel server
#12
+8
D.W.
2011-02-20 09:44:44 UTC
view on stackexchange narkive permalink

Non utilizzare chiavi di lunghezza insicura.

Assicurati di utilizzare algoritmi con una chiave sufficientemente lunga.

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

Per la crittografia a chiave pubblica, i consigli sulla lunghezza della chiave dipendono dall'algoritmo e il livello di sicurezza richiesto. Inoltre, aumentare la dimensione della chiave danneggia le prestazioni, quindi un eccessivo sovraccarico non è economico; quindi, questo richiede un po 'più di riflessione rispetto alla selezione delle dimensioni della chiave simmetrica. Per RSA, El Gamal o Diffie-Hellman, consiglierei che la chiave sia di almeno 1024 bit, come minimo assoluto; tuttavia, le chiavi a 1024 bit sono al limite di ciò che potrebbe diventare crackabile a breve termine e generalmente non sono consigliate per l'uso moderno, quindi se possibile, consiglierei chiavi da 1536 o anche 2048 bit. Per la crittografia a curva ellittica, le chiavi a 160 bit sembrano adeguate 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 delle chiavi pubbliche.

Il NIST raccomanda più di 1024 bit chiavi a partire dalla fine del 2010: http://securitymusings.com/article/1587/algorithm-and-key-length-deprecation
L'unica frase con cui non sono d'accordo: "" Questo è un errore meno comune di questi tempi "` ... Ancora uno degli errori crittografici più comuni che vedo, dopo "Nessuna crittografia" e "Rolling your own crypto".
@AviD, @nealmcb, grazie per il feedback. Ho modificato per riflettere il commento di @AviD's. Nota che ho reso questo un wiki della comunità, quindi sentiti libero di modificarlo per migliorare i consigli e correggere eventuali errori.
#13
+3
Shane Hansen
2012-09-08 21:55:43 UTC
view on stackexchange narkive permalink

Usa la modalità corretta

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

  AES (testo in chiaro [32 ] byte, chiave [32] byte) -> ciphertext [32] byte  

è molto insicuro. Il ragionamento è semplice, mentre il numero di chiavi possibili nello spazio delle chiavi è abbastanza grande, l'anello debole qui è la quantità di entropia nel messaggio. Come sempre, xkcd.com descrive è meglio di me http://xkcd.com/257/

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

  testo cifrato [i] = SomeFunction (testo cifrato [i-1], messaggio [i], chiave)  

Giusto per sottolineare alcune librerie di linguaggi in cui questo tipo di errore è facile da commettere: http://golang.org/pkg/crypto/aes/ fornisce un'implementazione AES che, se usata in modo ingenuo, risultato in modalità ECB.

La libreria pycrypto utilizza per impostazione predefinita la modalità ECB quando si crea un nuovo oggetto AES.

OpenSSL, fa bene. Ogni chiamata AES è esplicita sulla modalità di funzionamento. La cosa più sicura IMO è davvero cercare di non fare da soli criptovalute di basso livello come questa. Se sei costretto, procedi come se stessi camminando su un vetro rotto (con attenzione) e cerca di assicurarti che i tuoi utenti siano giustificati nel riporre la loro fiducia in te per salvaguardare i loro dati.

Grazie per questa risposta, Shane! Una domanda: questo è già coperto dall'altra risposta [Non utilizzare un codice a blocchi con ECB per la crittografia simmetrica] (http://security.stackexchange.com/a/2203/971)?
#14
+3
D.W.
2012-10-17 19:57:20 UTC
view on stackexchange narkive permalink

Non riutilizzare la stessa chiave su molti dispositivi.

Più ampiamente condividi una chiave crittografica, meno è probabile che tu possa mantenerla segreto. Alcuni sistemi distribuiti hanno riutilizzato la stessa chiave simmetrica su ogni dispositivo del sistema. Il problema con questo è che prima o poi qualcuno estrarrà la chiave da un singolo dispositivo e poi sarà in grado di attaccare tutti gli altri dispositivi. Quindi, non farlo.

Vedi anche "Crittografia simmetrica da non fare n. 6: non condividere una singola chiave su molti dispositivi" in questo articolo del blog. Crediti a Matthew Green.

#15
+3
John Deters
2013-05-15 22:04:48 UTC
view on stackexchange narkive permalink

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

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

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

Qualsiasi violazione di queste condizioni significa che non è più un cifrario pad 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 pad monouso viene trasformato matematicamente nell'algoritmo di allungamento della chiave. La combinazione della chiave breve con byte casuali altera solo lo spazio di ricerca necessario per forzare l'algoritmo di estensione 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ò utilizzando un "blocco unico" che utilizza una funzione crittograficamente sicura come generatore di chiavi. Ho scelto una chiave segreta, quindi ho aggiunto un numero casuale per assicurarmi che non venga riutilizzata. Dato che non sto riutilizzando la chiave, non c'è modo di attaccare il testo cifrato sottraendo un messaggio da un altro.

  testo in chiaro: 1234567890123456789012345678901234567890 materiale chiave: 757578fbf23ffa4d748e0800dd7c424a46feb0ccOTP function (---- ------ testo cifrato: 67412E83622DCE1B0C1E1A348B04D25872A8C85C  

Il materiale della chiave è stato generato in modo sicuro utilizzando SHA-1 per hash la mia password segreta (più casuale) al fine di estenderla. Ma qualsiasi utente malintenzionato che conosce l'algoritmo di estensione * utilizzato è SHA-1 può attaccarlo provando vari input in SHA-1 e XORing l'output con il testo cifrato. Indovinare la chiave "OTP" ora non è più difficile che indovinare gli input combinati per l'algoritmo crittografico. Questa proprietà è vera indipendentemente dall'algoritmo crittografico di base scelto, dalle misure di complessità che contiene o da come viene implementato o seminato.

Potresti avere un ottimo algoritmo di key-stretching. Potresti anche avere un generatore di numeri casuali molto sicuro. Tuttavia, il tuo algoritmo non è per definizione un blocco unico e quindi non ha la proprietà indistruttibile di un blocco unico.

* Applicare il principio di Kerckhoff significa che devi presumere che l'attaccante possa sempre determinare gli algoritmi utilizzati.

Modificheresti "" Dato che non sto riutilizzando la chiave, non c'è modo di attaccare il testo cifrato sottraendo un messaggio a un altro "" e aggiungeresti del testo dicendo che sono possibili altri attacchi? ESEMPIO: due time pad, protocollo errato o altro bias (rispettivamente PPTP, WEP, RC4). Un laico inconsapevole potrebbe interpretare male ciò che hai scritto e pensare che OTP offra "segretezza perfetta" in un altro senso della parola. Inoltre, dal momento che stai affrontando questo argomento, sarebbe utile una copertura di ciò che è utile un barella chiave PNG / PRG valido.
Nota: non è presente l'autenticazione del messaggio in una OTP. Le modifiche a un'OTP non verranno rilevate.
Nota: un * PRG protetto * è simile a un OTP. È uno che ha tutti i test statistici efficienti con un risultato trascurabile e che è impossibile per un PRG soddisfare ogni test statistico teorico. Questa "riduzione" della sicurezza è necessaria per l'efficienza poiché "Perfect Secrecy" richiede una trasmissione sicura di una OTP abbastanza grande da corrispondere alla dimensione del messaggio. ESEMPIO: tutte le trasmissioni OTP richiedono che il segreto venga trasmesso in modo sicuro (il che non è definito come). È più efficiente utilizzare questo metodo sicuro per inviare i dati in primo luogo.
È la "somiglianza" che porta le persone a fare le affermazioni stravaganti di indistruttibilità, ed è quella "efficienza" che rompe l'imprevedibilità del codice Vernam. Nessuno ha detto che la generazione delle chiavi, la gestione delle chiavi o la distribuzione delle chiavi con una OTP siano facili o pratiche: non è nessuna delle precedenti. È così difficile che le persone usino ancora altri cyphers, nonostante la promessa di una segretezza matematicamente perfetta. Nessun "allungamento della chiave" può alterare questa verità.
Un "PRNG sicuro" potrebbe essere utilizzato per generare i bit, ma se è veramente sicuro, hai ancora tutti i problemi di distribuzione perché non puoi duplicare la loro generazione sul computer del destinatario - se potessi, quello stato sarebbe la chiave, non il bit.
#16
+1
Watson Ladd
2012-09-08 21:05:27 UTC
view on stackexchange narkive permalink

Non fidarti degli standard.

In crittografia esistono molti standard e a volte devi usarli. Ma non dare per scontato che le persone che scrivono gli standard abbiano compreso 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 violati ripetutamente molte volte, grazie all'abbondanza di funzioni pericolose. GPG supporta ancora le chiavi DSA che sono troppo brevi per il comfort. SSL ha opzioni che non dovrebbero essere utilizzate e richiede attenzione per evitarle.

Cosa si può fare al riguardo? Fare attenzione, comprendere i rischi noti e tenere il passo con la ricerca di nuovi.

MD5 è uno standard, vero. Ma è stato sostituito con uno standard più attuale, SHA. Per la maggior parte degli scenari, gli standard DOVREBBERO essere seguiti per molte ragioni. L'interoperabilità è un fattore molto importante.
Questa è un'affermazione molto fuorviante. La formulazione implica che il lettore dovrebbe "fidarsi dei NON standard", il che chiaramente non è vero. La maggior parte degli standard di sicurezza viene creata solo dopo numerosi test sul campo nel mondo reale. Questo test è molto più approfondito di quanto una singola organizzazione possa generare per "provare" la sicurezza del proprio sistema non standard.
#17
+1
goodguys_activate
2013-05-20 20:47:19 UTC
view on stackexchange narkive permalink

Non utilizzare una OTP o un cifrario di flusso nella crittografia del disco

Esempio 1

Supponi di salvare due file utilizzando un cifrario a flusso / OTP. Se il file viene salvato di nuovo dopo una modifica minore, un utente malintenzionato può vedere che sono stati modificati solo alcuni bit e dedurre informazioni sul documento. (Immagina di cambiare il saluto "Dear Bob" in "Dear Alice").

Esempio 2

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

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

Soluzione

Usa un codice a blocchi per queste situazioni che include controlli di integrità del messaggio

#18
  0
goodguys_activate
2013-05-20 21:08:44 UTC
view on stackexchange narkive permalink

Non utilizzare mai una chiave di cifratura One Time Pad (OTP) o stream più di una volta

Un'OTP applicata due volte significa che i dati crittografati con "segretezza perfetta" verranno decrittografati e in chiaro. Ciò accade perché i dati vengono sottoposti a XOR due volte.

Supponiamo che un OTP / o stream con la stessa chiave venga riutilizzato.

Un utente malintenzionato raccoglie molti dati inviato da un client a un server e XORs un insieme di due pacchetti insieme fino a quando i due pacchetti si decrittano a vicenda (o sottoinsieme in essi).

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

Esempi del mondo reale

  • Progetto Verona (1941-46) per un esempio di OTP utilizzato dai russi e successivamente decrittografati 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 una volta inviati 2 ^ 24 pacchetti o se viene ripristinata una scheda NIC. Il primo problema è dovuto al fatto che l'IV è lungo 24 bit, con il risultato che dopo che sono stati trasmessi 16 milioni di frame viene creato un doppio time pad. Il secondo problema si verifica nelle implementazioni hardware in cui, dopo un ciclo di alimentazione, l'IV si azzera, risultando in un doppio time pad. Questo problema è facile da vedere poiché il IV viene inviato in chiaro.

Raccomandazioni

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

  • Il client deve utilizzare una OTP (o stream cipher con PRG) con il server e il server dovrebbe utilizzare una chiave diversa durante la crittografia dei dati sul client

  • Invece di generare molte molte chiavi, è possibile espandere una singola chiave in un flusso lungo utilizzando un PRG (supponendo che ti fidi del PRG) e utilizza ogni segmento di tale espansione come chiave.

  • Sappi che non tutti i PRG sono fatti per funzionare in modalità incrementale e potrebbe essere necessario un input casuale. (RC4 presenta questo problema in modalità incremento)

#19
  0
goodguys_activate
2013-05-20 21:26:00 UTC
view on stackexchange narkive permalink

Non utilizzare RC4

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

Ci sono punti deboli

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

Porta via Se devi usare RC4, ignora i primi 256 byte poiché sono polarizzati. Se utilizzi RC4 per concerti di dati, il bias in RC4 consentirà gli attacchi di tutti i dati crittografati precedenti.

#20
  0
goodguys_activate
2013-05-20 21:49:46 UTC
view on stackexchange narkive permalink

Utilizza processori di flusso moderni che funzionino in modo appropriato in hardware o software

Non tutti i cifrari di flusso sono progettati per essere implementati in hardware o software. Linear feedback shift register (LFSR) è un esempio di un cifrario hardware ampiamente diffuso che può essere facilmente violato.

LFSR è utilizzato in:

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

L'hardware per quanto sopra è ampiamente distribuito e quindi difficile da aggiornare o da portare agli standard moderni. Tutto quanto sopra è gravemente danneggiato e non dovrebbe essere considerato attendibile per comunicazioni sicure.

Attacco:

Poiché la chiave è suddivisa in due sezioni durante la crittografia ( 17 bit e 25 bit) e questi bit vengono utilizzati per crittografare lo stesso testo cifrato, è possibile utilizzare la conoscenza del formato MPEG e forzare una chiave a 17 bit per estrapolare quale sia la chiave a 25 bit.

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

Soluzione:

Il progetto eStream (nel 2008 ) qualificati 5 stream ciphers che dovrebbero essere usati. Una differenza notevole è che invece di usare una chiave con un IV, i cifrari usano una chiave, un nonce e un contatore. Salsa20 funziona in questo modo ed è progettato per essere utilizzato facilmente sia in hardware che in software. Nello specifico, è incluso nel set di istruzioni x86 SSE2.

A parte

Le cifrature moderne non solo sono più sicure, ma sono anche più veloci:

  PRG Speed ​​(MB / sec) RC4 126 (obsoleto) Salsa20 / 12 643 (moderno) Sosemaunk 727 (moderno)  
#21
  0
goodguys_activate
2013-05-23 09:42:28 UTC
view on stackexchange narkive permalink

Utilizza solo MAC che non siano vulnerabili agli attacchi alle estensioni dei messaggi

Un MAC è un codice hash che garantisce l'integrità del messaggio (nessuna modifica, ecc.) di un determinato piano testo. Molte implementazioni e standard pubblicati non riescono a proteggere un MAC da un utente malintenzionato che aggiunge dati aggiuntivi al MAC.

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

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

Soluzione:

  • Usa Encrypted CBC (ECBC) invece di raw CBC
  • Usa NMAC invece di cascade


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 2.0 con cui è distribuito.
Loading...