Revisione dell'implementazione - Chiave indipendente, lato amministratore e lato utente

1

L'amministratore del sito web deve leggere i dati dell'utente. Quindi, se la chiave è derivata dal passaggio utente, l'amministratore deve conoscere il passaggio utente, non esattamente una buona idea.

Il seguente schema di crittografia è stato gentilmente suggerito da Polynomial.

In sostanza, ciò che stai tentando di fare è mettere in backdoor l'account di ciascun utente in modo tale che solo l'utente e un singolo utente amministrativo possano accedere ai propri dati. Questo può essere ottenuto come segue:

us  = User salt  = Random unique value (not the same salt as used for authentication)
as  = Admin salt = Random unique value (not the same salt as used for authentication)

uk  = User key    = pbkdf2(user_pass, us, 256, rounds)
dk  = Data key    = random 256-bit key
ak  = Admin key   = pbkdf2(admin_pass, as, 256, rounds)
P   = RSA private key
p   = RSA public key

uk' = Encrypted user key    = dk ^ uk
dk' = Encrypted data key    = RSA_Encrypt(dk, p)
P'  = Encrypted private key = AES_Encrypt(P, ak)

m = message
iv = initialisation vector (random unique value)
c = ciphertext = AES_Encrypt(m, iv, dk)

Quindi archiviamo uk ', dk' e iv con il set di dati che stiamo crittografando. Ci archiviamo con il record dell'account utente. Memorizziamo anche P 'e come con il nostro record dell'account amministratore. La chiave pubblica P può essere memorizzata nel codice. La coppia di chiavi è comune tra i record.

La decrittazione dell'utente funziona come segue:

Compute uk from the user password and us.
Xor uk' with uk to retrieve dk.
Decrypt c using iv and dk, giving us m.

La decrittazione dell'amministratore funziona come segue (la chiave privata è archiviata offline):

Compute ak from the admin password and as.
Decrypt P using AES_Decrypt(P', ak)
Decrypt dk using RSA_Decrypt(dk', P)
Decrypt c using iv and dk, giving us m.

Ho cercato di implementare lo schema di Polynomial in PHP: questo è il risultato . Ora vorrei sapere se la mia implementazione è corretta e se è sicura.

Grazie mille per il tuo aiuto molto utile!

    
posta Surfer on the fall 16.01.2013 - 22:50
fonte

1 risposta

1

Questo non è diverso da uno schema che ho posto in questa domanda , che ha preso qualche derisione eccessivamente complessa. La tua è più semplice (perché l'autenticazione dell'utente viene gestita separatamente e qui viene trattata solo la sicurezza / il recupero dei dati dell'utente), ma c'è ancora parecchio da fare qui con la crittografia delle chiavi di crittografia in più modi. Necessario, probabilmente, ma comunque complesso.

Suggerirei due cambiamenti. Innanzitutto, la chiave privata RSA, invece di essere offuscata dietro le credenziali di un singolo account amministratore, potrebbe essere archiviata offline. Suppongo qui che il ripristino dei dati utente non sia un evento quotidiano, se è necessario un amministratore per farlo (gli amministratori hanno cose migliori da fare tutto il giorno che recuperare gli account utente). Quindi, quando è necessario che accada, un utente con privilegi di amministratore potrebbe recuperare un HSM (o una pen drive con il file di chiavi se è a buon mercato) dall'archivio protetto fisicamente e utilizzarlo con un programma offline (non parte del App PHP) per decrittografare i dati dell'utente.

Il vantaggio qui è che non dipende da un account amministratore comune, e quindi non richiede un account amministratore comune, evitando l'inevitabilità che le credenziali dell'account amministratore vengano scritte e successivamente cadano nelle mani "nemiche" . La chiave e / o il programma di ripristino sarebbero comunque accessibili solo a qualcuno con privilegi di amministratore, che userebbe le proprie credenziali di accesso personali per ottenere la chiave dalla memoria e accedere al programma. Questo ti dà anche la possibilità di una pista di controllo; sai esattamente quali credenziali sono state usate per estrarre la chiave ed eseguire il programma, quindi se c'è un sospetto compromesso puoi restringere la ricerca.

Puoi implementare qualsiasi pompa e circostanza aggiuntiva che ritieni necessaria per recuperare e utilizzare la chiave privata; Assicurati solo che le misure non siano così draconiane da far sì che gli utenti vogliano eluderle (o alternativamente, assicurati che le misure evitino fisicamente impedire l'elusione, che di solito richiede alcuni seri $$$).

In secondo luogo, vorrei anche memorizzare p nel livello dati, non nel codice. Mi rendo conto che questo schema è in atto in un sito PHP, e quindi c'è solo un posto dove pubblicare una modifica del codice che aggiorna la chiave pubblica. Tuttavia, dovrebbe la chiave pubblica deve essere modificata, IMO è ancora più facile andare nel DB e aggiornarlo piuttosto che pubblicare la modifica del codice, e non è molto più difficile ottenere la chiave pubblica (che è, ancora una volta, apparentemente non estremamente comune, sarebbe necessario solo quando dk di un utente è cambiato, e anche se questo cambia ogni sessione è una query DB banale da fare).

Ovviamente, cambiando p nel primo luogo, ogni dk' verrà crittografato con una precedente p obsoleta. Esistono diversi modi per attenuarlo:

  • Decrittografare e crittografare nuovamente la chiave dati di ogni utente ogni volta che cambia la coppia di chiavi RSA.
  • Memorizza il "numero di revisione" della chiave RSA utilizzato per crittografare la chiave dati di un utente, con il numero di revisione corrente memorizzato insieme alla chiave pubblica corrente e conservare diverse revisioni passate di chiavi private nella memoria.
    • Abbinato a costringere gli utenti a cambiare la propria password ogni 90 giorni (rigenerando e ricodificando le proprie chiavi dati) il numero di vecchie chiavi che dovresti conservare dovrebbe essere piuttosto basso.
  • costringere gli utenti a cambiare le loro password quando la coppia di chiavi RSA cambia, ripristinando e ricodificando le loro chiavi di dati con la nuova chiave pubblica.
risposta data 17.01.2013 - 00:18
fonte

Leggi altre domande sui tag