Implement the KDF
This commit is contained in:
parent
c9defbaafe
commit
900c7b4c93
2
Makefile
2
Makefile
|
@ -8,7 +8,7 @@ CFLAGS ?= -std=gnu11 -Os -g -Wall -Wextra -Werror -pedantic
|
|||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
all: puer.o
|
||||
all: puer
|
||||
|
||||
puer: puer.o
|
||||
$(CC) $(LDFLAGS) -o $@ $<
|
||||
|
|
53
puer.c
53
puer.c
|
@ -1,5 +1,6 @@
|
|||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void xxtea128(uint32_t const key[4], uint32_t block[4]) {
|
||||
|
@ -249,11 +250,53 @@ void hmac(unsigned char output[32], unsigned char key[], size_t keylen, unsigned
|
|||
finalize_hash(&state, output);
|
||||
}
|
||||
|
||||
// KDF_ROUNDS must be at least 2
|
||||
#define KDF_ROUNDS 100000
|
||||
unsigned char kdf_buf[KDF_ROUNDS * 32];
|
||||
void kdf(unsigned char key[16], unsigned char salt[32], unsigned char passphrase[], size_t passphraselen) {
|
||||
// This is based on the design of PBKDF2 but aims to be memory hard
|
||||
// This is achieved by storing all the hashes in a buffer and the
|
||||
// in the end hashing them together in reverse order, instead of
|
||||
// just xoring together.
|
||||
//
|
||||
// The memory-hardness of this scheme rests of the assumption that
|
||||
// it is not feasible to compute the final hash backwards, that is,
|
||||
// starting with the first hash and working towards the final hash.
|
||||
// While I cannot prove this to be the case, the fact that our hash
|
||||
// is made out of a one-way compression function makes me
|
||||
// relatively confident in it.
|
||||
|
||||
// Place the hash of the salt at the top of the buffer. We do not
|
||||
// include the counter i from PBKDF2 since we will ever only
|
||||
// produce one block of output
|
||||
size_t index = KDF_ROUNDS*32 - 32;
|
||||
hmac(&kdf_buf[index], passphrase, passphraselen, salt, 32);
|
||||
index -= 32;
|
||||
|
||||
// Walk back along the buffer, at each step hashing the previous
|
||||
// hashes
|
||||
while (index > 0) {
|
||||
hmac(&kdf_buf[index], passphrase, passphraselen, &kdf_buf[index+32], 32);
|
||||
index -= 32;
|
||||
}
|
||||
hmac(kdf_buf, passphrase, passphraselen, &kdf_buf[32], 32);
|
||||
|
||||
// Perform the final hash
|
||||
unsigned char final_hash[32];
|
||||
hmac(final_hash, passphrase, passphraselen, kdf_buf, KDF_ROUNDS * 32);
|
||||
|
||||
// Use first 128 bits of final hash as the key
|
||||
memcpy(key, final_hash, 16);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
unsigned char hashed[32];
|
||||
unsigned char key[] = "12345678901234567899";
|
||||
unsigned char message[] = "barbaz";
|
||||
hmac(hashed, key, sizeof(key)-1, message, sizeof(message)-1);
|
||||
for (size_t i = 0; i < 32; i++) {printf("%02hhx ", hashed[i]);}printf("\n"); //debg
|
||||
unsigned char key[16] = {0};
|
||||
unsigned char salt[32] = "seasaltrocksalt seasaltrocksalt";
|
||||
unsigned char passphrase[] = "a quick brown fox jumps over the lazy dog";
|
||||
kdf(key, salt, passphrase, sizeof(passphrase) - 1);
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
printf("%02hhx ", key[i]);
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue