Ho scritto un framework di autenticazione basato su database per le applicazioni web che sto programmando di programmare in futuro.
Il framework è implementato usando il linguaggio plpgsql di un database PostgreSQL e quindi l'estensione pgcrypto è usata per crittografare le informazioni sensibili.
Se l'utente di una webapp autentica (quindi il webserver attiva sth.) come
select authenticate('[email protected]', 'login-token')
il database restituisce
False, Invalid user / login token
o
True, Successfully logged in, session-id
L'ID di sessione viene trasmesso al server web in chiaro, quindi è possibile creare un cookie, mentre viene salvato nel database applicando un algoritmo di hashing, che viene fornito con pgcrypto-extension. Questa è una specie di implementazione di bcrypt (la Documentazione di PostgreSQL è piuttosto vaga). L'ID di sessione è combinato con un sale unico (uno per ID di sessione).
Quindi nel tavolo delle sessioni trovi sth. come
|primary key|user-id|bcrypt(session-id)|other information
La domanda riguarda la funzione utilizzata per verificare se l'ID di sessione è valido e di quale utente si tratta. Questa funzione viene attivata quando l'utente presenta un id di sessione al server web, che a sua volta convalida questo id di sessione.
select get_user_by_session_id(session-id)
Se non c'è alcun identificatore aggiuntivo la parte di selezione ha il seguente problema:
Per ogni riga nella tabella di sessione la funzione hash deve essere applicata all'ID di sessione specificato.
Funziona come
- seleziona una riga della tabella di sessione
- legge salt e hash l'id di sessione data dall'utente
- confronta il risultato con l'hash della riga effettiva
- ripeti fino a quando trovi una corrispondenza (restituisce True) o la fine della tabella viene raggiunta senza alcuna corrispondenza (restituisci False)
Questo è un po 'lento (più lento se ci sono più sessioni).
Quindi l'idea è di usare un identificatore, che non è sensibile a fare quanto segue (pseudocodice)
- seleziona get_user_by_session_id (user-given-dentifier, session_id)
- seleziona l'hash dalla tabella di sessione dove identificatore = identificatore fornito dall'utente
- controlla se hash_function (session_id) = hash
Questo ha il vantaggio, che è necessaria una sola operazione di crittografia, anziché una per ogni riga nella tabella di sessione finché non viene trovata quella valida.
Nel progetto attuale ci sono due possibili identificatori che potrei dare all'utente.
- Un member_key statico univoco che viene generato alla registrazione per ciascun utente.
- Il sale utilizzato per crittografare / hash l'ID di sessione
Vorrei andare per il sale, perché volevo usare il membro_key per scopi di identificazione (chiamate di supporto) o qualcos'altro. Non vedo alcun problema con questo, a causa dei seguenti motivi:
- in generale il sale non deve essere crittografato e può essere salvato in testo semplice
- solo il server web e l'utente stesso vedono il sale (server web durante la trasmissione, utente nel cookie)
- solo l'attaccante può ottenere questo sale intercettando la connessione - se lo fa, ottiene anche l'id di sessione in testo semplice
Mi manca qualcosa? Il member_key statico ha qualche vantaggio rispetto a salt?