Browse Source

pbkdf2: Reuse common hash state between iterations

master
Daniel Scharrer 1 year ago
parent
commit
5545a515ea
  1. 30
      src/crypto/pbkdf2.hpp

30
src/crypto/pbkdf2.hpp

@ -43,36 +43,35 @@ namespace crypto {
template <typename T>
struct hmac {
typedef typename T::state_t state_t;
enum constants {
block_size = T::block_size,
hash_size = T::hash_size * sizeof(typename T::hash_word),
};
void init(const char ikey[block_size]) {
inner.init();
inner.update(ikey, block_size);
void init(const state_t istate) {
inner.init(istate, 1);
}
void update(const char * data, size_t length) {
inner.update(data, length);
}
void finalize(const char okey[block_size], char mac[hash_size]) {
void finalize(const state_t ostate, char mac[hash_size]) {
char buffer[hash_size];
inner.finalize(buffer);
T outer;
outer.init();
outer.update(okey, block_size);
outer.init(ostate, 1);
outer.update(buffer, hash_size);
outer.finalize(mac);
}
static void prepare_key(const char * password, size_t length,
char ikey[block_size], char okey[block_size]) {
static void prepare_state(const char * password, size_t length, state_t istate, state_t ostate) {
char ikey[block_size], okey[block_size];
if(length > block_size) {
T hash;
hash.init();
@ -89,6 +88,9 @@ struct hmac {
ikey[i] = char(boost::uint8_t(ikey[i]) ^ boost::uint8_t(0x36));
}
T::prepare_state(ikey, 1, istate);
T::prepare_state(okey, 1, ostate);
}
private:
@ -110,8 +112,8 @@ struct pbkdf2 {
static void derive(const char * password, size_t password_length, const char * salt, size_t salt_length,
size_t iterations, char * key, size_t key_length) {
char ikey[block_size], okey[block_size];
hmac_t::prepare_key(password, password_length, ikey, okey);
typename hmac_t::state_t istate, ostate;
hmac_t::prepare_state(password, password_length, istate, ostate);
for(size_t block = 1; key_length > 0; block++) {
@ -119,19 +121,19 @@ struct pbkdf2 {
{
char b[4] = { char(block >> 24), char(block >> 16), char(block >> 8), char(block) };
hmac_t mac;
mac.init(ikey);
mac.init(istate);
mac.update(salt, salt_length);
mac.update(b, sizeof(b));
mac.finalize(okey, u);
mac.finalize(ostate, u);
}
char f[hash_size];
std::memcpy(f, u, hash_size);
for(size_t i = 1; i < iterations; i++) {
hmac_t mac;
mac.init(ikey);
mac.init(istate);
mac.update(u, hash_size);
mac.finalize(okey, u);
mac.finalize(ostate, u);
for(size_t j = 0; j < hash_size; j++) {
f[j] = char(boost::uint8_t(f[j]) ^ boost::uint8_t(u[j]));
}

Loading…
Cancel
Save