pare down ltc

This commit is contained in:
Thomas Fussell 2017-04-11 14:23:54 -04:00
parent 0d65569857
commit 077e181617

View File

@ -36,52 +36,40 @@
namespace { namespace {
const std::size_t ole_segment_length = 4096;
enum class hash_algorithm enum class hash_algorithm
{ {
sha1, sha1,
sha256, sha512
sha384,
sha512,
md5,
md4,
md2,
ripemd128,
ripemd160,
whirlpool
}; };
struct XLNT_API crypto_helper enum class cipher_algorithm
{ {
static const std::size_t segment_length; aes,
rc2,
rc4,
des,
desx,
triple_des,
triple_des_112
};
enum class cipher_algorithm enum class cipher_chaining
{ {
aes, ecb, // electronic code book
rc2, cbc // cipher block chaining
rc4, };
des,
desx,
triple_des,
triple_des_112
};
enum class cipher_chaining enum class cipher_direction
{ {
ecb, // electronic code book encryption,
cbc, // cipher block chaining decryption
cfb // cipher feedback chaining };
};
enum class cipher_direction
{
encryption,
decryption
};
static std::vector<std::uint8_t> hash(hash_algorithm algorithm, const std::vector<std::uint8_t> &input);
static std::vector<std::uint8_t> file(POLE::Storage &storage, const std::string &name);
struct encryption_info
{
struct standard_encryption_info struct standard_encryption_info
{ {
const std::size_t spin_count = 50000; const std::size_t spin_count = 50000;
@ -96,10 +84,7 @@ struct XLNT_API crypto_helper
std::vector<std::uint8_t> verifier_hash_input; std::vector<std::uint8_t> verifier_hash_input;
std::vector<std::uint8_t> verifier_hash_value; std::vector<std::uint8_t> verifier_hash_value;
std::vector<std::uint8_t> encrypted_key_value; std::vector<std::uint8_t> encrypted_key_value;
}; } standard;
static std::vector<std::uint8_t> decrypt_xlsx_standard(const std::vector<std::uint8_t> &encryption_info,
const std::string &password, const std::vector<std::uint8_t> &encrypted_package);
struct agile_encryption_info struct agile_encryption_info
{ {
@ -137,18 +122,7 @@ struct XLNT_API crypto_helper
std::vector<std::uint8_t> verifier_hash_value; std::vector<std::uint8_t> verifier_hash_value;
std::vector<std::uint8_t> encrypted_key_value; std::vector<std::uint8_t> encrypted_key_value;
} key_encryptor; } key_encryptor;
}; } agile;
static agile_encryption_info generate_agile_encryption_info(const std::string &password);
//static std::vector<std::uint8_t> write_agile_encryption_info(const std::string &password);
static std::vector<std::uint8_t> decrypt_xlsx_agile(const std::vector<std::uint8_t> &encryption_info,
const std::string &password, const std::vector<std::uint8_t> &encrypted_package);
static std::vector<std::uint8_t> decrypt_xlsx(const std::vector<std::uint8_t> &bytes, const std::string &password);
static std::vector<std::uint8_t> encrypt_xlsx(const std::vector<std::uint8_t> &bytes, const std::string &password);
}; };
template <typename T> template <typename T>
@ -302,7 +276,7 @@ static std::vector<std::uint8_t> decode_base64(const std::string &input)
return output; return output;
} }
std::vector<std::uint8_t> crypto_helper::hash(hash_algorithm algorithm, const std::vector<std::uint8_t> &input) std::vector<std::uint8_t> hash(hash_algorithm algorithm, const std::vector<std::uint8_t> &input)
{ {
if (algorithm == hash_algorithm::sha512) if (algorithm == hash_algorithm::sha512)
{ {
@ -316,7 +290,7 @@ std::vector<std::uint8_t> crypto_helper::hash(hash_algorithm algorithm, const st
throw xlnt::exception("unsupported hash algorithm"); throw xlnt::exception("unsupported hash algorithm");
} }
std::vector<std::uint8_t> crypto_helper::file(POLE::Storage &storage, const std::string &name) std::vector<std::uint8_t> file(POLE::Storage &storage, const std::string &name)
{ {
POLE::Stream stream(&storage, name.c_str()); POLE::Stream stream(&storage, name.c_str());
if (stream.fail()) return {}; if (stream.fail()) return {};
@ -325,14 +299,14 @@ std::vector<std::uint8_t> crypto_helper::file(POLE::Storage &storage, const std:
return bytes; return bytes;
} }
std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_standard( std::vector<std::uint8_t> decrypt_xlsx_standard(
const std::vector<std::uint8_t> &encryption_info, const std::vector<std::uint8_t> &encryption_info,
const std::string &password, const std::string &password,
const std::vector<std::uint8_t> &encrypted_package) const std::vector<std::uint8_t> &encrypted_package)
{ {
std::size_t offset = 0; std::size_t offset = 0;
standard_encryption_info info; encryption_info::standard_encryption_info info;
auto header_length = read_int<std::uint32_t>(offset, encryption_info); auto header_length = read_int<std::uint32_t>(offset, encryption_info);
auto index_at_start = offset; auto index_at_start = offset;
@ -463,15 +437,16 @@ std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_standard(
return decrypted; return decrypted;
} }
crypto_helper::agile_encryption_info crypto_helper::generate_agile_encryption_info(const std::string &password) encryption_info generate_encryption_info(const std::string &password)
{ {
agile_encryption_info result; encryption_info result;
result.key_data.salt_value.assign(password.begin(), password.end()); result.agile.key_data.salt_value.assign(password.begin(), password.end());
return result; return result;
} }
/* /*
std::vector<std::uint8_t> crypto_helper::write_agile_encryption_info(const std::string &password) std::vector<std::uint8_t> write_agile_encryption_info(const std::string &password)
{ {
static const auto &xmlns = xlnt::constants::ns("encryption"); static const auto &xmlns = xlnt::constants::ns("encryption");
static const auto &xmlns_p = xlnt::constants::ns("encryption-password"); static const auto &xmlns_p = xlnt::constants::ns("encryption-password");
@ -527,7 +502,7 @@ std::vector<std::uint8_t> crypto_helper::write_agile_encryption_info(const std::
} }
*/ */
std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_agile( std::vector<std::uint8_t> decrypt_xlsx_agile(
const std::vector<std::uint8_t> &encryption_info, const std::vector<std::uint8_t> &encryption_info,
const std::string &password, const std::string &password,
const std::vector<std::uint8_t> &encrypted_package) const std::vector<std::uint8_t> &encrypted_package)
@ -536,7 +511,7 @@ std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_agile(
static const auto &xmlns_p = xlnt::constants::ns("encryption-password"); static const auto &xmlns_p = xlnt::constants::ns("encryption-password");
// static const auto &xmlns_c = xlnt::constants::namespace_("encryption-certificate"); // static const auto &xmlns_c = xlnt::constants::namespace_("encryption-certificate");
agile_encryption_info result; encryption_info::agile_encryption_info result;
xml::parser parser(encryption_info.data(), encryption_info.size(), "EncryptionInfo"); xml::parser parser(encryption_info.data(), encryption_info.size(), "EncryptionInfo");
@ -579,6 +554,7 @@ std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_agile(
result.key_encryptor.cipher_chaining = parser.attribute("cipherChaining"); result.key_encryptor.cipher_chaining = parser.attribute("cipherChaining");
auto hash_algorithm_string = parser.attribute("hashAlgorithm"); auto hash_algorithm_string = parser.attribute("hashAlgorithm");
if (hash_algorithm_string == "SHA512") if (hash_algorithm_string == "SHA512")
{ {
result.key_encryptor.hash = hash_algorithm::sha512; result.key_encryptor.hash = hash_algorithm::sha512;
@ -587,13 +563,9 @@ std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_agile(
{ {
result.key_encryptor.hash = hash_algorithm::sha1; result.key_encryptor.hash = hash_algorithm::sha1;
} }
else if (hash_algorithm_string == "SHA256") else
{ {
result.key_encryptor.hash = hash_algorithm::sha256; throw xlnt::unsupported("hash");
}
else if (hash_algorithm_string == "SHA384")
{
result.key_encryptor.hash = hash_algorithm::sha384;
} }
result.key_encryptor.salt_value = decode_base64(parser.attribute("saltValue")); result.key_encryptor.salt_value = decode_base64(parser.attribute("saltValue"));
@ -692,17 +664,17 @@ std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_agile(
auto &segment = *reinterpret_cast<std::uint32_t *>(salt_with_block_key.data() + salt_size); auto &segment = *reinterpret_cast<std::uint32_t *>(salt_with_block_key.data() + salt_size);
auto total_size = static_cast<std::size_t>(*reinterpret_cast<const std::uint64_t *>(encrypted_package.data())); auto total_size = static_cast<std::size_t>(*reinterpret_cast<const std::uint64_t *>(encrypted_package.data()));
std::vector<std::uint8_t> encrypted_segment(segment_length, 0); std::vector<std::uint8_t> encrypted_segment(ole_segment_length, 0);
std::vector<std::uint8_t> decrypted_package; std::vector<std::uint8_t> decrypted_package;
decrypted_package.reserve(encrypted_package.size() - 8); decrypted_package.reserve(encrypted_package.size() - 8);
for (std::size_t i = 8; i < encrypted_package.size(); i += segment_length) for (std::size_t i = 8; i < encrypted_package.size(); i += ole_segment_length)
{ {
auto iv = hash(result.key_encryptor.hash, salt_with_block_key); auto iv = hash(result.key_encryptor.hash, salt_with_block_key);
iv.resize(16); iv.resize(16);
auto segment_begin = encrypted_package.begin() + static_cast<std::ptrdiff_t>(i); auto segment_begin = encrypted_package.begin() + static_cast<std::ptrdiff_t>(i);
auto current_segment_length = std::min(segment_length, encrypted_package.size() - i); auto current_segment_length = std::min(ole_segment_length, encrypted_package.size() - i);
auto segment_end = encrypted_package.begin() + static_cast<std::ptrdiff_t>(i + current_segment_length); auto segment_end = encrypted_package.begin() + static_cast<std::ptrdiff_t>(i + current_segment_length);
encrypted_segment.assign(segment_begin, segment_end); encrypted_segment.assign(segment_begin, segment_end);
auto decrypted_segment = xlnt::detail::aes_cbc_decrypt(encrypted_segment, key, iv); auto decrypted_segment = xlnt::detail::aes_cbc_decrypt(encrypted_segment, key, iv);
@ -718,8 +690,9 @@ std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_agile(
return decrypted_package; return decrypted_package;
} }
std::vector<std::uint8_t> crypto_helper::decrypt_xlsx( std::vector<std::uint8_t> decrypt_xlsx(
const std::vector<std::uint8_t> &bytes, const std::string &password) const std::vector<std::uint8_t> &bytes,
const std::string &password)
{ {
if (bytes.empty()) if (bytes.empty())
{ {
@ -782,21 +755,20 @@ std::vector<std::uint8_t> crypto_helper::decrypt_xlsx(
return decrypt_xlsx_standard(encryption_info, password, encrypted_package); return decrypt_xlsx_standard(encryption_info, password, encrypted_package);
} }
std::vector<std::uint8_t> crypto_helper::encrypt_xlsx( std::vector<std::uint8_t> encrypt_xlsx(
const std::vector<std::uint8_t> &bytes, const std::string &password) const std::vector<std::uint8_t> &bytes,
const std::string &password)
{ {
if (bytes.empty()) if (bytes.empty())
{ {
throw xlnt::exception("empty file"); throw xlnt::exception("empty file");
} }
generate_agile_encryption_info(password); generate_encryption_info(password);
return {}; return {};
} }
const std::size_t crypto_helper::segment_length = 4096;
} // namespace } // namespace
namespace xml { namespace xml {
@ -869,13 +841,13 @@ namespace detail {
std::vector<std::uint8_t> XLNT_API decrypt_xlsx(const std::vector<std::uint8_t> &data, const std::string &password) std::vector<std::uint8_t> XLNT_API decrypt_xlsx(const std::vector<std::uint8_t> &data, const std::string &password)
{ {
return crypto_helper::decrypt_xlsx(data, password); return ::decrypt_xlsx(data, password);
} }
void xlsx_consumer::read(std::istream &source, const std::string &password) void xlsx_consumer::read(std::istream &source, const std::string &password)
{ {
std::vector<std::uint8_t> data((std::istreambuf_iterator<char>(source)), (std::istreambuf_iterator<char>())); std::vector<std::uint8_t> data((std::istreambuf_iterator<char>(source)), (std::istreambuf_iterator<char>()));
const auto decrypted = crypto_helper::decrypt_xlsx(data, password); const auto decrypted = decrypt_xlsx(data, password);
vector_istreambuf decrypted_buffer(decrypted); vector_istreambuf decrypted_buffer(decrypted);
std::istream decrypted_stream(&decrypted_buffer); std::istream decrypted_stream(&decrypted_buffer);
read(decrypted_stream); read(decrypted_stream);
@ -891,7 +863,7 @@ void xlsx_producer::write(std::ostream &destination, const std::string &password
write(decrypted_stream); write(decrypted_stream);
} }
const auto encrypted = crypto_helper::encrypt_xlsx(decrypted, password); const auto encrypted = encrypt_xlsx(decrypted, password);
vector_istreambuf encrypted_buffer(encrypted); vector_istreambuf encrypted_buffer(encrypted);
destination << &encrypted_buffer; destination << &encrypted_buffer;