Crypto C ++: Partie 3-pbkdf2

Aug 26 2020

À la recherche de bibliothèques Crypto modernes.
Je n'ai rien trouvé de bon.

Je sais que j'ai probablement mal fait tout cela, alors travaillez avec moi ici. Il y aura quatre revues différentes pour quatre structures qui s'appuient les unes sur les autres:

  1. Hashing
  2. Clé hachée
  3. Clé de mot de passe
  4. Réponse au défi salé

Cette revue concerne une implémentation de l'implémentation pbkdf2. C'est une façon d'utiliser HMAC qui vous permet de rendre progressivement plus cher la création du hachage en cas d'échec. L'idée est que vous pouvez ralentir les attaques en rendant plus difficile de faire beaucoup de suppositions.

Les structures de données et l'implémentation présentées dans ces questions sont basées sur RFC2104 et cet article sur codeproject .

Exemple d'utilisation

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

Réponses

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)

"Un longan intet un std::size_ttous sont entrés dans un bar ..." ne pourraient-ils pas tous être std::size_t?

En outre, le remplacement de la loopvariable est inutilement déroutant.


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

J'ai l'impression que cela pourrait simplement être digest = tmp;avec un opérateur d'affectation approprié.


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

Cela pourrait-il être une constante nommée (ou même une fonction nommée)? Ou peut-être ajouter un commentaire pour expliquer pourquoi c'est ici.


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

Nitpick: pourrait utiliser ^=


Peut-être que la sortie devrait être une valeur de retour, pas écrite dans une référence?


Je ne connais pas assez la cryptographie / la sécurité pour en évaluer les aspects algorithme / sécurité.