Criptografía C ++: Parte 3-pbkdf2
Buscando bibliotecas criptográficas modernas.
No se pudo encontrar nada bueno.
Sé que probablemente hice todo mal, así que trabaja conmigo aquí. Habrá cuatro revisiones diferentes para cuatro estructuras que se basan entre sí:
- Hashing
- Clave hash
- Clave de contraseña
- Respuesta al desafío salado
Esta revisión es para una implementación de pbkdf2. Esta es una forma de usar HMAC que le permite hacer incrementalmente más caro crear el hash en fallas. La idea es que puedes ralentizar los ataques haciendo que sea más difícil hacer muchas conjeturas.
Las estructuras de datos y la implementación que se presentan en estas preguntas se basan en RFC2104 y en esta publicación sobre codeproject .
Ejemplo de uso
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
Respuestas
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)
"Un longan inty un std::size_ttodos entraron en un bar ..." ¿No podrían ser todos std::size_t?
Además, anular la loopvariable es innecesariamente confuso.
std::copy(std::begin(tmp), std::end(tmp), std::begin(digest));
Siento que esto podría ser digest = tmp;con un operador de asignación apropiado.
salt + "\x00\x00\x00\x01"s
¿Podría ser una constante con nombre (o incluso una función con nombre)? O tal vez agregue un comentario para explicar por qué está aquí.
digest[loop] = digest[loop] ^ tmp[loop];
Nitpick: podría usar ^=
¿Quizás la salida debería ser un valor de retorno, no escrito en una referencia?
No sé lo suficiente sobre criptografía / seguridad para evaluar los aspectos de algoritmo / seguridad de esto.