From 0f95cb9aba23b53f3bc26b37de122b2daab2d241 Mon Sep 17 00:00:00 2001 From: Toni Date: Mon, 27 Apr 2026 11:30:30 +0200 Subject: [PATCH] less flushing --- .gitignore | 2 ++ src/crypto.h | 11 ++++++----- src/mainwindow.cc | 8 +++++--- src/vault.cc | 36 +++++++++++++++++++----------------- src/vault.h | 5 ++++- 5 files changed, 36 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 88fb94a..1b05f30 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /build *.py *.dull +/TODO +/.clangd diff --git a/src/crypto.h b/src/crypto.h index b2ef1c0..fee68c1 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -1,11 +1,10 @@ #pragma once #include "common.h" +#include #include #include #include -#include - namespace Crypto { inline Botan::secure_vector encrypt(const Botan::secure_vector &key, @@ -16,15 +15,16 @@ inline Botan::secure_vector encrypt(const Botan::secure_vector &key, // XChaCha20 is selected automatically based on the nonce size // https://github.com/randombit/botan/blob/master/src/lib/stream/chacha/chacha.cpp#L375 - static auto cipher = Botan::AEAD_Mode::create_or_throw( + static thread_local auto cipher = Botan::AEAD_Mode::create_or_throw( "ChaCha20Poly1305", Botan::Cipher_Dir::Encryption); + cipher->clear(); auto nonce = rng.random_array<24>(); cipher->set_key(key); cipher->start(nonce); Botan::secure_vector res; - res.resize(24 + plaintext.size() + 16); + res.resize(24 + plaintext.size()); std::ranges::copy(nonce, res.begin()); std::ranges::copy(plaintext, res.begin() + 24); cipher->finish(res, 24); @@ -40,8 +40,9 @@ decrypt(const Botan::secure_vector &key, std::array nonce{}; std::copy_n(ciphertext_with_nonce.begin(), 24, nonce.begin()); - static auto cipher = Botan::AEAD_Mode::create_or_throw( + static thread_local auto cipher = Botan::AEAD_Mode::create_or_throw( "ChaCha20Poly1305", Botan::Cipher_Dir::Decryption); + cipher->clear(); cipher->set_key(key); cipher->start(nonce); diff --git a/src/mainwindow.cc b/src/mainwindow.cc index 86786a3..c38f8fe 100644 --- a/src/mainwindow.cc +++ b/src/mainwindow.cc @@ -70,10 +70,9 @@ MainWindow::MainWindow(QWidget *parent) ui->statusbar->showMessage("Creating the vault..."); QCoreApplication::processEvents(); - Vault::create(path.toStdString(), password.toStdString()); - m_vault = - std::make_unique(path.toStdString(), password.toStdString()); + Vault::create_and_open(path.toStdString(), password.toStdString()); + ui->statusbar->showMessage("Opened " + path); reload_fs_tree(); @@ -134,6 +133,7 @@ MainWindow::MainWindow(QWidget *parent) file.read(content.data(), size); m_vault->create_file(basename(path.toStdString()), content); } + m_vault->flush(); reload_fs_tree(); ui->statusbar->showMessage("Added " + QString::number(paths.size()) + @@ -304,6 +304,7 @@ void MainWindow::file_context_menu(const QPoint &pos) { style()->standardIcon(QStyle::SP_DialogCancelButton), "Delete"); connect(delete_action, &QAction::triggered, this, [this, item]() { m_vault->delete_file(item->text(0).toStdString()); + m_vault->flush(); reload_fs_tree(); }); @@ -346,6 +347,7 @@ void MainWindow::dropEvent(QDropEvent *event) { file.read(content.data(), size); m_vault->create_file(basename(u.toLocalFile().toStdString()), content); } + m_vault->flush(); ui->statusbar->showMessage( "Added " + QString::number(event->mimeData()->urls().size()) + " files"); reload_fs_tree(); diff --git a/src/vault.cc b/src/vault.cc index 83b11ad..e5cbe6e 100644 --- a/src/vault.cc +++ b/src/vault.cc @@ -49,7 +49,8 @@ Vault::Vault(std::string path, const std::string &password) build_file_map(); } -void Vault::create(const std::string &path, const std::string &password) { +std::unique_ptr Vault::create_and_open(const std::string &path, + const std::string &password) { static Botan::AutoSeeded_RNG rng; auto salt = rng.random_array<16>(); @@ -64,6 +65,8 @@ void Vault::create(const std::string &path, const std::string &password) { WRITE(file, to_char_ptr(salt.data()), 16); WRITE(file, to_char_ptr(check_ciphertext.data()), 46); file.close(); + + return std::make_unique(path, password); } void Vault::build_file_map() { @@ -86,8 +89,8 @@ void Vault::build_file_map() { } } -std::string Vault::read_file(const std::string &filename) { - auto header = m_file_map.at(filename); +std::string Vault::read_file(const std::string &name) { + auto header = m_file_map.at(name); ASSERT(!header.deleted); m_file.clear(); @@ -102,14 +105,15 @@ std::string Vault::read_file(const std::string &filename) { return {to_char_ptr(plaintext.data()), plaintext.size()}; } -void Vault::create_file(const std::string &filename, - const std::string &content) { +void Vault::create_file(const std::string &name, const std::string &content) { + ASSERT(!m_file_map.contains(name)); + m_file.clear(); m_file.seekp(0, std::ios::end); auto offset = m_file.tellp(); - auto name_ciphertext = Crypto::encrypt(m_key, to_span(filename)); + auto name_ciphertext = Crypto::encrypt(m_key, to_span(name)); u64 name_ciphertext_size = name_ciphertext.size(); auto ciphertext = Crypto::encrypt(m_key, to_span(content)); @@ -122,20 +126,19 @@ void Vault::create_file(const std::string &filename, WRITE(m_file, &ciphertext_size, sizeof(u64)); auto content_offset = m_file.tellp(); WRITE(m_file, ciphertext.data(), ciphertext_size); - m_file.flush(); - m_file_map[filename] = FileHeader{ + m_file_map[name] = FileHeader{ .offset = static_cast(offset), .deleted = false, .name_ciphertext_size = name_ciphertext_size, - .name = filename, + .name = name, .content_ciphertext_size = ciphertext_size, .content_offset = static_cast(content_offset), }; } -void Vault::delete_file(const std::string &filename) { - auto header = m_file_map.at(filename); +void Vault::delete_file(const std::string &name) { + auto header = m_file_map.at(name); // zero the ciphertext and mark as deleted m_file.clear(); @@ -152,15 +155,14 @@ void Vault::delete_file(const std::string &filename) { m_file.seekp(static_cast(header.offset), std::ios::beg); bool deleted = true; WRITE(m_file, &deleted, sizeof(bool)); - m_file.flush(); - m_file_map.erase(filename); + m_file_map.erase(name); } -void Vault::update_file(const std::string &filename, - const std::string &content) { - delete_file(filename); - create_file(filename, content); +void Vault::update_file(const std::string &name, const std::string &content) { + delete_file(name); + create_file(name, content); + flush(); } std::optional Vault::read_file_header() { diff --git a/src/vault.h b/src/vault.h index 53980aa..49d56d8 100644 --- a/src/vault.h +++ b/src/vault.h @@ -3,6 +3,7 @@ #include "common.h" #include #include +#include #include #include @@ -22,12 +23,14 @@ class Vault { public: explicit Vault(std::string path, const std::string &password); - static void create(const std::string &path, const std::string &password); + static std::unique_ptr create_and_open(const std::string &path, + const std::string &password); std::string read_file(const std::string &name); void create_file(const std::string &name, const std::string &content); void delete_file(const std::string &name); void update_file(const std::string &name, const std::string &content); + void flush() { m_file.flush(); } const std::string &path() const { return m_path; } const std::unordered_map &file_map() const {