pbkdf
This commit is contained in:
11
src/crypto.h
11
src/crypto.h
@@ -8,12 +8,9 @@
|
|||||||
|
|
||||||
namespace Crypto {
|
namespace Crypto {
|
||||||
|
|
||||||
static Botan::AutoSeeded_RNG g_rng; // NOLINT
|
// TODO: random salt per per-vault
|
||||||
|
const std::vector<u8> SALT = {0xab, 0xfb, 0x45, 0x1, 0x62, 0xcf, 0xd7, 0x46,
|
||||||
const Botan::secure_vector<u8> KEY = {
|
0xdf, 0xaf, 0x4e, 0xa9, 0xf0, 0x4b, 0x9f, 0x38};
|
||||||
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};
|
|
||||||
|
|
||||||
inline Botan::secure_vector<u8>
|
inline Botan::secure_vector<u8>
|
||||||
encrypt_xchacha20_poly1305(const Botan::secure_vector<u8> &plaintext,
|
encrypt_xchacha20_poly1305(const Botan::secure_vector<u8> &plaintext,
|
||||||
@@ -59,7 +56,7 @@ decrypt_xchacha20_poly1305(const Botan::secure_vector<u8> &ciphertext,
|
|||||||
inline Botan::secure_vector<u8>
|
inline Botan::secure_vector<u8>
|
||||||
derive_key_argon2id(const std::string &password, const std::vector<u8> &salt) {
|
derive_key_argon2id(const std::string &password, const std::vector<u8> &salt) {
|
||||||
auto pwdhash = Botan::PasswordHashFamily::create_or_throw("Argon2id")
|
auto pwdhash = Botan::PasswordHashFamily::create_or_throw("Argon2id")
|
||||||
->from_params(static_cast<u64>(1024 * 1024), 6, 4);
|
->from_params(static_cast<u64>(1024 * 1024), 8, 4);
|
||||||
|
|
||||||
Botan::secure_vector<u8> key(32);
|
Botan::secure_vector<u8> key(32);
|
||||||
pwdhash->derive_key(key.data(), key.size(), password.data(), password.size(),
|
pwdhash->derive_key(key.data(), key.size(), password.data(), password.size(),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
i32 main(i32 argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
MainWindow window;
|
MainWindow window;
|
||||||
|
|||||||
@@ -20,12 +20,21 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
return;
|
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);
|
std::ofstream create(path.toStdString(), std::ios::binary);
|
||||||
create.write("DULL", 4);
|
create.write("DULL", 4);
|
||||||
create.write(to_char_ptr(&VERSION), sizeof(VERSION));
|
create.write(to_char_ptr(&VERSION), sizeof(VERSION));
|
||||||
create.close();
|
create.close();
|
||||||
|
|
||||||
m_vault = std::make_unique<Vault>(path.toStdString());
|
m_vault =
|
||||||
|
std::make_unique<Vault>(path.toStdString(), password.toStdString());
|
||||||
reload_fs_tree();
|
reload_fs_tree();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -37,7 +46,18 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vault = std::make_unique<Vault>(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<Vault>(path.toStdString(), password.toStdString());
|
||||||
reload_fs_tree();
|
reload_fs_tree();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
19
src/vault.cc
19
src/vault.cc
@@ -4,12 +4,13 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
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);
|
m_file.open(m_path, std::ios::in | std::ios::out | std::ios::binary);
|
||||||
ASSERT(m_file.is_open());
|
|
||||||
|
|
||||||
ASSERT(m_file.good());
|
ASSERT(m_file.good());
|
||||||
|
|
||||||
|
m_key = Crypto::derive_key_argon2id(password, Crypto::SALT);
|
||||||
|
|
||||||
std::array<char, 4> header{};
|
std::array<char, 4> header{};
|
||||||
ASSERT(static_cast<bool>(m_file.read(header.data(), header.size())));
|
ASSERT(static_cast<bool>(m_file.read(header.data(), header.size())));
|
||||||
ASSERT(std::string_view(header.data(), header.size()) == "DULL");
|
ASSERT(std::string_view(header.data(), header.size()) == "DULL");
|
||||||
@@ -56,8 +57,8 @@ std::optional<std::string> Vault::read_file(const std::string &filename) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto plaintext = Crypto::decrypt_xchacha20_poly1305(
|
auto plaintext =
|
||||||
ciphertext, Crypto::KEY, header->nonce);
|
Crypto::decrypt_xchacha20_poly1305(ciphertext, m_key, header->nonce);
|
||||||
return std::string(to_char_ptr(plaintext.data()), plaintext.size());
|
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<u8> plaintext(content.begin(), content.end());
|
Botan::secure_vector<u8> 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<u8> nonce(nonce_sv.begin(), nonce_sv.end());
|
std::vector<u8> nonce(nonce_sv.begin(), nonce_sv.end());
|
||||||
|
|
||||||
auto ciphertext =
|
auto ciphertext = Crypto::encrypt_xchacha20_poly1305(plaintext, m_key, nonce);
|
||||||
Crypto::encrypt_xchacha20_poly1305(plaintext, Crypto::KEY, nonce);
|
|
||||||
u64 ciphertext_size = ciphertext.size();
|
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(to_char_ptr(&filename_size), sizeof(u64)));
|
||||||
ASSERT(m_file.write(filename.data(), static_cast<i64>(filename_size)));
|
ASSERT(m_file.write(filename.data(), static_cast<i64>(filename_size)));
|
||||||
ASSERT(m_file.write(to_char_ptr(nonce.data()), nonce.size()));
|
ASSERT(m_file.write(to_char_ptr(nonce.data()), nonce.size()));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include <botan/secmem.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -17,7 +18,7 @@ struct FileHeader {
|
|||||||
|
|
||||||
class Vault {
|
class Vault {
|
||||||
public:
|
public:
|
||||||
explicit Vault(std::string path);
|
explicit Vault(std::string path, const std::string &password);
|
||||||
|
|
||||||
std::vector<FileHeader> read_file_headers();
|
std::vector<FileHeader> read_file_headers();
|
||||||
std::optional<std::string> read_file(const std::string &name);
|
std::optional<std::string> read_file(const std::string &name);
|
||||||
@@ -30,4 +31,5 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
std::fstream m_file;
|
std::fstream m_file;
|
||||||
|
Botan::secure_vector<u8> m_key;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user