separate nonce for filenames
This commit is contained in:
@@ -5,7 +5,8 @@ Desktop app for securely storing sensitive files
|
|||||||
## Features
|
## Features
|
||||||
* **Pretty usable UI**
|
* **Pretty usable UI**
|
||||||
* **Overkill encryption:** XChaCha20-Poly1305 + Argon2id(m=1GB,t=6,p=4) key derivation
|
* **Overkill encryption:** XChaCha20-Poly1305 + Argon2id(m=1GB,t=6,p=4) key derivation
|
||||||
* **Cross-platform-ish:** Tested on Linux and Windows
|
* **Cross-platform-ish:** Builds on Linux, Windows and macOS
|
||||||
|
* **Drag and Drop support**
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
|
|||||||
@@ -107,8 +107,6 @@ void MainWindow::reload_fs_tree() {
|
|||||||
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_size));
|
||||||
item->setText(2, QString::number(header.global_offset));
|
|
||||||
item->setText(3, QString::fromStdString(Botan::hex_encode(header.nonce)));
|
|
||||||
}
|
}
|
||||||
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);
|
||||||
|
|||||||
@@ -33,16 +33,6 @@
|
|||||||
<string>Size</string>
|
<string>Size</string>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Offset</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Nonce</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@@ -93,11 +83,6 @@
|
|||||||
<string>Add</string>
|
<string>Add</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionCreateFile">
|
|
||||||
<property name="text">
|
|
||||||
<string>Create</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|||||||
32
src/vault.cc
32
src/vault.cc
@@ -62,8 +62,8 @@ std::optional<std::string> Vault::read_file(const std::string &filename) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto plaintext =
|
auto plaintext = Crypto::decrypt_xchacha20_poly1305(
|
||||||
Crypto::decrypt_xchacha20_poly1305(ciphertext, m_key, header->nonce);
|
ciphertext, m_key, header->content_nonce);
|
||||||
return std::string(to_char_ptr(plaintext.data()), plaintext.size());
|
return std::string(to_char_ptr(plaintext.data()), plaintext.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,23 +79,28 @@ 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 nonce_sv = rng.random_vec(24);
|
auto name_nonce_sv = rng.random_vec(24);
|
||||||
std::vector<u8> nonce(nonce_sv.begin(), nonce_sv.end());
|
std::vector<u8> name_nonce(name_nonce_sv.begin(), name_nonce_sv.end());
|
||||||
|
|
||||||
|
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 =
|
||||||
Crypto::encrypt_xchacha20_poly1305(filename_sv, m_key, nonce);
|
Crypto::encrypt_xchacha20_poly1305(filename_sv, m_key, name_nonce);
|
||||||
u64 filename_ciphertext_size = filename_ciphertext.size();
|
u64 filename_ciphertext_size = filename_ciphertext.size();
|
||||||
|
|
||||||
Botan::secure_vector<u8> content_sv(content.begin(), content.end());
|
Botan::secure_vector<u8> content_sv(content.begin(), content.end());
|
||||||
auto ciphertext =
|
auto ciphertext =
|
||||||
Crypto::encrypt_xchacha20_poly1305(content_sv, m_key, nonce);
|
Crypto::encrypt_xchacha20_poly1305(content_sv, m_key, content_nonce);
|
||||||
u64 ciphertext_size = ciphertext.size();
|
u64 ciphertext_size = ciphertext.size();
|
||||||
|
|
||||||
ASSERT(m_file.write(to_char_ptr(nonce.data()), nonce.size()));
|
ASSERT(m_file.write(to_char_ptr(name_nonce.data()), name_nonce.size()));
|
||||||
ASSERT(m_file.write(to_char_ptr(&filename_ciphertext_size), sizeof(u64)));
|
ASSERT(m_file.write(to_char_ptr(&filename_ciphertext_size), sizeof(u64)));
|
||||||
ASSERT(m_file.write(to_char_ptr(filename_ciphertext.data()),
|
ASSERT(m_file.write(to_char_ptr(filename_ciphertext.data()),
|
||||||
static_cast<i64>(filename_ciphertext_size)));
|
static_cast<i64>(filename_ciphertext_size)));
|
||||||
|
ASSERT(m_file.write(to_char_ptr(content_nonce.data()), content_nonce.size()));
|
||||||
ASSERT(m_file.write(to_char_ptr(&ciphertext_size), sizeof(u64)));
|
ASSERT(m_file.write(to_char_ptr(&ciphertext_size), sizeof(u64)));
|
||||||
ASSERT(m_file.write(to_char_ptr(ciphertext.data()),
|
ASSERT(m_file.write(to_char_ptr(ciphertext.data()),
|
||||||
static_cast<i64>(ciphertext_size)));
|
static_cast<i64>(ciphertext_size)));
|
||||||
@@ -160,10 +165,10 @@ 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{};
|
||||||
header.global_offset = m_file.tellg();
|
|
||||||
|
|
||||||
header.nonce.resize(24);
|
std::vector<u8> name_nonce;
|
||||||
if (!m_file.read(to_char_ptr(header.nonce.data()), 24)) {
|
name_nonce.resize(24);
|
||||||
|
if (!m_file.read(to_char_ptr(name_nonce.data()), 24)) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,9 +186,14 @@ std::optional<FileHeader> Vault::read_file_header() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto name =
|
auto name =
|
||||||
Crypto::decrypt_xchacha20_poly1305(name_ciphertext, m_key, header.nonce);
|
Crypto::decrypt_xchacha20_poly1305(name_ciphertext, m_key, 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)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_file.read(to_char_ptr(&header.content_size), sizeof(u64))) {
|
if (!m_file.read(to_char_ptr(&header.content_size), sizeof(u64))) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ struct FileHeader {
|
|||||||
std::string name;
|
std::string name;
|
||||||
u64 name_ciphertext_size;
|
u64 name_ciphertext_size;
|
||||||
u64 content_size;
|
u64 content_size;
|
||||||
std::vector<u8> nonce;
|
std::vector<u8> content_nonce;
|
||||||
u64 global_offset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Vault {
|
class Vault {
|
||||||
|
|||||||
Reference in New Issue
Block a user