mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
pare down ltc
This commit is contained in:
parent
0d65569857
commit
077e181617
|
@ -36,26 +36,16 @@
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
enum class cipher_algorithm
|
|
||||||
{
|
|
||||||
aes,
|
aes,
|
||||||
rc2,
|
rc2,
|
||||||
rc4,
|
rc4,
|
||||||
|
@ -63,25 +53,23 @@ struct XLNT_API crypto_helper
|
||||||
desx,
|
desx,
|
||||||
triple_des,
|
triple_des,
|
||||||
triple_des_112
|
triple_des_112
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class cipher_chaining
|
enum class cipher_chaining
|
||||||
{
|
{
|
||||||
ecb, // electronic code book
|
ecb, // electronic code book
|
||||||
cbc, // cipher block chaining
|
cbc // cipher block chaining
|
||||||
cfb // cipher feedback chaining
|
};
|
||||||
};
|
|
||||||
|
|
||||||
enum class cipher_direction
|
enum class cipher_direction
|
||||||
{
|
{
|
||||||
encryption,
|
encryption,
|
||||||
decryption
|
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;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user