mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
fix two crypto related todos
This commit is contained in:
parent
ff56701774
commit
607e069b33
|
@ -1334,19 +1334,21 @@ namespace detail {
|
||||||
|
|
||||||
std::vector<std::uint8_t> aes_ecb_encrypt(
|
std::vector<std::uint8_t> aes_ecb_encrypt(
|
||||||
const std::vector<std::uint8_t> &plaintext,
|
const std::vector<std::uint8_t> &plaintext,
|
||||||
const std::vector<std::uint8_t> &key)
|
const std::vector<std::uint8_t> &key,
|
||||||
|
const std::size_t offset)
|
||||||
{
|
{
|
||||||
if (plaintext.empty()) return {};
|
if (plaintext.empty()) return {};
|
||||||
|
|
||||||
if (plaintext.size() % 16 != 0)
|
auto len = plaintext.size() - offset;
|
||||||
|
|
||||||
|
if (len % 16 != 0)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("");
|
throw std::runtime_error("");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ciphertext = std::vector<std::uint8_t>(plaintext.size());
|
auto ciphertext = std::vector<std::uint8_t>(len);
|
||||||
auto expanded_key = rijndael_setup(key);
|
auto expanded_key = rijndael_setup(key);
|
||||||
auto len = plaintext.size();
|
auto pt = plaintext.data() + offset;
|
||||||
auto pt = plaintext.data();
|
|
||||||
auto ct = ciphertext.data();
|
auto ct = ciphertext.data();
|
||||||
|
|
||||||
while (len)
|
while (len)
|
||||||
|
@ -1363,19 +1365,21 @@ std::vector<std::uint8_t> aes_ecb_encrypt(
|
||||||
|
|
||||||
std::vector<std::uint8_t> aes_ecb_decrypt(
|
std::vector<std::uint8_t> aes_ecb_decrypt(
|
||||||
const std::vector<std::uint8_t> &ciphertext,
|
const std::vector<std::uint8_t> &ciphertext,
|
||||||
const std::vector<std::uint8_t> &key)
|
const std::vector<std::uint8_t> &key,
|
||||||
|
const std::size_t offset)
|
||||||
{
|
{
|
||||||
if (ciphertext.empty()) return {};
|
if (ciphertext.empty()) return {};
|
||||||
|
|
||||||
if (ciphertext.size() % 16 != 0)
|
auto len = ciphertext.size() - offset;
|
||||||
|
|
||||||
|
if (len % 16 != 0)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("");
|
throw std::runtime_error("");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto plaintext = std::vector<std::uint8_t>(ciphertext.size());
|
auto plaintext = std::vector<std::uint8_t>(len);
|
||||||
auto expanded_key = rijndael_setup(key);
|
auto expanded_key = rijndael_setup(key);
|
||||||
auto len = ciphertext.size();
|
auto ct = ciphertext.data() + offset;
|
||||||
auto ct = ciphertext.data();
|
|
||||||
auto pt = plaintext.data();
|
auto pt = plaintext.data();
|
||||||
|
|
||||||
while (len)
|
while (len)
|
||||||
|
@ -1393,20 +1397,22 @@ std::vector<std::uint8_t> aes_ecb_decrypt(
|
||||||
std::vector<std::uint8_t> aes_cbc_encrypt(
|
std::vector<std::uint8_t> aes_cbc_encrypt(
|
||||||
const std::vector<std::uint8_t> &plaintext,
|
const std::vector<std::uint8_t> &plaintext,
|
||||||
const std::vector<std::uint8_t> &key,
|
const std::vector<std::uint8_t> &key,
|
||||||
const std::vector<std::uint8_t> &original_iv)
|
const std::vector<std::uint8_t> &original_iv,
|
||||||
|
const std::size_t offset)
|
||||||
{
|
{
|
||||||
if (plaintext.empty()) return {};
|
if (plaintext.empty()) return {};
|
||||||
|
|
||||||
if (plaintext.size() % 16 != 0)
|
auto len = plaintext.size() - offset;
|
||||||
|
|
||||||
|
if (len % 16 != 0)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("");
|
throw std::runtime_error("");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ciphertext = std::vector<std::uint8_t>(plaintext.size());
|
auto ciphertext = std::vector<std::uint8_t>(len);
|
||||||
auto expanded_key = rijndael_setup(key);
|
auto expanded_key = rijndael_setup(key);
|
||||||
auto len = plaintext.size();
|
|
||||||
auto ct = ciphertext.data();
|
auto ct = ciphertext.data();
|
||||||
auto pt = plaintext.data();
|
auto pt = plaintext.data() + offset;
|
||||||
auto iv_vec = original_iv;
|
auto iv_vec = original_iv;
|
||||||
auto iv = iv_vec.data();
|
auto iv = iv_vec.data();
|
||||||
|
|
||||||
|
@ -1435,10 +1441,13 @@ std::vector<std::uint8_t> aes_cbc_encrypt(
|
||||||
std::vector<std::uint8_t> aes_cbc_decrypt(
|
std::vector<std::uint8_t> aes_cbc_decrypt(
|
||||||
const std::vector<std::uint8_t> &ciphertext,
|
const std::vector<std::uint8_t> &ciphertext,
|
||||||
const std::vector<std::uint8_t> &key,
|
const std::vector<std::uint8_t> &key,
|
||||||
const std::vector<std::uint8_t> &original_iv)
|
const std::vector<std::uint8_t> &original_iv,
|
||||||
|
const std::size_t offset)
|
||||||
{
|
{
|
||||||
if (ciphertext.empty()) return {};
|
if (ciphertext.empty()) return {};
|
||||||
|
|
||||||
|
auto len = ciphertext.size() - offset;
|
||||||
|
|
||||||
if (ciphertext.size() % 16 != 0)
|
if (ciphertext.size() % 16 != 0)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("");
|
throw std::runtime_error("");
|
||||||
|
@ -1446,10 +1455,9 @@ std::vector<std::uint8_t> aes_cbc_decrypt(
|
||||||
|
|
||||||
std::array<std::uint8_t, 16> temporary{{0}};
|
std::array<std::uint8_t, 16> temporary{{0}};
|
||||||
|
|
||||||
auto plaintext = std::vector<std::uint8_t>(ciphertext.size());
|
auto plaintext = std::vector<std::uint8_t>(len);
|
||||||
auto expanded_key = rijndael_setup(key);
|
auto expanded_key = rijndael_setup(key);
|
||||||
auto len = ciphertext.size();
|
auto ct = ciphertext.data() + offset;
|
||||||
auto ct = ciphertext.data();
|
|
||||||
auto pt = plaintext.data();
|
auto pt = plaintext.data();
|
||||||
auto iv_vec = original_iv;
|
auto iv_vec = original_iv;
|
||||||
auto iv = iv_vec.data();
|
auto iv = iv_vec.data();
|
||||||
|
|
|
@ -31,21 +31,25 @@ namespace detail {
|
||||||
|
|
||||||
std::vector<std::uint8_t> aes_ecb_encrypt(
|
std::vector<std::uint8_t> aes_ecb_encrypt(
|
||||||
const std::vector<std::uint8_t> &input,
|
const std::vector<std::uint8_t> &input,
|
||||||
const std::vector<std::uint8_t> &key);
|
const std::vector<std::uint8_t> &key,
|
||||||
|
const std::size_t offset = 0);
|
||||||
|
|
||||||
std::vector<std::uint8_t> aes_ecb_decrypt(
|
std::vector<std::uint8_t> aes_ecb_decrypt(
|
||||||
const std::vector<std::uint8_t> &input,
|
const std::vector<std::uint8_t> &input,
|
||||||
const std::vector<std::uint8_t> &key);
|
const std::vector<std::uint8_t> &key,
|
||||||
|
const std::size_t offset = 0);
|
||||||
|
|
||||||
std::vector<std::uint8_t> aes_cbc_encrypt(
|
std::vector<std::uint8_t> aes_cbc_encrypt(
|
||||||
const std::vector<std::uint8_t> &input,
|
const std::vector<std::uint8_t> &input,
|
||||||
const std::vector<std::uint8_t> &key,
|
const std::vector<std::uint8_t> &key,
|
||||||
const std::vector<std::uint8_t> &iv);
|
const std::vector<std::uint8_t> &iv,
|
||||||
|
const std::size_t offset = 0);
|
||||||
|
|
||||||
std::vector<std::uint8_t> aes_cbc_decrypt(
|
std::vector<std::uint8_t> aes_cbc_decrypt(
|
||||||
const std::vector<std::uint8_t> &input,
|
const std::vector<std::uint8_t> &input,
|
||||||
const std::vector<std::uint8_t> &key,
|
const std::vector<std::uint8_t> &key,
|
||||||
const std::vector<std::uint8_t> &iv);
|
const std::vector<std::uint8_t> &iv,
|
||||||
|
const std::size_t offset = 0);
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -240,9 +240,15 @@ std::vector<std::uint8_t> decrypt_xlsx_standard(
|
||||||
offset += verifier_size;
|
offset += verifier_size;
|
||||||
|
|
||||||
const auto verifier_hash_size = read_int<std::uint32_t>(offset, encryption_info);
|
const auto verifier_hash_size = read_int<std::uint32_t>(offset, encryption_info);
|
||||||
|
const auto encrypted_verifier_hash_size = std::size_t(32);
|
||||||
std::vector<std::uint8_t> encrypted_verifier_hash(encryption_info.begin() + static_cast<std::ptrdiff_t>(offset),
|
std::vector<std::uint8_t> encrypted_verifier_hash(encryption_info.begin() + static_cast<std::ptrdiff_t>(offset),
|
||||||
encryption_info.begin() + static_cast<std::ptrdiff_t>(offset + verifier_hash_size));
|
encryption_info.begin() + static_cast<std::ptrdiff_t>(offset + encrypted_verifier_hash_size));
|
||||||
offset += verifier_hash_size;
|
offset += encrypted_verifier_hash_size;
|
||||||
|
|
||||||
|
if (offset != encryption_info.size())
|
||||||
|
{
|
||||||
|
throw xlnt::exception("extra data after encryption info");
|
||||||
|
}
|
||||||
|
|
||||||
// begin key generation algorithm
|
// begin key generation algorithm
|
||||||
|
|
||||||
|
@ -301,32 +307,19 @@ std::vector<std::uint8_t> decrypt_xlsx_standard(
|
||||||
|
|
||||||
auto calculated_verifier_hash = hash(info.hash,
|
auto calculated_verifier_hash = hash(info.hash,
|
||||||
aes_ecb_decrypt(encrypted_verifier, key));
|
aes_ecb_decrypt(encrypted_verifier, key));
|
||||||
|
|
||||||
// TODO: I can't figure out how to pad encrypted_verifier_hash to 32 bytes
|
|
||||||
// so that it matches calculated_verifier_hash after decryption so we'll just
|
|
||||||
// compare the first block (16 bytes) for now.
|
|
||||||
calculated_verifier_hash.resize(16);
|
|
||||||
encrypted_verifier_hash.resize(16);
|
|
||||||
|
|
||||||
auto decrypted_verifier_hash = aes_ecb_decrypt(
|
auto decrypted_verifier_hash = aes_ecb_decrypt(
|
||||||
encrypted_verifier_hash, key);
|
encrypted_verifier_hash, key);
|
||||||
|
decrypted_verifier_hash.resize(verifier_hash_size);
|
||||||
|
|
||||||
if (calculated_verifier_hash != decrypted_verifier_hash)
|
if (calculated_verifier_hash != decrypted_verifier_hash)
|
||||||
{
|
{
|
||||||
throw xlnt::exception("bad password");
|
throw xlnt::exception("bad password");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t ignore = 0;
|
offset = 0;
|
||||||
auto decrypted_size = static_cast<std::size_t>(
|
auto decrypted_size = read_int<std::uint64_t>(offset, encrypted_package);
|
||||||
read_int<std::uint64_t>(ignore, encrypted_package));
|
auto decrypted = aes_ecb_decrypt(encrypted_package, key, offset);
|
||||||
|
decrypted.resize(static_cast<std::size_t>(decrypted_size));
|
||||||
// TODO: don't copy encrypted package just to cut off the first 8 bytes
|
|
||||||
auto encrypted_data = std::vector<std::uint8_t>(
|
|
||||||
encrypted_package.begin() + 8,
|
|
||||||
encrypted_package.end());
|
|
||||||
auto decrypted = aes_ecb_decrypt(encrypted_data, key);
|
|
||||||
|
|
||||||
decrypted.resize(decrypted_size);
|
|
||||||
|
|
||||||
return decrypted;
|
return decrypted;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user