C ++ Crypto: Phần 3-pbkdf2
Tìm kiếm xung quanh các thư viện Crypto hiện đại.
Không thể tìm thấy bất cứ điều gì tốt.
Tôi biết có lẽ tôi đã làm điều này sai hoàn toàn vì vậy hãy làm việc với tôi ở đây. Sẽ có bốn đánh giá khác nhau cho bốn cấu trúc xây dựng dựa trên nhau:
- Băm
- Khoá băm
- Khóa mật khẩu
- Phản ứng thử thách muối
Đánh giá này là để triển khai việc triển khai pbkdf2. Đây là một cách sử dụng HMAC cho phép bạn tăng dần chi phí để tạo băm khi thất bại. Ý tưởng là bạn có thể làm chậm các cuộc tấn công bằng cách khó đoán nhiều hơn.
Cấu trúc dữ liệu và cách triển khai được trình bày trong những câu hỏi này dựa trên RFC2104 và bài đăng này trên codeproject .
Ví dụ sử dụng
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
Trả lời
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 longan intand a std::size_tall walk into a bar ..." không phải tất cả đều như std::size_tvậy sao?
Ngoài ra, việc ghi đè loopbiến gây nhầm lẫn không cần thiết.
std::copy(std::begin(tmp), std::end(tmp), std::begin(digest));
Tôi cảm thấy như điều này có thể chỉ digest = tmp;với một toán tử gán thích hợp.
salt + "\x00\x00\x00\x01"s
Đây có thể là một hằng số được đặt tên (hoặc thậm chí là một hàm được đặt tên)? Hoặc có thể thêm một bình luận để giải thích lý do tại sao điều này ở đây.
digest[loop] = digest[loop] ^ tmp[loop];
Nitpick: có thể sử dụng ^=
Có lẽ đầu ra phải là một giá trị trả về, không được ghi vào một tham chiếu?
Tôi không biết đủ về mật mã / bảo mật để đánh giá các khía cạnh thuật toán / an toàn của điều này.