std::array for nonces
This commit is contained in:
@@ -3,14 +3,13 @@
|
|||||||
#include <botan/aead.h>
|
#include <botan/aead.h>
|
||||||
#include <botan/hex.h>
|
#include <botan/hex.h>
|
||||||
#include <botan/pwdhash.h>
|
#include <botan/pwdhash.h>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Crypto {
|
namespace Crypto {
|
||||||
|
|
||||||
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,
|
||||||
const Botan::secure_vector<u8> &key,
|
const Botan::secure_vector<u8> &key,
|
||||||
const std::vector<u8> &nonce) {
|
const std::array<u8, 24> &nonce) {
|
||||||
ASSERT(key.size() == 32);
|
ASSERT(key.size() == 32);
|
||||||
ASSERT(nonce.size() == 24);
|
ASSERT(nonce.size() == 24);
|
||||||
|
|
||||||
@@ -31,7 +30,7 @@ encrypt_xchacha20_poly1305(const Botan::secure_vector<u8> &plaintext,
|
|||||||
inline Botan::secure_vector<u8>
|
inline Botan::secure_vector<u8>
|
||||||
decrypt_xchacha20_poly1305(const Botan::secure_vector<u8> &ciphertext,
|
decrypt_xchacha20_poly1305(const Botan::secure_vector<u8> &ciphertext,
|
||||||
const Botan::secure_vector<u8> &key,
|
const Botan::secure_vector<u8> &key,
|
||||||
const std::vector<u8> &nonce) {
|
const std::array<u8, 24> &nonce) {
|
||||||
ASSERT(ciphertext.size() >= 16);
|
ASSERT(ciphertext.size() >= 16);
|
||||||
ASSERT(key.size() == 32);
|
ASSERT(key.size() == 32);
|
||||||
ASSERT(nonce.size() == 24);
|
ASSERT(nonce.size() == 24);
|
||||||
@@ -49,7 +48,8 @@ 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::array<u8, 16> &salt) {
|
||||||
// thousands of years to crack a random 8 char password on a 100 GPUs
|
// thousands of years to crack a random 8 char password on a 100 GPUs
|
||||||
auto pwdhash = Botan::PasswordHashFamily::create_or_throw("Argon2id")
|
auto pwdhash = Botan::PasswordHashFamily::create_or_throw("Argon2id")
|
||||||
->from_params(static_cast<u64>(1024 * 1024), 8, 4);
|
->from_params(static_cast<u64>(1024 * 1024), 8, 4);
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ void MainWindow::reload_fs_tree() {
|
|||||||
for (const auto &header : headers) {
|
for (const auto &header : headers) {
|
||||||
auto *item = new QTreeWidgetItem(ui->fsTreeWidget);
|
auto *item = new QTreeWidgetItem(ui->fsTreeWidget);
|
||||||
item->setText(0, QString::fromStdString(header.name));
|
item->setText(0, QString::fromStdString(header.name));
|
||||||
item->setText(1, QString::number(header.content_size));
|
item->setText(1, QString::number(header.content_ciphertext_size));
|
||||||
}
|
}
|
||||||
for (int i = 0; i < ui->fsTreeWidget->columnCount(); ++i) {
|
for (int i = 0; i < ui->fsTreeWidget->columnCount(); ++i) {
|
||||||
ui->fsTreeWidget->resizeColumnToContents(i);
|
ui->fsTreeWidget->resizeColumnToContents(i);
|
||||||
|
|||||||
42
src/vault.cc
42
src/vault.cc
@@ -18,8 +18,7 @@ Vault::Vault(std::string path, const std::string &password)
|
|||||||
ASSERT(m_file.read(to_char_ptr(&version), sizeof(version)));
|
ASSERT(m_file.read(to_char_ptr(&version), sizeof(version)));
|
||||||
ASSERT(version == VERSION);
|
ASSERT(version == VERSION);
|
||||||
|
|
||||||
std::vector<u8> salt{};
|
std::array<u8, 16> salt{};
|
||||||
salt.resize(16);
|
|
||||||
ASSERT(m_file.read(to_char_ptr(salt.data()), 16));
|
ASSERT(m_file.read(to_char_ptr(salt.data()), 16));
|
||||||
|
|
||||||
m_key = Crypto::derive_key_argon2id(password, salt);
|
m_key = Crypto::derive_key_argon2id(password, salt);
|
||||||
@@ -35,7 +34,8 @@ std::vector<FileHeader> Vault::read_file_headers() {
|
|||||||
auto header = read_file_header();
|
auto header = read_file_header();
|
||||||
if (header) {
|
if (header) {
|
||||||
headers.push_back(header.value());
|
headers.push_back(header.value());
|
||||||
m_file.seekg(static_cast<i64>(header->content_size), std::ios::cur);
|
m_file.seekg(static_cast<i64>(header->content_ciphertext_size),
|
||||||
|
std::ios::cur);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -56,9 +56,9 @@ std::optional<std::string> Vault::read_file(const std::string &filename) {
|
|||||||
|
|
||||||
if (header->name == filename) {
|
if (header->name == filename) {
|
||||||
Botan::secure_vector<u8> ciphertext;
|
Botan::secure_vector<u8> ciphertext;
|
||||||
ciphertext.resize(header->content_size);
|
ciphertext.resize(header->content_ciphertext_size);
|
||||||
if (!m_file.read(to_char_ptr(ciphertext.data()),
|
if (!m_file.read(to_char_ptr(ciphertext.data()),
|
||||||
static_cast<i64>(header->content_size))) {
|
static_cast<i64>(header->content_ciphertext_size))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +67,8 @@ std::optional<std::string> Vault::read_file(const std::string &filename) {
|
|||||||
return std::string(to_char_ptr(plaintext.data()), plaintext.size());
|
return std::string(to_char_ptr(plaintext.data()), plaintext.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_file.seekg(static_cast<i64>(header->content_size), std::ios::cur);
|
m_file.seekg(static_cast<i64>(header->content_ciphertext_size),
|
||||||
|
std::ios::cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@@ -79,12 +80,8 @@ void Vault::create_file(const std::string &filename,
|
|||||||
m_file.seekp(0, std::ios::end);
|
m_file.seekp(0, std::ios::end);
|
||||||
|
|
||||||
static Botan::AutoSeeded_RNG rng;
|
static Botan::AutoSeeded_RNG rng;
|
||||||
auto name_nonce_sv = rng.random_vec(24);
|
auto name_nonce = rng.random_array<24>();
|
||||||
std::vector<u8> name_nonce(name_nonce_sv.begin(), name_nonce_sv.end());
|
auto content_nonce = rng.random_array<24>();
|
||||||
|
|
||||||
auto content_nonce_sv = rng.random_vec(24);
|
|
||||||
std::vector<u8> content_nonce(content_nonce_sv.begin(),
|
|
||||||
content_nonce_sv.end());
|
|
||||||
|
|
||||||
Botan::secure_vector<u8> filename_sv(filename.begin(), filename.end());
|
Botan::secure_vector<u8> filename_sv(filename.begin(), filename.end());
|
||||||
auto filename_ciphertext =
|
auto filename_ciphertext =
|
||||||
@@ -124,13 +121,15 @@ void Vault::delete_file(const std::string &filename) {
|
|||||||
|
|
||||||
if (header->name == filename) {
|
if (header->name == filename) {
|
||||||
entry_start = current_pos;
|
entry_start = current_pos;
|
||||||
entry_total_size = 24 + sizeof(u64) + header->name_ciphertext_size +
|
entry_total_size = 24 + sizeof(u64) + header->name_ciphertext_size + 24 +
|
||||||
sizeof(u64) + header->content_size;
|
sizeof(u64) + header->content_ciphertext_size;
|
||||||
m_file.seekg(static_cast<i64>(header->content_size), std::ios::cur);
|
m_file.seekg(static_cast<i64>(header->content_ciphertext_size),
|
||||||
|
std::ios::cur);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_file.seekg(static_cast<i64>(header->content_size), std::ios::cur);
|
m_file.seekg(static_cast<i64>(header->content_ciphertext_size),
|
||||||
|
std::ios::cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry_start != -1) {
|
if (entry_start != -1) {
|
||||||
@@ -166,9 +165,7 @@ void Vault::update_file(const std::string &filename,
|
|||||||
std::optional<FileHeader> Vault::read_file_header() {
|
std::optional<FileHeader> Vault::read_file_header() {
|
||||||
FileHeader header{};
|
FileHeader header{};
|
||||||
|
|
||||||
std::vector<u8> name_nonce;
|
if (!m_file.read(to_char_ptr(header.name_nonce.data()), 24)) {
|
||||||
name_nonce.resize(24);
|
|
||||||
if (!m_file.read(to_char_ptr(name_nonce.data()), 24)) {
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,16 +182,15 @@ std::optional<FileHeader> Vault::read_file_header() {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto name =
|
auto name = Crypto::decrypt_xchacha20_poly1305(name_ciphertext, m_key,
|
||||||
Crypto::decrypt_xchacha20_poly1305(name_ciphertext, m_key, name_nonce);
|
header.name_nonce);
|
||||||
header.name = std::string(name.begin(), name.end());
|
header.name = std::string(name.begin(), name.end());
|
||||||
|
|
||||||
header.content_nonce.resize(24);
|
|
||||||
if (!m_file.read(to_char_ptr(header.content_nonce.data()), 24)) {
|
if (!m_file.read(to_char_ptr(header.content_nonce.data()), 24)) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_file.read(to_char_ptr(&header.content_size), sizeof(u64))) {
|
if (!m_file.read(to_char_ptr(&header.content_ciphertext_size), sizeof(u64))) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return header;
|
return header;
|
||||||
|
|||||||
10
src/vault.h
10
src/vault.h
@@ -1,19 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include <array>
|
||||||
#include <botan/secmem.h>
|
#include <botan/secmem.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
constexpr i16 VERSION = 1;
|
constexpr i16 VERSION = 1;
|
||||||
constexpr u64 AFTER_HEADER_OFFSET = 22;
|
constexpr u64 AFTER_HEADER_OFFSET = 22;
|
||||||
|
|
||||||
|
// !!! REMEMBER TO UPDATE entry_total_size IN Vault::delete_file
|
||||||
struct FileHeader {
|
struct FileHeader {
|
||||||
std::string name;
|
std::array<u8, 24> name_nonce;
|
||||||
u64 name_ciphertext_size;
|
u64 name_ciphertext_size;
|
||||||
u64 content_size;
|
std::string name;
|
||||||
std::vector<u8> content_nonce;
|
std::array<u8, 24> content_nonce;
|
||||||
|
u64 content_ciphertext_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Vault {
|
class Vault {
|
||||||
|
|||||||
Reference in New Issue
Block a user