Revision f16b75e3
Added by david.sorber over 2 years ago
| 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();
|
||
|
});
|
||
|
}
|
||
Significant improvements including reading input from encrypted file.
Also added crypto utility to en/decrypt a file.