pgLab/core/PasswordManager.cpp

181 lines
4.6 KiB
C++
Raw Normal View History

#include "PasswordManager.h"
//#include <botan/filters.h>
//#include <botan/pipe.h>
//#include <botan/sha2_64.h>
//#include <botan/hash.h>
//#include <botan/hmac.h>
//#include <botan/pbkdf2.h>
//#include <botan/rng.h>
//#include <botan/base64.h>
//#include <botan/loadstor.h>
//#include <botan/mem_ops.h>
#include <botan/auto_rng.h>
#include <botan/base64.h>
#include <botan/psk_db_sql.h>
#include <botan/sqlite3.h>
#include <botan/scrypt.h>
#include <boost/lexical_cast.hpp>
Botan::secure_vector<uint8_t> PasswordManager::KeyStrengthener::derive(const std::string &passphrase)
{
Botan::secure_vector<uint8_t> master_key(m_keySize);
m_hasher->derive_key(master_key.data(), master_key.size(), passphrase.c_str(), passphrase.length(), m_salt.data(), m_salt.size());
return master_key;
}
void PasswordManager::KeyStrengthener::saveParams(std::shared_ptr<Botan::Sqlite3_Database> db, const std::string &table_name)
{
auto sc = dynamic_cast<Botan::Scrypt*>(m_hasher.get());
size_t i1 = sc->N();
size_t i2 = sc->r();
size_t i3 = sc->p();
// SAVE parameters in database
auto stmt = db->new_statement("INSERT INTO " + table_name + "(id, algo, i1, i2, i3, ks, salt) VALUES(?1, ?2, ?3, ?4, ?5)");
stmt->bind(1, 1);
stmt->bind(2, "Scrypt");
stmt->bind(3, i1);
stmt->bind(4, i2);
stmt->bind(5, i3);
stmt->bind(6, m_keySize);
stmt->bind(7, Botan::base64_encode(m_salt));
stmt->spin();
}
// -------------------------
void PasswordManager::openDatabase(std::shared_ptr<Botan::Sqlite3_Database> db, std::string passphrase)
{
// std::string psk_db_file_name;
// auto db = std::make_shared<Botan::Sqlite3_Database>(psk_db_file_name);
KeyStrengthener ks;
// if (database exists)
if (isPskStoreInitialized(db)) {
ks = getKeyStrengthener(db);
}
else {
initializeNewPskStore(db);
ks = createKeyStrengthener();
ks.saveParams(db, m_secretAlgoTableName);
}
Botan::secure_vector<uint8_t> master_key = ks.derive(passphrase);
m_pskDatabase = std::make_unique<Botan::Encrypted_PSK_Database_SQL>(master_key, db, m_passwordTableName);
}
void PasswordManager::closeDatabase()
{
m_pskDatabase.reset();
}
void PasswordManager::set(const std::string &id, const std::string &passwd)
{
if (m_pskDatabase) {
}
else {
throw PasswordManagerLockedException();
}
}
std::string PasswordManager::get(const std::string &id, const std::string &passwd)
{
if (m_pskDatabase) {
}
else {
throw PasswordManagerLockedException();
}
}
void PasswordManager::remove(const std::string &id)
{
if (m_pskDatabase) {
}
else {
throw PasswordManagerLockedException();
}
}
void PasswordManager::initializeNewPskStore(std::shared_ptr<Botan::Sqlite3_Database> db)
{
// Create tables
// - psk_masterkey_algo
// - psk_passwd
std::string create_statement =
"CREATE TABLE IF NOT EXISTS " + m_secretAlgoTableName + "( \n"
" id INTEGER PRIMARY KEY \n"
" algo TEXT \n"
" i1 INTEGER \n"
" i2 INTEGER \n"
" i3 INTEGER \n"
" ks INTEGER \n"
" salt TEXT \n"
");";
db->create_table(create_statement);
}
bool PasswordManager::isPskStoreInitialized(std::shared_ptr<Botan::Sqlite3_Database> db)
{
// Is the table with the secret data present and filled?
auto stmt = db->new_statement("SELECT name FROM sqlite_master WHERE type='table' AND name=?1");
stmt->bind(1, m_secretAlgoTableName);
bool ok = stmt->step();
if (ok) {
auto stmt = db->new_statement("SELECT algo FROM " + m_secretAlgoTableName + " WHERE id=1");
return stmt->step();
}
return false;
}
PasswordManager::KeyStrengthener PasswordManager::getKeyStrengthener(std::shared_ptr<Botan::Sqlite3_Database> db)
{
auto stmt = db->new_statement("SELECT algo, i1, i2, i3, ks, salt FROM " + m_secretAlgoTableName + " WHERE id=1");
if (stmt->step()) {
std::string algo = stmt->get_str(0);
size_t i1 = boost::lexical_cast<size_t>(stmt->get_str(1));
size_t i2 = boost::lexical_cast<size_t>(stmt->get_str(2));
size_t i3 = boost::lexical_cast<size_t>(stmt->get_str(3));
size_t ks = boost::lexical_cast<size_t>(stmt->get_str(4));
auto pwh_fam = Botan::PasswordHashFamily::create(algo);
return KeyStrengthener(
pwh_fam->from_params(i1, i2, i3),
Botan::base64_decode(stmt->get_str(5)),
ks
);
}
else {
}
}
PasswordManager::KeyStrengthener PasswordManager::createKeyStrengthener()
{
// std::unique_ptr<Botan::PasswordHash> pwh;
size_t key_size = 64;
Botan::secure_vector<uint8_t> salt(key_size);
Botan::AutoSeeded_RNG rng;
rng.randomize(salt.data(), salt.size());
const std::string algo = "Scrypt";
auto pwh_fam = Botan::PasswordHashFamily::create(algo);
return KeyStrengthener(
pwh_fam->tune(key_size, std::chrono::seconds(2), 130),
salt,
key_size
);
}