Un sistema su cui sto lavorando accetta come input un numero di conto cliente e deve generare un token basato su di esso. Non è consentito archiviare il testo in chiaro del numero di conto stesso, pertanto l'obiettivo del token è il seguente:
- Impossibile essere invertito nel numero di conto.
- Può essere usato per cercare e identificare in modo univoco un record di metadati dell'account nel nostro database.
I numeri di conto assomigliano ai numeri delle carte di credito. Sono lunghe stringhe numeriche a 16 cifre; i primi 4 caratteri sono costanti; l'ultimo carattere è una cifra di controllo calcolabile. Ciò significa che la dimensione effettiva dell'insieme di input è una stringa numerica di 11 caratteri: 99.999.999.999 possibili permutazioni.
Ho pensato ai metodi seguenti. Assumere hash significa sufficientemente lento hash sicuro quale alta iterazione PBKDF2, bcrypt o Argon2 e cifrare significa AES256.
1. Hash semplice
hash(account_num)
Pur essendo semplice, questo approccio è facilmente reversibile tramite la forza bruta ed è vulnerabile alle tabelle arcobaleno.
2. Hash salato per account
hash(salt + account_num)
Questo approccio corregge la vulnerabilità alle tabelle arcobaleno, tuttavia, a causa delle dimensioni limitate del set di input è ancora facile da annullare tramite brute-force.
3. Hash salato per utente crittografato con Global Pepper
encrypt(hash( salt + account_num ), pepper)
Questo è basato su di Dropbox memorizzazione delle password meccanismo . L'inversione tramite brute-force richiede la perdita sia dei blob crittografati che della chiave di crittografia. Tuttavia, poiché la crittografia dello stesso valore due volte con la stessa chiave genera diversi blob di output, ciò interrompe la possibilità di selezionare un account dal database per numero di account.
4. Approccio ibrido
- Memorizza le ultime 4 cifre del numero di conto in testo semplice.
- Memorizzato l'intero numero di conto come hash salato crittografato con pepe.
- Utilizza AWS KMS per la crittografia hash per ridurre le probabilità di perdita di una chiave.
Cosa questo compie:
- Possiamo cercare gli account utilizzando le ultime 4 cifre del numero di conto. Basandosi sul controllo di alcune migliaia di numeri di conto, questa selezione tornerà tra 1-3 possibili account.
- Fai scorrere su ciascuna delle possibili corrispondenze dell'account ...
- Decrittografa l'hash del numero di conto per l'account.
- Confronta l'hash decrittografato con il numero dell'account di input.
- Interrompi l'iterazione non appena troviamo un hash corrispondente (utilizza questa riga account) o esaurisci gli account (crea una nuova riga account).
La mia domanda: l'approccio 4 ha davvero senso? Per la sicurezza extra che fornisce, è eccessivamente complicato? Ha dei difetti a cui non ho pensato? Soprattutto, c'è un modo più semplice per risolvere questo problema?