Come implementare la protezione con password per i singoli file?

Sto scrivendo una piccola app per desktop che dovrebbe essere in grado di crittografare un file di dati e proteggerlo con una password (ad esempio, è necessario inserire la password corretta per decodificare). Voglio che il file di dati crittografato sia autonomo e portatile, quindi l’autenticazione deve essere incorporata nel file (o così presumo).

Ho una strategia che sembra fattibile e sembra logica in base a quello che so (che è probabilmente sufficiente per essere pericoloso), ma non ho idea se sia effettivamente un buon progetto o meno. Allora dimmi: è pazzesco? C’è un modo migliore / migliore per farlo?

  • Passaggio 1: l’utente inserisce la password in testo semplice, ad es. “MyDifficultPassword”
  • Passaggio 2: l’applicazione esegue l’hashing della password utente e utilizza tale valore come chiave simmetrica per crittografare / decrittografare il file di dati. es. “MyDifficultPassword” -> “HashedUserPwdAndKey”.
  • Passaggio 3: App elimina il valore hash del passaggio 2 e salva il nuovo valore nell’intestazione del file di dati (ovvero la parte non crittografata del file di dati) e utilizza tale valore per convalidare la password dell’utente. es. “HashedUserPwdAndKey” -> “HashedValueForAuthentication”

Fondamentalmente sto estrapolando dal modo comune di implementare le password del sito web (quando non stai usando OpenID, cioè), che è quello di memorizzare l’hash (salato) della password dell’utente nel tuo DB e non salvare mai la password effettiva . Ma poiché utilizzo la password utente con hash per la chiave di crittografia simmetrica, non posso utilizzare lo stesso valore per l’autenticazione. Così l’ho cancellato di nuovo, fondamentalmente trattandolo proprio come un’altra password, e salvando il valore doublely-hash nel file di dati. In questo modo, posso trasferire il file su un altro PC e decrittarlo inserendo semplicemente la mia password.

Quindi questo design è ragionevolmente sicuro, o irrimediabilmente ingenuo, o da qualche parte nel mezzo? Grazie!

EDIT: chiarimenti e domande di follow-up: Salt.
Pensavo che il sale dovesse essere tenuto segreto per essere utile, ma le risposte e i collegamenti implicano che non è così. Ad esempio, questa specifica collegata da erickson (sotto) dice:

Pertanto, la derivazione della chiave basata su password come definito qui è una funzione di una password, un valore salt e un conteggio di iterazione, in cui le ultime due quantità non devono essere mantenute segrete.

Questo significa che potrei memorizzare il valore di sale nello stesso posto / file della chiave con hash ed essere comunque più sicuro di se non usassi del sale durante l’hashing? Come funziona?

Un po ‘più di contesto: il file crittografato non è pensato per essere condiviso o decrittografato da altri, si tratta di dati davvero monoutente. Ma mi piacerebbe distribuirlo in un ambiente condiviso su computer che non controllo completamente (ad esempio sul posto di lavoro) ed essere in grado di migrare / spostare i dati semplicemente copiando il file (quindi posso usarlo a casa, su diversi postazioni di lavoro, ecc.).

Generazione chiave

Ti consiglio di utilizzare un algoritmo riconosciuto come PBKDF2 definito in PKCS # 5 versione 2.0 per generare una chiave dalla tua password. È simile all’algoritmo che descrivi, ma è in grado di generare chiavi simmetriche più lunghe da utilizzare con AES. Dovresti riuscire a trovare una libreria open source che implementa i generatori di chiavi PBE per diversi algoritmi.

Formato del file

Potresti anche considerare l’utilizzo della Sintassi dei messaggi crittografici come formato per il tuo file. Ciò richiederà alcuni studi da parte tua, ma ancora una volta ci sono librerie esistenti da utilizzare e si apre la possibilità di interagire in modo più fluido con altri software, come i client di posta abilitati S / MIME.

Convalida password

Per quanto riguarda il desiderio di memorizzare un hash della password, se si utilizza PBKDF2 per generare la chiave, è ansible utilizzare un algoritmo di hashing della password standard (grande sale, un migliaio di cicli di hashing) per quello e ottenere valori diversi.

In alternativa, è ansible calcolare un MAC sul contenuto. È più probabile che una collisione hash su una password sia utile per un utente malintenzionato; una collisione hash sul contenuto è probabilmente inutile. Ma servirebbe a far sapere a un destinatario legittimo che è stata usata la password sbagliata per la decodifica.

Sale crittografico

Salt aiuta a contrastare gli attacchi del dizionario pre-calcolato.

Supponiamo che un utente malintenzionato abbia un elenco di password probabili. Può eliminarli tutti e confrontarli con l’hash della password della sua vittima e vedere se corrisponde. Se la lista è grande, questo potrebbe richiedere molto tempo. Non vuole passare così tanto tempo sul suo prossimo objective, quindi registra il risultato in un “dizionario” in cui un hash punta al suo input corrispondente. Se la lista delle password è molto, molto lunga, può usare tecniche come una Rainbow Table per risparmiare spazio.

Tuttavia, supponiamo che il suo prossimo objective abbia salato la propria password. Anche se l’aggressore sa qual è il sale, la sua tabella precalcasting è inutile: il sale cambia l’hash risultante da ciascuna password. Deve ri-hash tutte le password nella sua lista, apponendo il sale del bersaglio all’input. Ogni diverso sale richiede un dizionario diverso, e se vengono usati abbastanza sali, l’attaccante non avrà spazio per memorizzare dizionari per tutti. Lo spazio di trading per risparmiare tempo non è più un’opzione; l’attaccante deve ricorrere all’astinatura di ciascuna password nella sua lista per ogni bersaglio che vuole attaccare.

Quindi, non è necessario mantenere il sale segreto. È sufficiente assicurarsi che l’autore dell’attacco non abbia un dizionario pre-calcolato corrispondente a quel particolare sale.

Come ha detto Niyaz, l’approccio sembra ragionevole se si utilizza un’implementazione di qualità di algoritmi forti, come SHA-265 e AES per l’hashing e la crittografia. Inoltre, consiglierei di usare un Salt per ridurre la possibilità di creare un dizionario con tutti gli hash delle password.

Certamente, leggere la Crittografia Applicata di Bruce Schneier non è mai sbagliato.

Se si utilizza un algoritmo di hash forte (SHA-2) e un algoritmo di crittografia avanzata (AES), si andrà bene con questo approccio.

Perché non utilizzare una libreria di compressione che supporti i file protetti da password? Ho usato un file zip protetto da password contenente contenuti XML in passato:}

È davvero necessario salvare la password con hash nel file. Non puoi semplicemente usare la password (o la password con hash) con un po ‘di sale e quindi cifrare il file con esso. Quando decifri, prova a decodificare il file con la password + salt. Se l’utente fornisce una password errata, il file decrittografato non è corretto.

Unico inconveniente che posso pensare è che se l’utente inserisce accidentalmente una password errata e la decrittografia è lenta, deve aspettare per riprovare. E naturalmente, se la password viene dimenticata, non c’è modo di decifrare il file.