Skip to content

Commit

Permalink
fix two crypto related todos
Browse files Browse the repository at this point in the history
  • Loading branch information
tfussell committed Apr 19, 2017
1 parent ff56701 commit 607e069
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 43 deletions.
46 changes: 27 additions & 19 deletions source/detail/crypto/aes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1334,19 +1334,21 @@ namespace detail {

std::vector<std::uint8_t> aes_ecb_encrypt(
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.size() % 16 != 0)
auto len = plaintext.size() - offset;

if (len % 16 != 0)
{
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 len = plaintext.size();
auto pt = plaintext.data();
auto pt = plaintext.data() + offset;
auto ct = ciphertext.data();

while (len)
Expand All @@ -1363,19 +1365,21 @@ std::vector<std::uint8_t> aes_ecb_encrypt(

std::vector<std::uint8_t> aes_ecb_decrypt(
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.size() % 16 != 0)
auto len = ciphertext.size() - offset;

if (len % 16 != 0)
{
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 len = ciphertext.size();
auto ct = ciphertext.data();
auto ct = ciphertext.data() + offset;
auto pt = plaintext.data();

while (len)
Expand All @@ -1393,20 +1397,22 @@ std::vector<std::uint8_t> aes_ecb_decrypt(
std::vector<std::uint8_t> aes_cbc_encrypt(
const std::vector<std::uint8_t> &plaintext,
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.size() % 16 != 0)
auto len = plaintext.size() - offset;

if (len % 16 != 0)
{
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 len = plaintext.size();
auto ct = ciphertext.data();
auto pt = plaintext.data();
auto pt = plaintext.data() + offset;
auto iv_vec = original_iv;
auto iv = iv_vec.data();

Expand Down Expand Up @@ -1435,21 +1441,23 @@ std::vector<std::uint8_t> aes_cbc_encrypt(
std::vector<std::uint8_t> aes_cbc_decrypt(
const std::vector<std::uint8_t> &ciphertext,
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 {};

auto len = ciphertext.size() - offset;

if (ciphertext.size() % 16 != 0)
{
throw std::runtime_error("");
}

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 len = ciphertext.size();
auto ct = ciphertext.data();
auto ct = ciphertext.data() + offset;
auto pt = plaintext.data();
auto iv_vec = original_iv;
auto iv = iv_vec.data();
Expand Down
12 changes: 8 additions & 4 deletions source/detail/crypto/aes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,25 @@ namespace detail {

std::vector<std::uint8_t> aes_ecb_encrypt(
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(
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(
const std::vector<std::uint8_t> &input,
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(
const std::vector<std::uint8_t> &input,
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 xlnt
33 changes: 13 additions & 20 deletions source/detail/crypto/xlsx_crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,15 @@ std::vector<std::uint8_t> decrypt_xlsx_standard(
offset += verifier_size;

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),
encryption_info.begin() + static_cast<std::ptrdiff_t>(offset + verifier_hash_size));
offset += verifier_hash_size;
encryption_info.begin() + static_cast<std::ptrdiff_t>(offset + encrypted_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

Expand Down Expand Up @@ -301,32 +307,19 @@ std::vector<std::uint8_t> decrypt_xlsx_standard(

auto calculated_verifier_hash = hash(info.hash,
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(
encrypted_verifier_hash, key);
decrypted_verifier_hash.resize(verifier_hash_size);

if (calculated_verifier_hash != decrypted_verifier_hash)
{
throw xlnt::exception("bad password");
}

std::size_t ignore = 0;
auto decrypted_size = static_cast<std::size_t>(
read_int<std::uint64_t>(ignore, encrypted_package));

// 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);
offset = 0;
auto decrypted_size = read_int<std::uint64_t>(offset, encrypted_package);
auto decrypted = aes_ecb_decrypt(encrypted_package, key, offset);
decrypted.resize(static_cast<std::size_t>(decrypted_size));

return decrypted;
}
Expand Down

0 comments on commit 607e069

Please sign in to comment.