C ++ Crypto: Parte 3-pbkdf2

Aug 26 2020

Alla ricerca di moderne librerie Crypto.
Impossibile trovare niente di buono.

So che probabilmente ho sbagliato tutto, quindi lavora con me qui. Ci saranno quattro diverse revisioni per quattro strutture che si basano l'una sull'altra:

  1. Hashing
  2. Chiave con hash
  3. Chiave password
  4. Risposta alla sfida salata

Questa recensione è per un'implementazione dell'implementazione di pbkdf2. Questo è un modo di utilizzare HMAC che ti consente di rendere incrementalmente più costoso la creazione dell'hash in caso di errori. L'idea è che puoi rallentare gli attacchi rendendo più difficile fare molte ipotesi.

Le strutture dati e l'implementazione presentate in queste domande si basano su RFC2104 e questo post su codeproject .

Esempio di utilizzo

Digest<Pbkdf2<HMac<Sha1>>>    digest;
Pbkdf2<HMac<Sha1>>            pbkdf2;

pbkdf2.hash("The password", "A Salt", 2048, digest);

pbkdf2.h

#ifndef THORS_ANVIL_CRYPTO_PBKDF2_H
#define THORS_ANVIL_CRYPTO_PBKDF2_H

#include "hmac.h"
#include <string>

// RFC-2898 PKCS #5: Password-Based Cryptography Specification Version 2.0

namespace ThorsAnvil::Crypto
{

// Look in hmac.h for good examples of PRF
// ThorsAnvil::Crypto::HMac
template<typename PRF>
struct Pbkdf2
{
    static constexpr std::size_t digestSize = PRF::digestSize;
    using DigestStore    = typename PRF::DigestStore;

    void hash(std::string const& password, std::string const& salt, long iter, DigestStore& digest)
    {
#pragma vera-pushoff
        using namespace std::string_literals;
#pragma vera-pop
        PRF             prf;
        DigestStore     tmp;

        prf.hash(password, salt + "\x00\x00\x00\x01"s, tmp);
        std::copy(std::begin(tmp), std::end(tmp), std::begin(digest));

        for (int loop = 1; loop < iter; ++loop)
        {
            prf.hash(password, tmp.view(), tmp);
            for (std::size_t loop = 0; loop < digestSize; ++loop)
            {
                digest[loop] = digest[loop] ^ tmp[loop];
            }
        }
    }
};

}

#endif

Risposte

1 user673679 Nov 16 2020 at 03:47
void hash(std::string const& password, std::string const& salt, long iter, DigestStore& digest)
...
for (int loop = 1; loop < iter; ++loop)
        ...
        for (std::size_t loop = 0; loop < digestSize; ++loop)

"A longun inte std::size_ttutti entrati in un bar ..." non poteva che essere tutti std::size_t?

Inoltre, l'override della loopvariabile crea inutilmente confusione.


    std::copy(std::begin(tmp), std::end(tmp), std::begin(digest));

Penso che questo potrebbe essere solo digest = tmp;con un operatore di assegnazione appropriato.


salt + "\x00\x00\x00\x01"s

Potrebbe essere una costante con nome (o anche una funzione con nome)? O magari aggiungi un commento per spiegare perché è qui.


            digest[loop] = digest[loop] ^ tmp[loop];

Nitpick: potrebbe usare ^=


Forse l'output dovrebbe essere un valore di ritorno, non scritto in un riferimento?


Non ne so abbastanza di crittografia / sicurezza per valutare gli aspetti algoritmo / sicurezza di questo.