diff --git a/database/salt_store.cpp b/database/salt_store.cpp new file mode 100644 index 0000000..e9ca878 --- /dev/null +++ b/database/salt_store.cpp @@ -0,0 +1,63 @@ +#include "salt_store.h" +#include +#include +#include +#include +#include + +SaltStore::SaltStore(uint64_t key_lifetime, size_t salt_size, std::string secret) { + this->key_lifetime = key_lifetime; + this->salt_size = salt_size; + this->secret = secret; +} + +std::string SaltStore::getSalt() { + expireKeys(); + char bfr[salt_size]; + FILE * rand_in = fopen("/dev/urandom", "r"); + if(!rand_in) { + fprintf(stderr, "Could not open /dev/urandom!\n"); + return ""; + } + if(salt_size != fread(bfr, sizeof(char), salt_size, rand_in)) { + fclose(rand_in); + fprintf(stderr, "Could not read from /dev/urandom!\n"); + return ""; + } + fclose(rand_in); + + // zero-terminated strings suck + for(unsigned int i=0;i((uint64_t)time(NULL), SHA1Hash(salt + secret))); + return salt; +} + +bool SaltStore::consumeKey(std::string key) { + expireKeys(); + SHA1Hash h; + h.fromHex(key); + std::list >::iterator p; + for(p = valid_keys.begin();p != valid_keys.end(); ++p) { + if(p->second == h) { + valid_keys.erase(p); + return true; + } + } + return false; +} + +void SaltStore::expireKeys() { + std::list >::iterator p; + uint64_t cur_t = (uint64_t)time(NULL); + for(p = valid_keys.begin();p != valid_keys.end();++p) { + if((cur_t - p->first) > key_lifetime) + p = valid_keys.erase(p); + } +} + diff --git a/database/salt_store.h b/database/salt_store.h new file mode 100644 index 0000000..ea34d15 --- /dev/null +++ b/database/salt_store.h @@ -0,0 +1,25 @@ +#ifndef _SALT_STORE_H_ +#define _SALT_STORE_H_ +#include "sha1.h" +#include +#include + +class SaltStore { + +public: + SaltStore(uint64_t key_lifetime, size_t salt_size, std::string secret); + ~SaltStore(); + std::string getSalt(); + bool consumeKey(std::string key); + +private: + void expireKeys(); + std::list > valid_keys; + uint64_t key_lifetime; + size_t salt_size; + std::string secret; + +}; + +#endif +