Cascate di hash per aumentare la difficoltà computazionale

0

La domanda che sto ponendo è: c'è qualche ragione per cui il seguente metodo non rende molto più difficile per un utente malintenzionato tentare di forzare bruscamente l'input (o usare un attacco dizionario)?

Questa domanda forse non è del tutto pratica, ma è ispirata dall'idea di bcrypt, ma senza la necessità di implementare effettivamente bcrypt quando hai a portata di mano SHA. Per metterlo in contesto, tendo a usare un metodo di manipolazione delle stringhe e hashing per generare password per i siti web. Fondamentalmente, prendi una stringa segreta, diciamo, TheNameOfMyLongDeceasedHamster , aggiungi qualcosa di ovvio a un sito web TheNameOfMyLongDeceasedHamsterFacebookUserMrBoink che lo metti attraverso qualcosa come SHA256, prendi l'output binario, converti in base64 e prendi i primi 16 caratteri. Immagino che uno troverà difficile ottenere la stringa segreta anche se si conosce l'output di questo processo e l'input specifico del sito. Ho riflettuto su un metodo semplice per renderlo più costoso dal punto di vista computazionale, dal momento che non è una perdita da dire 0,25 secondi su un laptop i5 per calcolare un singolo hash in javascript, ma naturalmente se qualcuno vuole provare a trovare il TheNameOfMyLongDeceasedHamster dato l'output di questo (e forse le coppie di ricerca / sostituzione) e forse qualche tipo di attacco del dizionario, rende tutto più difficile da provare.

L'idea è un po 'ingenua e mi chiedo se ci siano dei seri inconvenienti che gli esperti di sicurezza conoscono?

L'idea è la seguente:

Passaggio 1. Prendi un testo ben noto (qualcosa che puoi facilmente trovare). Per me, prendo la Vulgata latina del Sermone sul monte, rimuovi tutti i segni di punteggiatura, converti in lettere minuscole e dividi in parole separate. Questo produce un array come

["videns","autem","jesus",...]

e si presume che ogni utente malintenzionato abbia accesso a questo testo. È importante sottolineare che ho solo bisogno di ricordare come ricostruirlo.

Passaggio 2. Specificare un numero di coppie di parole, ad es.

var wordsmap = "in:humpty et:dumpty cum:hmmm";

e convertire nel modulo

var wordsmapa = ["in:humpty","et:dumpty","cum:hmmm"];

e quindi sostituire tramite

var fluff = "videns autem jesus ...";
for(i in wordsmapa) {
   fluff = fluff.replace(wordsmapa[i][0],wordsmapa[i][1]);
}
fluffwords = fluff.split(" ");

per ottenere

["videns","autem","jesus",...]

dove alcune parole potrebbero essere state sostituite. (Il bit sostitutivo è facoltativo, ma ha degli usi, ad esempio se cambio 'jesus' nella stringa a qualunque sia il mio nome utente, semplicemente boggiando 'SecretStringtwitter' attraverso questo processo produrrà quella che sembra una bella password strong per il mio account Twitter, es. 'lG0aFybg0 / zGLPCO'.)

Passaggio 3. Prendi una funzione hash, come sha256, e itera (è ovviamente importante / utile assicurarsi che tutto sia uniforme, ad es. stringhe esadecimali o buffer di byte)

function hashcascade(x) {
    for(var i=0,l=fluffwords.length; i < l; i++) {
        var w = fluffwords[i];
        t = hash(t+w);
    }
    return t;
}

così da usare

secretstring = "TheNameOfMyLongDeceasedHamster"; // obviously this will not be in plaintext in the source, but taken from the user somehow
specificinput = "FacebookUserMrFluff";
hashinput = secretstring + specificinput
hexout = hashcascade(hashinput)
binout = hex2bin(hexout)
b64out = btoa(binout)
result = b64out.substr(0,16)

Come tale, prendi i primi 16 caratteri dalla base64 di

hash(hash(hash(...hash("SecretStringSpecificStringvidens")+"autem")+"jesus")...)

C'è qualche ragione per cui questo non rende più difficile per un utente malintenzionato tentare di forzare bruscamente l'input (o usare un attacco dizionario)?

Infine, usato in questo modo, qualsiasi modifica alla stringa segreta cambia totalmente l'output, così come qualsiasi ricerca / sostituzione sul "testo conosciuto" usato per generare l'array di parole.

Sto giocando con questo metodo per creare / ricreare password, in modo da avere un gestore di password di memorizzazione zero conciso, basandosi sulla memorizzazione di una singola stringa segreta, usando qualche intuizione intuitiva per ciò che dovrebbe essere la parola sostituzioni, e poi qualcosa ovvio come il nome di dominio del sito web. Metti tutto questo attraverso la procedura sopra, e dì 0.25 secondi dopo, la tua password.

    
posta John Allsup 24.08.2016 - 01:42
fonte

1 risposta

1

Sono molto confuso dalla tua domanda, perché da una parte menzioni bcrypt, un algoritmo di verifica della password:

This question is perhaps not entirely practical, but is inspired by the idea of bcrypt, but without needing to actually implement bcrypt when you have SHA handy.

... ma poi cambia marcia alla generazione della password:

To put it in context, I tend to use a method of string manipulation and hashing to generate passwords for websites.

Ma questi sono problemi non correlati, quindi una soluzione per uno non è necessariamente applicabile all'altra.

Ma in ogni caso, per quanto posso dire dalla tua spiegazione, stai proponendo un sistema per generare le password derivate in modo deterministico da questi input:

  1. Una password principale segreta;
  2. Un identificatore pubblico per la password derivata (ad esempio FacebookUserMrFluff );
  3. Alcuni parametri pubblici aggiuntivi (la lista di parole e le sostituzioni).

Un problema qui è che, poiché lo schema è completamente deterministico, un intruso che è in grado di ottenere una hash + salt pair per una delle password derivate (o una password in chiaro da un sito come uno qualsiasi di questi ) può quindi montare un attacco di forza bruta per recuperare la password principale. E se ci riescono, possono calcolare tutte le password derivate, passate, presenti e future .

Forse iterando la funzione di hash molte volte aumenta il costo dell'attacco a forza bruta contro il tuo schema. Ma perché permettere un simile attacco? Confronta con questo banale bit di consigli sulla gestione delle password utente:

  • Utilizza password generate a caso di buona lunghezza;
  • memorizzali in un gestore di password crittografato.

In questo caso, poiché le password sono generate casualmente, sono tutte indipendenti -un utente malintenzionato che ne crepa una non può sfruttarle per trovare un'altra password. Un utente malintenzionato dovrebbe rubare il tuo database delle password per lanciare un attacco di forza bruta contro le tue altre password, mentre nel tuo schema ha solo bisogno di una singola password derivata.

Oltre a questo, se hai "SHA a portata di mano" esiste già una soluzione di hashing per password standard iterata: PBDKF2 . Quindi, anche se hai insistito nell'usare questo metodo discutibile per generare password derivate deterministicamente, non è necessario ricorrere al tuo algoritmo dispari.

    
risposta data 24.08.2016 - 02:51
fonte

Leggi altre domande sui tag