Come può essere implementato un database di password condiviso?

2

Nel modulo tradizionale, un database delle password è simile a qualsiasi altro file di database, ad eccezione del fatto che i contenuti sono crittografati utilizzando una chiave derivata da una passphrase immessa dall'utente. L'utente inserisce la sua passphrase, decrittografa il database, legge alcune voci, scrive / modifica alcune altre voci, re-crittografa il database e lo scrive nuovamente su disco.

Diciamo che volevamo estendere questo concetto a un ambiente condiviso. Supponiamo che il nostro database abbia dieci voci ( 0 fino a 9 ) e tre utenti ( Alice , Bob e Carl ), ciascuna con la propria passphrase unica. Per complicare ulteriormente lo scenario, Alice dovrebbe essere in grado di accedere a tutte le voci, Bob dovrebbe solo essere in grado di accedere alle voci 0-4 e Carl dovrebbe essere in grado di accedere solo alle voci 5-9. Se Alice cambia una delle voci, Bob o Carl dovrebbero vedere il valore aggiornato (se hanno accesso). Se Bob o Carl cambia una delle voci a cui hanno accesso, Alice dovrebbe vedere il valore aggiornato.

Sono curioso di sapere se esiste un modo in cui qualcosa di simile potrebbe essere implementato in modo sicuro. Tutti gli approcci che sono stato in grado di fare o richiedono che ci sia una sorta di chiave "master" memorizzata insieme al database, lasciando così una grande opportunità per chiunque abbia accesso al filesystem o alla memoria del server - o memorizzare una copia crittografata in modo univoco di ciascun set di voci per ciascun utente. Ma ciò interromperà gli scenari in cui un utente deve aggiornare un valore in modo che gli altri utenti possano vedere.

C'è un modo per farlo, o in qualche modo sottile i requisiti potrebbero essere modificati per rendere il sistema meno paradossale?

    
posta smitelli 05.02.2015 - 04:05
fonte

3 risposte

2

Ho pensato un po 'alle risposte che sono state pubblicate finora, e c'è una promessa interessante nell'idea di utilizzare un algoritmo a chiave pubblica. Pensando ad alta voce, ogni utente potrebbe avere una coppia di chiavi pubblica / privata (in cui ogni chiave pubblica è memorizzata sul server centrale insieme ai database).

Archiviazione chiave pubblica sul server:

+-------+------------------------+
| Alice | [public key for Alice] |
+-------+------------------------+
| Bob   | [public key for Bob]   |
+-------+------------------------+
| Carl  | [public key for Carl]  |
+-------+------------------------+

Ogni voce verrà archiviata crittografata, utilizzando un cifrario simmetrico con una chiave per voce generata casualmente dal server ogni volta che viene scritta una voce:

+---+-------------------------------------------------+
| 0 | symmetric_cipher([plaintext 0], [random key 0]) |
+---+-------------------------------------------------+
| 1 | symmetric_cipher([plaintext 1], [random key 1]) |
+---+-------------------------------------------------+
|   ...                                               |
+---+-------------------------------------------------+
| 9 | symmetric_cipher([plaintext 9], [random key 9]) |
+---+-------------------------------------------------+

Per il controllo degli accessi, una terza mappatura potrebbe memorizzare la chiave generata a caso per ogni voce, che è stata crittografata utilizzando la chiave pubblica di ciascun utente autorizzato:

+-------+---+-------------------------------------------------------+
| Alice | 0 | pubkey_cipher([random key 0], [public key for Alice]) |
+-------+---+-------------------------------------------------------+
| Bob   | 0 | pubkey_cipher([random key 0], [public key for Bob])   |
+-------+---+-------------------------------------------------------+
| Alice | 1 | pubkey_cipher([random key 1], [public key for Alice]) |
+-------+---+-------------------------------------------------------+
| Bob   | 1 | pubkey_cipher([random key 1], [public key for Bob])   |
+-------+---+-------------------------------------------------------+
|   ...                                                             |
+-------+---+-------------------------------------------------------+
| Alice | 8 | pubkey_cipher([random key 8], [public key for Alice]) |
+-------+---+-------------------------------------------------------+
| Carl  | 8 | pubkey_cipher([random key 8], [public key for Carl])  |
+-------+---+-------------------------------------------------------+
| Alice | 9 | pubkey_cipher([random key 9], [public key for Alice]) |
+-------+---+-------------------------------------------------------+
| Carl  | 9 | pubkey_cipher([random key 9], [public key for Carl])  |
+-------+---+-------------------------------------------------------+

(Da quello che ho letto, questo è un po 'quello che fa GPG quando si invia un messaggio crittografato a più destinatari.)

Ogni utente può utilizzare la propria chiave privata per decifrare la chiave simmetrica "entrata", valida solo per quella specifica voce. Quella chiave permetterà loro di decifrare e leggere quella voce. Se hanno bisogno di cambiarlo e di ri-salvarlo, potrebbero usare la stessa chiave con cui hanno letto e sovrascriverlo, oppure il server potrebbe generare una nuova chiave di accesso e utilizzare la chiave pubblica per ogni utente autorizzato per aggiornare l'altro interessato righe.

Ristabilire un utente sarebbe semplice come rimuovere la loro riga dalla tabella di mappatura user-to-entry. Se ci si preoccupa che possano aver memorizzato una o più chiavi di accesso, queste possono essere rigenerate in modo trasparente per ciascun utente rimanente senza alcun intervento da parte loro.

Sembra che la preoccupazione principale sarebbe spostarsi per garantire che i canali di comunicazione client-server fossero sicuri e che il client possa mantenere segreti i suoi segreti.

    
risposta data 05.02.2015 - 19:27
fonte
1

Per ogni database condiviso, utilizzare una chiave generata a caso per la sua crittografia. Non conservare la chiave così com'è, ma memorizzarla in tre copie (Alice ha una chiave crittografata con la sua password, Bob ha una chiave crittografata con la sua password e così via). Se Alice vuole cambiare la sua password di crittografia, prima decrittografare la sua copia chiave e quindi cifrarla con la nuova password; la chiave di crittografia generata a caso sottostante non cambia in questo scenario e le chiavi di Bob e Carl funzioneranno comunque. - Immagino che una sorta di salatura sia preferibile; se non fosse uno sarebbe facilmente in grado di rilevare se due utenti hanno scelto la stessa password personale.

Non so esattamente come verrà impostata la condivisione; dovrai trasmettere la vera chiave di crittografia da un utente all'altro senza perdite. Forse potresti dividere la chiave in due parti (XOR con una stringa casuale di cryptosafe) e condividerne una metà nel tuo sistema di database, e l'altra metà da copia e incolla dallo schermo all'e-mail?

Buona fortuna.

    
risposta data 05.02.2015 - 18:00
fonte
0

Se stai già ricodificando l'intero database su ogni scrittura, suppongo che non sarebbe un grosso passo avanti mantenere un archivio dati separato per ogni lettore (o gruppo di lettori allo stesso modo). Potrebbe rivelarsi più efficiente tenere un libro mastro di transazioni per ciascun lettore, quindi specificare anche le autorizzazioni scrivi nei metadati per ogni voce elencata / tabella a cui fare riferimento nell'autenticazione delle transazioni di scrittura.

Forse un'interfaccia simile a questa:

<writer>: <key> = <value> -> <reader>(<permissions>)

Ad esempio, questo comando identifica il writer , imposta 3 su "ciao" e definisce gli utenti autorizzati:

Alice: 3 = "hello" -> Alice(r+u+d), Bob(r)

Ciò potrebbe indurre il client di Alice a firmare la stringa di transazione sopra citata e a crittografarla due volte, una per Alice e una per Bob, prima di passare alla memoria persistente condivisa da Alice, Bob e possibilmente Carl e un utente malintenzionato. Ciascuno di Alice e Bob vedrebbero e decodificheranno la transazione, verificheranno le autorizzazioni e autenticheranno le firme, le applicheranno ai rispettivi database e ne cercheranno di nuove.

Per le autorizzazioni di gruppo, sostituisci Alice e Bob con i nomi dei gruppi sul lato destro dell'esempio e aggiungi i metadati secondo necessità (tramite lo stesso meccanismo o altro). Devono anche esserci timestamp con ogni transazione per fornire un chiaro ordine di mutazione, ma ho voluto mantenerlo semplice qui.

Descrivere essenzialmente crittografato / autenticato pub-sub , magari con serializzazioni a lungo termine del dati crittografati per ogni persona e sottoposti a backup di memoria persistente a lungo termine da parte di ciascuna persona per consentire il bootstrap rapido su nuove macchine e scoraggiare l'archiviazione a lungo termine su supporti personali meno sicuri (evitando che attraversino l'intero libro mastro delle transazioni e li elaborino tutto sequenzialmente durante il processo di sincronizzazione).

Esistono certamente sistemi come questo con un lontano approccio più efficiente / pratico già implementato all'interno di una base di codice stabilita. Non ne conosco perché non ho avuto bisogno di lavorare con un sistema come questo fino ad oggi, ma mi guarderò attorno e modificherò la risposta se la trovo. Come ultimo pensiero, dai un'occhiata a come PGP supporta più destinatari di un messaggio in un'unica codifica: potrebbe offrire alcune informazioni.

    
risposta data 05.02.2015 - 05:32
fonte

Leggi altre domande sui tag