C ++ Crypto: Teil 3-pbkdf2

Aug 26 2020

Suchen Sie nach modernen Crypto-Bibliotheken.
Konnte nichts Gutes finden.

Ich weiß, dass ich das wahrscheinlich alles falsch gemacht habe, also arbeite hier mit mir. Es gibt vier verschiedene Überprüfungen für vier Strukturen, die aufeinander aufbauen:

  1. Hashing
  2. Hashed Key
  3. Passwortschlüssel
  4. Antwort auf gesalzene Herausforderung

Diese Überprüfung bezieht sich auf eine Implementierung der Implementierung von pbkdf2. Dies ist eine Möglichkeit, HMAC zu verwenden, mit der Sie die Erstellung des Hash bei Fehlern schrittweise verteuern können. Die Idee ist, dass Sie Angriffe verlangsamen können, indem Sie es schwieriger machen, viele Vermutungen anzustellen.

Die in diesen Fragen vorgestellten Datenstrukturen und Implementierungen basieren auf RFC2104 und diesem Beitrag zum Codeprojekt .

Anwendungsbeispiel

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

Antworten

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 longein intund std::size_talle in eine Bar ging ...“ konnten sie nicht alle sein std::size_t?

Das Überschreiben der loopVariablen ist außerdem unnötig verwirrend.


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

Ich denke, dies könnte nur digest = tmp;mit einem geeigneten Zuweisungsoperator geschehen.


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

Könnte dies eine benannte Konstante (oder sogar eine benannte Funktion) sein? Oder fügen Sie einen Kommentar hinzu, um zu erklären, warum dies hier ist.


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

Nitpick: könnte gebrauchen ^=


Vielleicht sollte die Ausgabe ein Rückgabewert sein, der nicht in eine Referenz geschrieben wird?


Ich weiß nicht genug über Kryptographie / Sicherheit, um den Algorithmus / die Sicherheitsaspekte davon zu bewerten.