Come criptare correttamente un canale di comunicazione tra un client e un server (senza SSL)?

6

Ho una scarsa conoscenza nel mondo della crittografia, sto appena iniziando a impararlo quindi sono un principiante:)

Come progetto per entrare nel campo della crittografia, voglio scrivere un programma client \ server che possa inviare e ricevere dati in modo sicuro ( i crittografato).

Diciamo che voglio crittografare il traffico tra un client e un server o tra due client. Il servizio che sto utilizzando può parlare solo con il server o un altro client (che funge anche da server) su una porta conosciuta, il server ascolta sostanzialmente una connessione su un lato su una porta predefinita.

Voglio che quei servizi siano in grado di comunicare tra loro senza la possibilità che una terza parte che sta ascoltando sulla rete sia in grado di decrittografare il contenuto della conversazione o provare a imitare un servizio.

Non sto cercando un nuovo modo per scambiare le chiavi (o dovrei?), posso avere le chiavi salvate in modo sicuro nei servizi così quando x invia un messaggio a y e di nuovo, saranno gli unici in grado di decodificare il contenuto e la risposta (fuori rotta, solo per un servizio verificato ).

  • nota a margine, la chiave può essere salvata nel programma - hardcoded o può essere generato da una combinazione di elementi (ad es. IP, nome-computer, nome utente o qualsiasi altra combinazione di costanti) che può essere trasmesso al client in modo che sia in grado di generare la chiave (diciamo che sto passando l'IP, il nome del computer e un seme casuale, ci sarà una formula conosciuta per creare la chiave da quei valori).

Ho bisogno di utilizzare una chiave simmetrica per la crittografia, ma forse posso provare a utilizzare due chiavi pre-generate come fa SSL.

So che se uso sempre la stessa chiave, una terza persona può annusare il traffico e ottenere la chiave (matematica al meglio, come è fatta?), più dati raccoglierà, più più facile diventa (?).

Quindi, cosa dovrei fare per promettere che nessuno sarà in grado di ottenere la chiave di crittografia (eventualmente leggendo i dati)? Quale cifra dovrei usare? Cos'altro ho bisogno di sapere prima di iniziare il mio viaggio?

    
posta YSY 21.09.2011 - 21:47
fonte

7 risposte

8

Questo è in realtà più semplice di quanto gli altri abbiano suggerito di pensare. Ecco cosa propongo:

  1. Genera una coppia di chiavi pubblica / privata utilizzando RSA. Puoi farlo su qualsiasi macchina Unix usando openssl: openssl genrsa -out rsa.private 2048
  2. Distribuisci la chiave pubblica come codificata nel tuo client.
  3. Quando il client esegue l'accesso, il client genera una chiave privata condivisa (che utilizza anche openssl o un'altra libreria di crittografia ben nota) e la crittografa utilizzando la chiave pubblica.
  4. tutti i dati tra client e server devono essere crittografati con la nuova chiave condivisa per la durata della sessione.

Ci sono molte altre cose che puoi fare per renderlo più rigido, come limitare la lunghezza di Sesison a una o poche ore prima di generare nuovamente le chiavi, avere il digest dei messaggi del server, ecc. Una piena comprensione della crittografia aiuterà capisci cosa sono e perché, ma per un'implementazione di base (per dati di valore medio-basso) questo dovrebbe essere sufficiente.

    
risposta data 22.09.2011 - 04:46
fonte
2

Prima della codifica, leggi questo: link

Questa domanda è troppo ampia per adattarsi a StackExchange purtroppo. La lunghezza e l'ampiezza della crittografia sono raramente attraversate da un singolo individuo con qualsiasi grado di successo senza un'istruzione formale in matematica, informatica e un'infarinatura di ingegneria.

Questo libro ti aiuterà a imparare concetti comuni, errori comuni, folli da cui imparare e esempi da seguire.

    
risposta data 21.09.2011 - 23:15
fonte
1

Fondamentalmente vuoi il tipo di tunnel fornito da SSL. Queste cose sono effettivamente difficili da ottenere.

SSL è un insieme di diverse cose. C'è il tunnel stesso: una volta che c'è un segreto condiviso (quello che viene chiamato il "segreto pre-master" nella specifica TLS ), e client e server sono d'accordo su quali algoritmi utilizzare, quindi i singoli record di dati possono essere crittografati, come descritto nella sezione 6 della specifica. Per arrivare a quel punto, SSL esegue prima l' handshake in cui si verifica la crittografia asimmetrica. Se controlli sia il client che il server e già "intrinsecamente" condividono un segreto, allora puoi saltare l'handshake.

Durante l'handshake, il server invia un blob opaco (il "certificato") che il client può utilizzare per ottenere la chiave pubblica del server. Se il client ha una conoscenza inerente della chiave pubblica del server, può ignorare completamente ciò che il server ha inviato e utilizzare semplicemente la chiave pubblica conosciuta. La convalida del certificato (che è una parte di codice piuttosto complessa) viene utilizzata solo quando il client desidera rilevare dinamicamente la chiave pubblica del server, ovvero ciò che si verifica sul Web. Ma, a seconda del tuo scenario, questo non è necessariamente necessario.

Ora abbiamo in questo sito una domanda su come funziona SSL con molto risposte descrittive (se lunghe).

Se SSL non ti ispira, dai un'occhiata a SSH. Stessi concetti, protocollo distinto. SSH è descritto su diversi documenti; inizia con RFC 4251 .

    
risposta data 05.10.2012 - 03:18
fonte
0

Non può essere fatto senza un canale di distribuzione indipendente per trasferire una chiave dal server al client. Per SSL, questo è l'intero processo di firma del certificato e le chiavi pubbliche per i certificati radice dell'autorità di certificazione inclusi nei browser web. Quindi il tuo primo problema è capire come ottenere una chiave dal server al client in un modo che non può essere intercettato da un attacco man-in-the-middle (cioè non sulla rete).

    
risposta data 21.09.2011 - 22:00
fonte
0

Se vuoi creare un canale sicuro senza SSL / TLS, allora ciò che devi fare è riorganizzare SSL / TLS, pezzo dopo pezzo. Non c'è molto (se non altro) che puoi tralasciare e rimanere con una connessione sicura: tutto ciò che vedi è il risultato di circa 20 anni di utilizzo, revisione e analisi.

Questa è una parte piuttosto significativa del motivo per cui si sente sempre che non si dovrebbe provare a trasmettere la propria crittografia. Quindi, piuttosto che iniziare da zero e fare la tua strada, è meglio stare seduti con le specifiche e imparare come funzionano le implementazioni esistenti.

    
risposta data 05.10.2012 - 10:32
fonte
0

Mi rendo conto che questo è un vecchio post, e spero di non aver vagato troppo fuori tema, ma alcuni pensieri.

In primo luogo, in termini di pre-configurazione delle chiavi, è una cattiva pratica (specialmente se si utilizza un algoritmo di crittografia più vecchio come DES, dove è abbastanza semplice recuperare la chiave). Vuoi essere in grado di ruotare periodicamente le chiavi, non solo usarle per sempre; in linea di principio almeno quanto più usi una chiave tanto meno diventa sicura (perché se qualcuno riuscisse a ottenere la chiave in qualche modo potrebbe decrittografare tutte le comunicazioni che usavano quella chiave).

In pratica, gli algoritmi di crittografia moderni e correttamente applicati sono molto difficili da decifrare e in genere sono piuttosto resistenti agli attacchi in chiaro e testo in chiaro, ma ci sono spesso altri modi per ottenere una chiave, come l'hacking - o ottenere l'accesso fisico a - il server o il computer client; questo in realtà è successo a molte aziende (la maggior parte notoriamente Target). Questo in particolare è un problema se lo stai archiviando sul server in chiaro. (C'è molta documentazione là fuori su come archiviare cose come questa correttamente - non ho mai provato questo con una chiave ma immagino che tu voglia seguire procedure simili a come avresti protetto una password).

Il problema della rotazione della chiave non sarebbe un problema se si ha accesso fisico continuo al client e al server, nel qual caso è possibile aggiornare le chiavi periodicamente (a condizione che non si dimentichi). (Dovresti comunque memorizzarli in modo sicuro sia sul client che sul server nel caso in cui qualcuno abbia hackerato il server o il client o ottenuto l'accesso fisico ad esso).

Come regola generale, tieni presente che la sicurezza è sempre relativa, quindi quando dici che vuoi essere sicuro, la domanda è sempre "Quanto è sicuro?" Ad esempio, avevo un progetto in cui stavamo usando i codici affini per crittografare determinati valori del database; quelli sono facili da decifrare ma il nostro scopo nell'usarli era impedire l'accesso da parte di osservatori casuali, non intenzionalmente cattivi, quindi era sufficiente. In pratica, la maggior parte degli algoritmi più vecchi come questo sono già gravemente danneggiati e di conseguenza offrono pochissima protezione contro un aggressore sufficientemente motivato con risorse adeguate. Ad esempio, DES (Data Encryption Standard) è vulnerabile agli attacchi di "forza bruta" a causa delle sue chiavi troppo corte (anche alla fine degli anni '90 era possibile forzare una chiave in meno di 24 ore) ma offre comunque almeno una certa protezione contro gli attaccanti non motivati.

Inoltre, probabilmente questo non è esattamente ciò che intendevi nel tuo post originale ma non ci sono pratici algoritmi in cui è letteralmente impossibile per un utente malintenzionato non decifrare il tuo messaggio; per algoritmi moderni come AES è impraticabile (ma non, in linea di principio, impossibile) fare per ora. (Frase chiave: "Per ora". DES era sicuro quando fu sviluppato per la prima volta, ma fu pubblicamente rotto 20 anni dopo ed era probabilmente possibile che i governi facessero così tanto tempo prima). Ci sono alcuni algoritmi che hanno "sicurezza perfetta", come il one-time pad (in cui si ha una chiave completamente casuale che è lunga quanto il messaggio che si usa una sola volta); per questi, non è possibile scoprire più sul messaggio che la sua lunghezza senza la chiave. Tuttavia, questo algoritmo non è pratico a causa del problema dello scambio di chiavi; è altrettanto difficile scambiare la chiave in modo sicuro per scambiare il messaggio in modo sicuro.

    
risposta data 17.03.2016 - 18:39
fonte
0

Ho affrontato una situazione simile in passato e ho risolto le richieste GET e POST su HTTPS. In Android è piuttosto semplice codificare e il client HTTP incluso si prende cura di tutte le funzionalità crittografiche per te, così puoi avere una soluzione semplice ed evitare il rischioso "preparare la tua crittografia"

    
risposta data 12.07.2017 - 10:19
fonte

Leggi altre domande sui tag