Project

General

Profile

« Previous | Next » 

Revision f16b75e3

Added by david.sorber over 2 years ago

Significant improvements including reading input from encrypted file.
Also added crypto utility to en/decrypt a file.

View differences:

src/Catalog.cc
#include <algorithm>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <sodium.h>
#include "Catalog.h"
Catalog::Catalog()
: m_loaded(false)
{
// Temporarily fill the catalog with some test data
#if 0
m_catalog.push_back({"Target", "baranovich@gmail.com\nF-B-3-7"});
m_catalog.push_back({"United", "david.sorber@gmail.com\nF-B-3-7"});
m_catalog.push_back({"Pepco", "david.sorber@gmail.com\nNZ-98-O"});
m_catalog.push_back({"Washington Gas", "baranovich@gmail.com\nS-N-718"});
#else
const std::string pwFile("/home/dsorber/Documents/chicken_soup/chicken_soup.txt");
std::ifstream infile(pwFile);
if (! infile)
if (sodium_init() != 0)
{
return;
// TODO: throw exception here
// return 1;
}
}
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;
// Iterate over the PW file and parse it (key is first line of each stanza
// and the value are the remaining lines)
std::string line;
std::string key;
std::string valueKey;
std::string value;
bool firstLine = true;
while (std::getline(infile, line))
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: " << key << std::endl;
// std::cout << "KEY: " << valueKey << std::endl;
// std::cout << "VAL: " << value << "\n" << std::endl;
m_catalog.push_back({key, value});
m_catalog.push_back({valueKey, value});
firstLine = true;
}
else
{
if (firstLine)
{
key.clear();
valueKey.clear();
value.clear();
key.swap(line);
valueKey.swap(line);
firstLine = false;
}
else
......
}
// Debuggery
// std::cout << "KEY: " << key << std::endl;
// std::cout << "KEY: " << valueKey << std::endl;
// std::cout << "VAL: " << value << "\n" << std::endl;
m_catalog.push_back({key, value});
m_catalog.push_back({valueKey, value});
// Close the input file
infile.close();
sort();
// Now we loaded
m_loaded = true;
#endif
// 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();
});
// End of the line
end_load:
std::fclose(ctFile);
return ret;
}
Catalog::~Catalog()
{
}
void Catalog::setAllVisible()
{
......
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();
});
}

Also available in: Unified diff