C ++ Crypto: Parte 3-pbkdf2
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:
- Hashing
- Chiave con hash
- Chiave password
- 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
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.