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: สามารถใช้ได้ ^=


บางทีผลลัพธ์ควรเป็นค่าส่งกลับไม่ใช่เขียนอ้างอิง?


ฉันไม่รู้เพียงพอเกี่ยวกับการเข้ารหัส / ความปลอดภัยเพื่อประเมินอัลกอริทึม / แง่มุมด้านความปลอดภัยของสิ่งนี้