#include "KeyStrengthener.h"
#include <botan/base64.h>

KeyStrengthener::KeyStrengthener(std::unique_ptr<Botan::PasswordHash> hasher, Botan::secure_vector<uint8_t> salt, size_t keysize)
	: m_hasher (std::move(hasher))
	, m_salt   (std::move(salt))
	, m_keySize(keysize)
{}

KeyStrengthener::KeyStrengthener(KeyStrengthener &&rhs)
	: m_hasher (std::move(rhs.m_hasher))
	, m_salt   (std::move(rhs.m_salt))
	, m_keySize(rhs.m_keySize)
{}

KeyStrengthener &KeyStrengthener::operator=(KeyStrengthener &&rhs)
{
	if (&rhs != this) {
		m_hasher  = std::move(rhs.m_hasher);
		m_salt    = std::move(rhs.m_salt);
		m_keySize = rhs.m_keySize;
	}
	return *this;
}

Botan::secure_vector<uint8_t> 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 KeyStrengthener::saveParams(SQLiteConnection &db, const QString &table_name)
{
    size_t i1 = m_hasher->memory_param();
    size_t i2 = m_hasher->iterations();
    size_t i3 = m_hasher->parallelism();

	auto salt_str = QString::fromUtf8(Botan::base64_encode(m_salt).c_str());
	// SAVE parameters in database

    auto stmt = db.Prepare("INSERT OR REPLACE INTO " + table_name + "(id, algo, i1, i2, i3, ks, salt) "
                           + "VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7)");
    stmt.Bind(1, 1);
    stmt.Bind(2, "Scrypt");
    stmt.Bind(3, (int)i1);
    stmt.Bind(4, (int)i2);
    stmt.Bind(5, (int)i3);
    stmt.Bind(6, (int)m_keySize);
    stmt.Bind(7, salt_str);
    stmt.Step();
}
