pare down ltc

This commit is contained in:
Thomas Fussell 2017-04-11 12:02:35 -04:00
parent 83cbc3f7eb
commit 3e2a0fc15f
9 changed files with 230 additions and 359 deletions

View File

@ -44,24 +44,6 @@ namespace {
#define LTC_NO_ROLC #define LTC_NO_ROLC
#include "tomcrypt.h" #include "tomcrypt.h"
#if (ARGTYPE == 0)
void crypt_argchk(char *v, char *s, int d)
{
fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n",
v, d, s);
abort();
}
#endif
void zeromem(volatile void *out, size_t outlen)
{
volatile char *mem = (char *)out;
LTC_ARGCHKVD(out != NULL);
while (outlen-- > 0) {
*mem++ = '\0';
}
}
#define SETUP rijndael_setup #define SETUP rijndael_setup
#define ECB_ENC rijndael_ecb_encrypt #define ECB_ENC rijndael_ecb_encrypt
#define ECB_DEC rijndael_ecb_decrypt #define ECB_DEC rijndael_ecb_decrypt
@ -1007,8 +989,6 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
#ifndef ENCRYPT_ONLY #ifndef ENCRYPT_ONLY
ulong32 *rrk; ulong32 *rrk;
#endif #endif
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(skey != NULL);
if (keylen != 16 && keylen != 24 && keylen != 32) { if (keylen != 16 && keylen != 24 && keylen != 32) {
return CRYPT_INVALID_KEYSIZE; return CRYPT_INVALID_KEYSIZE;
@ -1168,10 +1148,6 @@ int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
int Nr, r; int Nr, r;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(skey != NULL);
Nr = skey->rijndael.Nr; Nr = skey->rijndael.Nr;
rk = skey->rijndael.eK; rk = skey->rijndael.eK;
@ -1293,10 +1269,6 @@ int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
int Nr, r; int Nr, r;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(skey != NULL);
Nr = skey->rijndael.Nr; Nr = skey->rijndael.Nr;
rk = skey->rijndael.dK; rk = skey->rijndael.dK;
@ -1423,8 +1395,6 @@ void ECB_DONE(symmetric_key *skey)
*/ */
int ECB_KS(int *keysize) int ECB_KS(int *keysize)
{ {
LTC_ARGCHK(keysize != NULL);
if (*keysize < 16) if (*keysize < 16)
return CRYPT_INVALID_KEYSIZE; return CRYPT_INVALID_KEYSIZE;
if (*keysize < 24) { if (*keysize < 24) {
@ -1449,10 +1419,6 @@ int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s
unsigned char tmpy; unsigned char tmpy;
#endif #endif
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(cbc != NULL);
if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return err; return err;
} }
@ -1506,7 +1472,6 @@ int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s
int cbc_done(symmetric_CBC *cbc) int cbc_done(symmetric_CBC *cbc)
{ {
int err; int err;
LTC_ARGCHK(cbc != NULL);
if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return err; return err;
@ -1519,10 +1484,6 @@ int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s
{ {
int x, err; int x, err;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(cbc != NULL);
if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return err; return err;
} }
@ -1585,10 +1546,6 @@ int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
{ {
int x, err; int x, err;
LTC_ARGCHK(IV != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(cbc != NULL);
/* bad param? */ /* bad param? */
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err; return err;
@ -1612,8 +1569,6 @@ int register_cipher(const struct ltc_cipher_descriptor *cipher)
{ {
int x; int x;
LTC_ARGCHK(cipher != NULL);
/* is it already registered? */ /* is it already registered? */
LTC_MUTEX_LOCK(&ltc_cipher_mutex); LTC_MUTEX_LOCK(&ltc_cipher_mutex);
for (x = 0; x < TAB_SIZE; x++) { for (x = 0; x < TAB_SIZE; x++) {
@ -1657,9 +1612,7 @@ int cipher_is_valid(int idx)
int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb) int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb)
{ {
int err; int err;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err; return err;
} }
@ -1686,7 +1639,6 @@ int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s
int ecb_done(symmetric_ECB *ecb) int ecb_done(symmetric_ECB *ecb)
{ {
int err; int err;
LTC_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err; return err;
@ -1698,9 +1650,7 @@ int ecb_done(symmetric_ECB *ecb)
int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb) int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb)
{ {
int err; int err;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err; return err;
} }
@ -1727,8 +1677,6 @@ int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s
int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb) int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb)
{ {
int err; int err;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err; return err;
@ -1741,8 +1689,9 @@ int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds,
} // namespace } // namespace
namespace xlnt { namespace xlnt {
namespace detail {
std::vector<std::uint8_t> xaes_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)
{ {
@ -1760,7 +1709,7 @@ std::vector<std::uint8_t> xaes_ecb_encrypt(
return output; return output;
} }
std::vector<std::uint8_t> xaes_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)
{ {
@ -1778,7 +1727,7 @@ std::vector<std::uint8_t> xaes_ecb_decrypt(
return output; return output;
} }
std::vector<std::uint8_t> xaes_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)
@ -1797,7 +1746,7 @@ std::vector<std::uint8_t> xaes_cbc_encrypt(
return output; return output;
} }
std::vector<std::uint8_t> xaes_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)
@ -1816,6 +1765,7 @@ std::vector<std::uint8_t> xaes_cbc_decrypt(
return output; return output;
} }
} // namespace detail
} // namespace xlnt } // namespace xlnt
#pragma clang diagnostic pop #pragma clang diagnostic pop

View File

@ -4,23 +4,25 @@
#include <vector> #include <vector>
namespace xlnt { namespace xlnt {
namespace detail {
std::vector<std::uint8_t> xaes_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);
std::vector<std::uint8_t> xaes_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);
std::vector<std::uint8_t> xaes_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);
std::vector<std::uint8_t> xaes_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);
} // namespace detail
} // namespace xlnt } // namespace xlnt

View File

@ -72,14 +72,8 @@ enum {
#include "tomcrypt_cfg.h" #include "tomcrypt_cfg.h"
#include "tomcrypt_macros.h" #include "tomcrypt_macros.h"
#include "tomcrypt_cipher.h" #include "tomcrypt_cipher.h"
#include "tomcrypt_hash.h"
#include "tomcrypt_mac.h"
#include "tomcrypt_prng.h"
#include "tomcrypt_pk.h"
#include "tomcrypt_math.h" #include "tomcrypt_math.h"
#include "tomcrypt_misc.h" #include "tomcrypt_misc.h"
#include "tomcrypt_argchk.h"
#include "tomcrypt_pkcs.h"
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -654,18 +654,6 @@ extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer
#ifdef LTC_RIJNDAEL #ifdef LTC_RIJNDAEL
/* make aes an alias */
#define aes_setup rijndael_setup
#define aes_ecb_encrypt rijndael_ecb_encrypt
#define aes_ecb_decrypt rijndael_ecb_decrypt
#define aes_test rijndael_test
#define aes_done rijndael_done
#define aes_keysize rijndael_keysize
#define aes_enc_setup rijndael_enc_setup
#define aes_enc_ecb_encrypt rijndael_enc_ecb_encrypt
#define aes_enc_keysize rijndael_enc_keysize
int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);

View File

@ -332,87 +332,6 @@ typedef struct {
*/ */
int (*isprime)(void *a, int b, int *c); int (*isprime)(void *a, int b, int *c);
/* ---- (optional) ecc point math ---- */
/** ECC GF(p) point multiplication (from the NIST curves)
@param k The integer to multiply the point by
@param G The point to multiply
@param R The destination for kG
@param modulus The modulus for the field
@param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only)
@return CRYPT_OK on success
*/
int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
/** ECC GF(p) point addition
@param P The first point
@param Q The second point
@param R The destination of P + Q
@param modulus The modulus
@param mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
*/
int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
/** ECC GF(p) point double
@param P The first point
@param R The destination of 2P
@param modulus The modulus
@param mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
*/
int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp);
/** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1)
@param P The point to map
@param modulus The modulus
@param mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
@remark The mapping can be different but keep in mind a ecc_point only has three
integers (x,y,z) so if you use a different mapping you have to make it fit.
*/
int (*ecc_map)(ecc_point *P, void *modulus, void *mp);
/** Computes kA*A + kB*B = C using Shamir's Trick
@param A First point to multiply
@param kA What to multiple A by
@param B Second point to multiply
@param kB What to multiple B by
@param C [out] Destination point (can overlap with A or B
@param modulus Modulus for curve
@return CRYPT_OK on success
*/
int (*ecc_mul2add)(ecc_point *A, void *kA,
ecc_point *B, void *kB,
ecc_point *C,
void *modulus);
/* ---- (optional) rsa optimized math (for internal CRT) ---- */
/** RSA Key Generation
@param prng An active PRNG state
@param wprng The index of the PRNG desired
@param size The size of the modulus (key size) desired (octets)
@param e The "e" value (public key). e==65537 is a good choice
@param key [out] Destination of a newly created private key pair
@return CRYPT_OK if successful, upon error all allocated ram is freed
*/
int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key);
/** RSA exponentiation
@param in The octet array representing the base
@param inlen The length of the input
@param out The destination (to be stored in an octet array format)
@param outlen The length of the output buffer and the resulting size (zero padded to the size of the modulus)
@param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA
@param key The RSA key to use
@return CRYPT_OK on success
*/
int (*rsa_me)(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int which,
rsa_key *key);
/* ---- basic math continued ---- */ /* ---- basic math continued ---- */
/** Modular addition /** Modular addition

View File

@ -21,14 +21,139 @@
// @license: http://www.opensource.org/licenses/mit-license.php // @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file // @author: see AUTHORS file
#include <array>
#include <detail/crypto/aes.hpp> #include <detail/crypto/aes.hpp>
#include <detail/crypto/base64.hpp> #include <detail/crypto/base64.hpp>
#include <detail/crypto/sha.hpp> #include <detail/crypto/sha.hpp>
#include <detail/pole.hpp>
#include <detail/xlsx_consumer.hpp>
#include <detail/xlsx_producer.hpp>
#include <detail/constants.hpp>
#include <detail/vector_streambuf.hpp>
#include <detail/default_case.hpp> #include <detail/default_case.hpp>
#include <detail/crypto/xlsx_crypto.hpp> #include <detail/include_libstudxml.hpp>
namespace { namespace {
enum class hash_algorithm
{
sha1,
sha256,
sha384,
sha512,
md5,
md4,
md2,
ripemd128,
ripemd160,
whirlpool
};
struct XLNT_API crypto_helper
{
static const std::size_t segment_length;
enum class cipher_algorithm
{
aes,
rc2,
rc4,
des,
desx,
triple_des,
triple_des_112
};
enum class cipher_chaining
{
ecb, // electronic code book
cbc, // cipher block chaining
cfb // cipher feedback chaining
};
enum class cipher_direction
{
encryption,
decryption
};
static std::vector<std::uint8_t> aes(const std::vector<std::uint8_t> &key, const std::vector<std::uint8_t> &iv,
const std::vector<std::uint8_t> &source, cipher_chaining chaining, cipher_direction direction);
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 standard_encryption_info
{
const std::size_t spin_count = 50000;
std::size_t block_size;
std::size_t key_bits;
std::size_t key_bytes;
std::size_t hash_size;
cipher_algorithm cipher;
cipher_chaining chaining;
const hash_algorithm hash = hash_algorithm::sha1;
std::vector<std::uint8_t> salt_value;
std::vector<std::uint8_t> verifier_hash_input;
std::vector<std::uint8_t> verifier_hash_value;
std::vector<std::uint8_t> encrypted_key_value;
};
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
{
// key data
struct
{
std::size_t salt_size;
std::size_t block_size;
std::size_t key_bits;
std::size_t hash_size;
std::string cipher_algorithm;
std::string cipher_chaining;
std::string hash_algorithm;
std::vector<std::uint8_t> salt_value;
} key_data;
struct
{
std::vector<std::uint8_t> hmac_key;
std::vector<std::uint8_t> hmac_value;
} data_integrity;
struct
{
std::size_t spin_count;
std::size_t salt_size;
std::size_t block_size;
std::size_t key_bits;
std::size_t hash_size;
std::string cipher_algorithm;
std::string cipher_chaining;
hash_algorithm hash;
std::vector<std::uint8_t> salt_value;
std::vector<std::uint8_t> verifier_hash_input;
std::vector<std::uint8_t> verifier_hash_value;
std::vector<std::uint8_t> encrypted_key_value;
} key_encryptor;
};
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>
auto read_int(std::size_t &index, const std::vector<std::uint8_t> &raw_data) auto read_int(std::size_t &index, const std::vector<std::uint8_t> &raw_data)
{ {
@ -56,6 +181,7 @@ std::vector<std::uint8_t> decode_base64(const std::string &encoded)
return decoded; return decoded;
} }
/*
std::string encode_base64(const std::vector<std::uint8_t> &decoded) std::string encode_base64(const std::vector<std::uint8_t> &decoded)
{ {
std::string encoded(static_cast<std::size_t>(Base64::EncodedLength(decoded.size())), 0); std::string encoded(static_cast<std::size_t>(Base64::EncodedLength(decoded.size())), 0);
@ -63,74 +189,8 @@ std::string encode_base64(const std::vector<std::uint8_t> &decoded)
return encoded; return encoded;
} }
*/
} // namespace
namespace xml {
template <>
struct value_traits<xlnt::detail::hash_algorithm>
{
static xlnt::detail::hash_algorithm parse(std::string hash_algorithm_string, const parser &)
{
if (hash_algorithm_string == "SHA1")
return xlnt::detail::hash_algorithm::sha1;
else if (hash_algorithm_string == "SHA256")
return xlnt::detail::hash_algorithm::sha256;
else if (hash_algorithm_string == "SHA384")
return xlnt::detail::hash_algorithm::sha384;
else if (hash_algorithm_string == "SHA512")
return xlnt::detail::hash_algorithm::sha512;
else if (hash_algorithm_string == "MD5")
return xlnt::detail::hash_algorithm::md5;
else if (hash_algorithm_string == "MD4")
return xlnt::detail::hash_algorithm::md4;
else if (hash_algorithm_string == "MD2")
return xlnt::detail::hash_algorithm::md2;
else if (hash_algorithm_string == "Ripemd128")
return xlnt::detail::hash_algorithm::ripemd128;
else if (hash_algorithm_string == "Ripemd160")
return xlnt::detail::hash_algorithm::ripemd160;
else if (hash_algorithm_string == "Whirlpool")
return xlnt::detail::hash_algorithm::whirlpool;
default_case(xlnt::detail::hash_algorithm::sha1);
}
static std::string serialize(xlnt::detail::hash_algorithm algorithm, const serializer &)
{
switch (algorithm)
{
case xlnt::detail::hash_algorithm::sha1:
return "SHA1";
case xlnt::detail::hash_algorithm::sha256:
return "SHA256";
case xlnt::detail::hash_algorithm::sha384:
return "SHA384";
case xlnt::detail::hash_algorithm::sha512:
return "SHA512";
case xlnt::detail::hash_algorithm::md5:
return "MD5";
case xlnt::detail::hash_algorithm::md4:
return "MD4";
case xlnt::detail::hash_algorithm::md2:
return "MD2";
case xlnt::detail::hash_algorithm::ripemd128:
return "Ripemd128";
case xlnt::detail::hash_algorithm::ripemd160:
return "Ripemd160";
case xlnt::detail::hash_algorithm::whirlpool:
return "Whirlpool";
}
default_case("SHA1");
}
}; // struct value_traits<>
} // namespace xml
namespace xlnt {
namespace detail {
std::vector<std::uint8_t> crypto_helper::aes( std::vector<std::uint8_t> crypto_helper::aes(
const std::vector<std::uint8_t> &key, const std::vector<std::uint8_t> &key,
@ -140,19 +200,19 @@ std::vector<std::uint8_t> crypto_helper::aes(
{ {
if (direction == cipher_direction::encryption && chaining == cipher_chaining::cbc) if (direction == cipher_direction::encryption && chaining == cipher_chaining::cbc)
{ {
return xaes_cbc_encrypt(source, key, iv); return xlnt::detail::aes_cbc_encrypt(source, key, iv);
} }
else if (direction == cipher_direction::decryption && chaining == cipher_chaining::cbc) else if (direction == cipher_direction::decryption && chaining == cipher_chaining::cbc)
{ {
return xaes_cbc_decrypt(source, key, iv); return xlnt::detail::aes_cbc_decrypt(source, key, iv);
} }
else if (direction == cipher_direction::encryption && chaining == cipher_chaining::ecb) else if (direction == cipher_direction::encryption && chaining == cipher_chaining::ecb)
{ {
return xaes_ecb_encrypt(source, key); return xlnt::detail::aes_ecb_encrypt(source, key);
} }
else if (direction == cipher_direction::decryption && chaining == cipher_chaining::ecb) else if (direction == cipher_direction::decryption && chaining == cipher_chaining::ecb)
{ {
return xaes_ecb_decrypt(source, key); return xlnt::detail::aes_ecb_decrypt(source, key);
} }
throw xlnt::exception("unsupported encryption algorithm"); throw xlnt::exception("unsupported encryption algorithm");
@ -324,6 +384,7 @@ crypto_helper::agile_encryption_info crypto_helper::generate_agile_encryption_in
return result; return result;
} }
/*
std::vector<std::uint8_t> crypto_helper::write_agile_encryption_info(const std::string &password) std::vector<std::uint8_t> crypto_helper::write_agile_encryption_info(const std::string &password)
{ {
static const auto &xmlns = xlnt::constants::ns("encryption"); static const auto &xmlns = xlnt::constants::ns("encryption");
@ -378,6 +439,7 @@ std::vector<std::uint8_t> crypto_helper::write_agile_encryption_info(const std::
return encryption_info; return encryption_info;
} }
*/
std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_agile( std::vector<std::uint8_t> crypto_helper::decrypt_xlsx_agile(
const std::vector<std::uint8_t> &encryption_info, const std::vector<std::uint8_t> &encryption_info,
@ -644,6 +706,81 @@ std::vector<std::uint8_t> crypto_helper::encrypt_xlsx(
const std::size_t crypto_helper::segment_length = 4096; const std::size_t crypto_helper::segment_length = 4096;
} // namespace
namespace xml {
template <>
struct value_traits<hash_algorithm>
{
/*
static hash_algorithm parse(std::string hash_algorithm_string, const parser &)
{
if (hash_algorithm_string == "SHA1")
return hash_algorithm::sha1;
else if (hash_algorithm_string == "SHA256")
return hash_algorithm::sha256;
else if (hash_algorithm_string == "SHA384")
return hash_algorithm::sha384;
else if (hash_algorithm_string == "SHA512")
return hash_algorithm::sha512;
else if (hash_algorithm_string == "MD5")
return hash_algorithm::md5;
else if (hash_algorithm_string == "MD4")
return hash_algorithm::md4;
else if (hash_algorithm_string == "MD2")
return hash_algorithm::md2;
else if (hash_algorithm_string == "Ripemd128")
return hash_algorithm::ripemd128;
else if (hash_algorithm_string == "Ripemd160")
return hash_algorithm::ripemd160;
else if (hash_algorithm_string == "Whirlpool")
return hash_algorithm::whirlpool;
default_case(hash_algorithm::sha1);
}
static std::string serialize(hash_algorithm algorithm, const serializer &)
{
switch (algorithm)
{
case hash_algorithm::sha1:
return "SHA1";
case hash_algorithm::sha256:
return "SHA256";
case hash_algorithm::sha384:
return "SHA384";
case hash_algorithm::sha512:
return "SHA512";
case hash_algorithm::md5:
return "MD5";
case hash_algorithm::md4:
return "MD4";
case hash_algorithm::md2:
return "MD2";
case hash_algorithm::ripemd128:
return "Ripemd128";
case hash_algorithm::ripemd160:
return "Ripemd160";
case hash_algorithm::whirlpool:
return "Whirlpool";
}
default_case("SHA1");
}
*/
}; // struct value_traits<>
} // namespace xml
namespace xlnt {
namespace detail {
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);
}
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>()));

View File

@ -21,138 +21,18 @@
// @license: http://www.opensource.org/licenses/mit-license.php // @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file // @author: see AUTHORS file
#include <array> #include <cstdint>
#include <string>
#include <vector>
#include <xlnt/xlnt_config.hpp> #include <xlnt/xlnt_config.hpp>
#include <xlnt/utils/exceptions.hpp>
#include <xlnt/workbook/workbook.hpp>
#include <detail/constants.hpp>
#include <detail/include_libstudxml.hpp>
#include <detail/pole.hpp>
#include <detail/vector_streambuf.hpp>
#include <detail/xlsx_consumer.hpp>
#include <detail/xlsx_producer.hpp>
namespace xlnt { namespace xlnt {
namespace detail { namespace detail {
enum class hash_algorithm std::vector<std::uint8_t> XLNT_API decrypt_xlsx(const std::vector<std::uint8_t> &bytes, const std::string &password);
{
sha1,
sha256,
sha384,
sha512,
md5,
md4,
md2,
ripemd128,
ripemd160,
whirlpool
};
struct XLNT_API crypto_helper //static std::vector<std::uint8_t> encrypt_xlsx(const std::vector<std::uint8_t> &bytes, const std::string &password);
{
static const std::size_t segment_length;
enum class cipher_algorithm
{
aes,
rc2,
rc4,
des,
desx,
triple_des,
triple_des_112
};
enum class cipher_chaining
{
ecb, // electronic code book
cbc, // cipher block chaining
cfb // cipher feedback chaining
};
enum class cipher_direction
{
encryption,
decryption
};
static std::vector<std::uint8_t> aes(const std::vector<std::uint8_t> &key, const std::vector<std::uint8_t> &iv,
const std::vector<std::uint8_t> &source, cipher_chaining chaining, cipher_direction direction);
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 standard_encryption_info
{
const std::size_t spin_count = 50000;
std::size_t block_size;
std::size_t key_bits;
std::size_t key_bytes;
std::size_t hash_size;
cipher_algorithm cipher;
cipher_chaining chaining;
const hash_algorithm hash = hash_algorithm::sha1;
std::vector<std::uint8_t> salt_value;
std::vector<std::uint8_t> verifier_hash_input;
std::vector<std::uint8_t> verifier_hash_value;
std::vector<std::uint8_t> encrypted_key_value;
};
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
{
// key data
struct
{
std::size_t salt_size;
std::size_t block_size;
std::size_t key_bits;
std::size_t hash_size;
std::string cipher_algorithm;
std::string cipher_chaining;
std::string hash_algorithm;
std::vector<std::uint8_t> salt_value;
} key_data;
struct
{
std::vector<std::uint8_t> hmac_key;
std::vector<std::uint8_t> hmac_value;
} data_integrity;
struct
{
std::size_t spin_count;
std::size_t salt_size;
std::size_t block_size;
std::size_t key_bits;
std::size_t hash_size;
std::string cipher_algorithm;
std::string cipher_chaining;
hash_algorithm hash;
std::vector<std::uint8_t> salt_value;
std::vector<std::uint8_t> verifier_hash_input;
std::vector<std::uint8_t> verifier_hash_value;
std::vector<std::uint8_t> encrypted_key_value;
} key_encryptor;
};
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);
};
} // namespace detail } // namespace detail
} // namespace xlnt } // namespace xlnt

View File

@ -40,6 +40,7 @@ class rich_text;
class manifest; class manifest;
class path; class path;
class relationship; class relationship;
class variant;
class workbook; class workbook;
class worksheet; class worksheet;

View File

@ -40,7 +40,7 @@ public:
source_workbook.save(destination); source_workbook.save(destination);
std::ifstream source_stream(source.string(), std::ios::binary); std::ifstream source_stream(source.string(), std::ios::binary);
const auto source_decrypted = xlnt::detail::crypto_helper::decrypt_xlsx( const auto source_decrypted = xlnt::detail::decrypt_xlsx(
xlnt::detail::to_vector(source_stream), password); xlnt::detail::to_vector(source_stream), password);
return xml_helper::xlsx_archives_match(source_decrypted, destination); return xml_helper::xlsx_archives_match(source_decrypted, destination);