PSK Database¶
Added in version 2.4.0.
Many applications need to store pre-shared keys (hereafter PSKs) for authentication purposes.
An abstract interface to PSK stores, along with some implementations
of same, are provided in psk_db.h
-
class PSK_Database¶
-
bool is_encrypted() const¶
Returns true if (at least) the PSKs themselves are encrypted. Returns false if PSKs are stored in plaintext.
-
std::set<std::string> list_names() const¶
Return the set of valid names stored in the database, ie values for which
get
will return a value.
-
void set(const std::string &name, const uint8_t psk[], size_t psk_len)¶
Save a PSK. If
name
already exists, the current value will be overwritten.
-
secure_vector<uint8_t> get(const std::string &name) const¶
Return a value saved with
set
. Throws an exception ifname
doesn’t exist.
-
void remove(const std::string &name)¶
Remove
name
from the database. Ifname
doesn’t exist, ignores the request.
-
void set_str(const std::string &name, const std::string &psk)¶
Like
set
but accepts the psk as a string (eg for a password).
-
bool is_encrypted() const¶
The same header also provides a specific instantiation of PSK_Database
which
encrypts both names and PSKs. It must be subclassed to provide the storage.
-
class Encrypted_PSK_Database : public PSK_Database¶
-
Encrypted_PSK_Database(const secure_vector<uint8_t> &master_key)¶
Initializes or opens a PSK database. The master key is used the secure the contents. It may be of any length. If encrypting PSKs under a passphrase, use a suitable key derivation scheme (such as PBKDF2) to derive the secret key. If the master key is lost, all PSKs stored are unrecoverable.
Both names and values are encrypted using NIST key wrapping (see NIST SP800-38F) with AES-256. First the master key is used with HMAC(SHA-256) to derive two 256-bit keys, one for encrypting all names and the other to key an instance of HMAC(SHA-256). Values are each encrypted under an individual key created by hashing the encrypted name with HMAC. This associates the encrypted key with the name, and prevents an attacker with write access to the data store from taking an encrypted key associated with one entity and copying it to another entity.
Names and PSKs are both padded to the next multiple of 8 bytes, providing some obfuscation of the length.
One artifact of the names being encrypted is that is is possible to use multiple different master keys with the same underlying storage. Each master key will be responsible for a subset of the keys. An attacker who knows one of the keys will be able to tell there are other values encrypted under another key, but will not be able to tell how many other master keys are in use.
-
virtual void kv_set(const std::string &index, const std::string &value) = 0¶
Save an encrypted value. Both
index
andvalue
will be non-empty base64 encoded strings.
-
virtual std::string kv_get(const std::string &index) const = 0¶
Return a value saved with
kv_set
, or return the empty string.
-
virtual void kv_del(const std::string &index) = 0¶
Remove a value saved with
kv_set
.
-
virtual std::set<std::string> kv_get_all() const = 0¶
Return all active names (ie values for which
kv_get
will return a non-empty string).
-
Encrypted_PSK_Database(const secure_vector<uint8_t> &master_key)¶
A subclass of Encrypted_PSK_Database
which stores data in a SQL database
is also available.
-
class Encrypted_PSK_Database_SQL : public Encrypted_PSK_Database¶
Creates or uses the named table in
db
. The SQL schema of the table is(psk_name TEXT PRIMARY KEY, psk_value TEXT)
.