Project

General

Profile

Download (5.44 KB) Statistics
| Branch: | Revision:
#include <algorithm>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>

#include <sodium.h>

#include "Catalog.h"

Catalog::Catalog()
: m_loaded(false)
{
if (sodium_init() != 0)
{
throw std::runtime_error("libsodium init error!");
}
}

Catalog::~Catalog()
{
}

int Catalog::load(
char* filePath,
char* passwordBuffer,
uint32_t passwordBufferSize,
float* complete)
{
const uint32_t CHUNK_SIZE{4096};
const uint32_t saltLen{crypto_pwhash_SALTBYTES};
const uint32_t keyLen{crypto_secretstream_xchacha20poly1305_KEYBYTES};
int ret = 0;

// Setup salt and key buffers
uint8_t salt[saltLen]{};
uint8_t key[keyLen]{};
uint8_t inBuffer[CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES]{};
uint8_t outBuffer[CHUNK_SIZE]{};
uint8_t header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]{};
crypto_secretstream_xchacha20poly1305_state state;
std::stringstream fileContents;
std::string decryptedData;
uint32_t decryptedDataSize = 0;

std::string line;
std::string valueKey;
std::string value;
bool firstLine = true;

decryptedData.reserve(8 * CHUNK_SIZE);

// Read in salt value
FILE* ctFile = std::fopen(filePath, "rb");
std::fread(salt, 1, saltLen, ctFile);

// Generate key from password and salt
if (crypto_pwhash(key, sizeof key, passwordBuffer,
std::strlen(passwordBuffer), salt,
crypto_pwhash_OPSLIMIT_INTERACTIVE,
crypto_pwhash_MEMLIMIT_INTERACTIVE,
crypto_pwhash_ALG_ARGON2ID13) != 0)
{
ret = ERR_PWHASH_OUT_OF_MEMORY;
goto end_load;
}

// Explicitly zeroize the password buffer
explicit_bzero(passwordBuffer, passwordBufferSize);

// Read in header and init crypto algorithm state
std::fread(header, 1, sizeof header, ctFile);
if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, key) != 0)
{
ret = ERR_DECRYPT_INCOMPLETE_HEADER;
goto end_load;
}

// Decrypt the CT file chunk by chunk
size_t readlen;
long long unsigned numOutBytes;
int eof;
uint8_t tag;
do
{
readlen = fread(inBuffer, 1, sizeof inBuffer, ctFile);
eof = feof(ctFile);

int rc = crypto_secretstream_xchacha20poly1305_pull(&state, outBuffer,
&numOutBytes,
&tag,inBuffer,
readlen, nullptr,
0);
if (rc != 0)
{
ret = ERR_DECRYPT_CORRUPTED_CHUNK;
goto end_load;
}

if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && ! eof)
{
ret = ERR_DECRYPT_PREMATURE_END;
goto end_load;
}

// Append the decryted buffer to the decrypted data
decryptedData.resize(decryptedDataSize + numOutBytes);
std::memcpy(decryptedData.data() + decryptedDataSize, outBuffer, numOutBytes);
decryptedDataSize += numOutBytes;
}
while (! eof);

// Zero out the crypto buffers that are no longer needed
explicit_bzero(salt, saltLen);
explicit_bzero(key, keyLen);
explicit_bzero(inBuffer, CHUNK_SIZE);
explicit_bzero(outBuffer, CHUNK_SIZE);

// Create a stringstream in order to iterate line by line
fileContents << decryptedData;

// Iterate line by line and parse the simple file format
while (std::getline(fileContents, line))
{
if (line.size() == 0)
{
// Debuggery
// std::cout << "KEY: " << valueKey << std::endl;
// std::cout << "VAL: " << value << "\n" << std::endl;

m_catalog.push_back({valueKey, value});
firstLine = true;
}
else
{
if (firstLine)
{
valueKey.clear();
value.clear();

valueKey.swap(line);
firstLine = false;
}
else
{
value += line + "\n";
}
}
}

// Debuggery
// std::cout << "KEY: " << valueKey << std::endl;
// std::cout << "VAL: " << value << "\n" << std::endl;
m_catalog.push_back({valueKey, value});

sort();

// Now we loaded
m_loaded = true;



// End of the line
end_load:
std::fclose(ctFile);
return ret;
}


void Catalog::setAllVisible()
{
for (auto& item : m_catalog)
{
item.setVisibilty(true);
}
}

void Catalog::filter(const std::string& criteria)
{
// Tokenize the filter criteria
std::vector<std::string_view> tokens;
tokenize(criteria, " ", tokens);

// Iterate over the filter criteria tokens
for (auto& token : tokens)
{
// Attempt to match each catalog item
for (auto& item : m_catalog)
{
if (item.match(token))
{
item.setVisibilty(true);
}
else
{
item.setVisibilty(false);
}
}
}
}

void Catalog::sort()
{
// Sort the catalog (A -> Z) for display purposes
std::sort(
m_catalog.begin(),
m_catalog.end(),
[](auto const& lhs, auto const& rhs)
{
return lhs.getLcKey() < rhs.getLcKey();
});
}
(1-1/9)