C ++ Crypto: часть 3-pbkdf2

Aug 26 2020

Ищу современные библиотеки Crypto.
Не нашел ничего хорошего.

Я знаю, что, вероятно, сделал все неправильно, поэтому работайте со мной здесь. Будет четыре разных обзора четырех структур, которые опираются друг на друга:

  1. Хеширование
  2. Хешированный ключ
  3. Ключ пароля
  4. Ответ на соленый вызов

Этот обзор посвящен реализации реализации pbkdf2. Это способ использования HMAC, который позволяет постепенно увеличивать затраты на создание хэша при сбоях. Идея заключается в том, что вы можете замедлить атаки, усложнив много предположений.

Структуры данных и реализация, представленные в этих вопросах, основаны на RFC2104 и этой публикации на codeproject .

Пример использования

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

Ответы

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)

«А и все ходили в бар ...» они не могли быть все ?longintstd::size_tstd::size_t

Кроме того, переопределение loopпеременной излишне сбивает с толку.


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

Я чувствую, что это могло быть просто digest = tmp;с подходящим оператором присваивания.


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

Может ли это быть именованной константой (или даже именованной функцией)? Или, может быть, добавьте комментарий, чтобы объяснить, почему это здесь.


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

Nitpick: можно использовать ^=


Возможно, вывод должен быть возвращаемым значением, а не записанным в ссылку?


Я недостаточно знаю о криптографии / безопасности, чтобы оценить аспекты алгоритма / безопасности.