From 453bb91e24eab1cf037cbb9bb4b3c613fcc34c2e Mon Sep 17 00:00:00 2001 From: Toni Date: Mon, 3 Nov 2025 12:31:15 +0100 Subject: [PATCH] pbkdf --- src/crypto.h | 11 ++++------- src/main.cc | 2 +- src/mainwindow.cc | 24 ++++++++++++++++++++++-- src/vault.cc | 19 +++++++++++-------- src/vault.h | 4 +++- 5 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/crypto.h b/src/crypto.h index 7789677..f788bd2 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -8,12 +8,9 @@ namespace Crypto { -static Botan::AutoSeeded_RNG g_rng; // NOLINT - -const Botan::secure_vector KEY = { - 0xaa, 0x1b, 0x6c, 0xd2, 0x8e, 0x54, 0x9d, 0xdb, 0xe8, 0xd6, 0x9e, - 0xe9, 0xa4, 0x19, 0xa4, 0xc1, 0x2, 0x73, 0x58, 0x82, 0xa3, 0x75, - 0x5f, 0x86, 0xbd, 0x0, 0x92, 0x97, 0x1e, 0xf3, 0x27, 0x5d}; +// TODO: random salt per per-vault +const std::vector SALT = {0xab, 0xfb, 0x45, 0x1, 0x62, 0xcf, 0xd7, 0x46, + 0xdf, 0xaf, 0x4e, 0xa9, 0xf0, 0x4b, 0x9f, 0x38}; inline Botan::secure_vector encrypt_xchacha20_poly1305(const Botan::secure_vector &plaintext, @@ -59,7 +56,7 @@ decrypt_xchacha20_poly1305(const Botan::secure_vector &ciphertext, inline Botan::secure_vector derive_key_argon2id(const std::string &password, const std::vector &salt) { auto pwdhash = Botan::PasswordHashFamily::create_or_throw("Argon2id") - ->from_params(static_cast(1024 * 1024), 6, 4); + ->from_params(static_cast(1024 * 1024), 8, 4); Botan::secure_vector key(32); pwdhash->derive_key(key.data(), key.size(), password.data(), password.size(), diff --git a/src/main.cc b/src/main.cc index 94224dc..6bd0704 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,7 +1,7 @@ #include "mainwindow.h" #include -i32 main(i32 argc, char *argv[]) { +int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow window; diff --git a/src/mainwindow.cc b/src/mainwindow.cc index 755c274..dbb4e57 100644 --- a/src/mainwindow.cc +++ b/src/mainwindow.cc @@ -20,12 +20,21 @@ MainWindow::MainWindow(QWidget *parent) return; } + QString password = QInputDialog::getText( + this, "Choose a password", "Choose a password", QLineEdit::Password); + if (password.length() < 5) { + QMessageBox::critical(this, "Error", + "Password must be at least 5 characters long."); + return; + } + std::ofstream create(path.toStdString(), std::ios::binary); create.write("DULL", 4); create.write(to_char_ptr(&VERSION), sizeof(VERSION)); create.close(); - m_vault = std::make_unique(path.toStdString()); + m_vault = + std::make_unique(path.toStdString(), password.toStdString()); reload_fs_tree(); }); @@ -37,7 +46,18 @@ MainWindow::MainWindow(QWidget *parent) return; } - m_vault = std::make_unique(path.toStdString()); + QString password = QInputDialog::getText( + this, "Unlock the vault", "Enter vault password", QLineEdit::Password); + if (password.length() < 5) { + QMessageBox::critical(this, "Error", + "Password must be at least 5 characters long."); + return; + } + + // TODO: check if password valid + + m_vault = + std::make_unique(path.toStdString(), password.toStdString()); reload_fs_tree(); }); diff --git a/src/vault.cc b/src/vault.cc index 400b9a6..2779c22 100644 --- a/src/vault.cc +++ b/src/vault.cc @@ -4,12 +4,13 @@ #include #include -Vault::Vault(std::string path) : m_path(std::move(path)) { +Vault::Vault(std::string path, const std::string &password) + : m_path(std::move(path)) { m_file.open(m_path, std::ios::in | std::ios::out | std::ios::binary); - ASSERT(m_file.is_open()); - ASSERT(m_file.good()); + m_key = Crypto::derive_key_argon2id(password, Crypto::SALT); + std::array header{}; ASSERT(static_cast(m_file.read(header.data(), header.size()))); ASSERT(std::string_view(header.data(), header.size()) == "DULL"); @@ -56,8 +57,8 @@ std::optional Vault::read_file(const std::string &filename) { break; } - auto plaintext = Crypto::decrypt_xchacha20_poly1305( - ciphertext, Crypto::KEY, header->nonce); + auto plaintext = + Crypto::decrypt_xchacha20_poly1305(ciphertext, m_key, header->nonce); return std::string(to_char_ptr(plaintext.data()), plaintext.size()); } @@ -76,13 +77,15 @@ void Vault::create_file(const std::string &filename, Botan::secure_vector plaintext(content.begin(), content.end()); - auto nonce_sv = Crypto::g_rng.random_vec(24); + Botan::AutoSeeded_RNG rng; + auto nonce_sv = rng.random_vec(24); std::vector nonce(nonce_sv.begin(), nonce_sv.end()); - auto ciphertext = - Crypto::encrypt_xchacha20_poly1305(plaintext, Crypto::KEY, nonce); + auto ciphertext = Crypto::encrypt_xchacha20_poly1305(plaintext, m_key, nonce); u64 ciphertext_size = ciphertext.size(); + // TODO: encrypt filenames as well + ASSERT(m_file.write(to_char_ptr(&filename_size), sizeof(u64))); ASSERT(m_file.write(filename.data(), static_cast(filename_size))); ASSERT(m_file.write(to_char_ptr(nonce.data()), nonce.size())); diff --git a/src/vault.h b/src/vault.h index 79c9cdc..c086359 100644 --- a/src/vault.h +++ b/src/vault.h @@ -1,6 +1,7 @@ #pragma once #include "common.h" +#include #include #include #include @@ -17,7 +18,7 @@ struct FileHeader { class Vault { public: - explicit Vault(std::string path); + explicit Vault(std::string path, const std::string &password); std::vector read_file_headers(); std::optional read_file(const std::string &name); @@ -30,4 +31,5 @@ public: private: std::string m_path; std::fstream m_file; + Botan::secure_vector m_key; };