Skip to content

Commit

Permalink
Merge branch 'modernize'
Browse files Browse the repository at this point in the history
  • Loading branch information
kimci86 committed Mar 2, 2024
2 parents 0b5a891 + a82d1c6 commit 9481856
Show file tree
Hide file tree
Showing 33 changed files with 636 additions and 692 deletions.
26 changes: 13 additions & 13 deletions include/Arguments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Arguments
{
public:
/// Constructor
Error(const std::string& description);
explicit Error(const std::string& description);
};

/// \brief Constructor parsing command line arguments
Expand All @@ -29,7 +29,7 @@ class Arguments
/// \exception FileError if a file cannot be opened
/// \exception ZipError if a zip entry cannot be opened
/// \exception Data::Error if the loaded data cannot be used to carry out an attack
Data loadData() const;
auto loadData() const -> Data;

std::optional<std::string> cipherFile; ///< File containing the ciphertext
std::optional<std::size_t> cipherIndex; ///< Index of the zip entry containing ciphertext
Expand All @@ -50,7 +50,7 @@ class Arguments

/// Additional bytes of plaintext with their offset relative to ciphertext without encryption header (may be
/// negative)
std::map<int, byte> extraPlaintext;
std::map<int, std::uint8_t> extraPlaintext;

/// Tell not to use the check byte derived from ciphertext entry metadata as known plaintext
bool ignoreCheckByte = false;
Expand Down Expand Up @@ -92,7 +92,7 @@ class Arguments
std::optional<ChangeKeys> changeKeys;

/// Characters to generate password candidates
std::optional<bytevec> bruteforce;
std::optional<std::vector<std::uint8_t>> bruteforce;

/// Range of password lengths to try during password recovery
struct LengthInterval
Expand All @@ -104,7 +104,7 @@ class Arguments
std::size_t maxLength{std::numeric_limits<std::size_t>::max()};

/// Compute the intersection between this interval and the given \a other interval
LengthInterval operator&(const LengthInterval& other) const;
auto operator&(const LengthInterval& other) const -> LengthInterval;
};
/// \copydoc LengthInterval
std::optional<LengthInterval> length;
Expand All @@ -131,7 +131,7 @@ class Arguments
const char** m_current;
const char** const m_end;

bool finished() const;
auto finished() const -> bool;

void parseArgument();

Expand Down Expand Up @@ -165,13 +165,13 @@ class Arguments
help
};

std::string readString(const std::string& description);
Option readOption(const std::string& description);
int readInt(const std::string& description);
std::size_t readSize(const std::string& description);
bytevec readHex(const std::string& description);
uint32 readKey(const std::string& description);
bytevec readCharset();
auto readString(const std::string& description) -> std::string;
auto readOption(const std::string& description) -> Option;
auto readInt(const std::string& description) -> int;
auto readSize(const std::string& description) -> std::size_t;
auto readHex(const std::string& description) -> std::vector<std::uint8_t>;
auto readKey(const std::string& description) -> std::uint32_t;
auto readCharset() -> std::vector<std::uint8_t>;
};

#endif // BKCRACK_ARGUMENTS_HPP
23 changes: 10 additions & 13 deletions include/Attack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,13 @@ class Attack
bool exhaustive, Progress& progress);

/// Carry out the attack for the given Z[2,32) value
void carryout(uint32 z7_2_32);
void carryout(std::uint32_t z7_2_32);

enum : std::size_t
{
/// Number of contiguous known plaintext bytes required by the attack
CONTIGUOUS_SIZE = 8,
/// Number of contiguous known plaintext bytes required by the attack
static constexpr std::size_t contiguousSize = 8;

/// Total number of known plaintext bytes required by the attack
ATTACK_SIZE = 12
};
/// Total number of known plaintext bytes required by the attack
static constexpr std::size_t attackSize = 12;

private:
// iterate recursively over Z-lists
Expand All @@ -56,9 +53,9 @@ class Attack
const bool exhaustive;
Progress& progress;

u32arr<CONTIGUOUS_SIZE> zlist;
u32arr<CONTIGUOUS_SIZE> ylist; // the first two elements are not used
u32arr<CONTIGUOUS_SIZE> xlist; // the first four elements are not used
std::array<std::uint32_t, contiguousSize> zlist;
std::array<std::uint32_t, contiguousSize> ylist; // the first two elements are not used
std::array<std::uint32_t, contiguousSize> xlist; // the first four elements are not used
};

/// \brief Iterate on Zi[2,32) candidates to try and find complete internal keys
Expand All @@ -71,7 +68,7 @@ class Attack
/// \param exhaustive True to try and find all valid keys,
/// false to stop searching after the first one is found
/// \param progress Object to report progress
std::vector<Keys> attack(const Data& data, const u32vec& zi_2_32_vector, int& start, std::size_t index, int jobs,
bool exhaustive, Progress& progress);
auto attack(const Data& data, const std::vector<std::uint32_t>& zi_2_32_vector, int& start, std::size_t index, int jobs,
bool exhaustive, Progress& progress) -> std::vector<Keys>;

#endif // BKCRACK_ATTACK_HPP
3 changes: 2 additions & 1 deletion include/ConsoleProgress.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class ConsoleProgress : public Progress
{
public:
/// Start a thread to print progress
ConsoleProgress(std::ostream& os, const std::chrono::milliseconds& interval = std::chrono::milliseconds(200));
explicit ConsoleProgress(std::ostream& os,
const std::chrono::milliseconds& interval = std::chrono::milliseconds{200});

/// Notify and stop the printing thread
~ConsoleProgress();
Expand Down
20 changes: 7 additions & 13 deletions include/Crc32Tab.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,36 @@ class Crc32Tab
{
public:
/// \return CRC32 using a lookup table
static inline uint32 crc32(uint32 pval, byte b)
static auto crc32(std::uint32_t pval, std::uint8_t b) -> std::uint32_t
{
return pval >> 8 ^ instance.crctab[lsb(pval) ^ b];
}

/// \return CRC32^-1 using a lookup table
static inline uint32 crc32inv(uint32 crc, byte b)
static auto crc32inv(std::uint32_t crc, std::uint8_t b) -> std::uint32_t
{
return crc << 8 ^ instance.crcinvtab[msb(crc)] ^ b;
}

/// \return Yi[24,32) from Zi and Z{i-1} using CRC32^-1
static inline uint32 getYi_24_32(uint32 zi, uint32 zim1)
static auto getYi_24_32(std::uint32_t zi, std::uint32_t zim1) -> std::uint32_t
{
return (crc32inv(zi, 0) ^ zim1) << 24;
}

/// \return Z{i-1}[10,32) from Zi[2,32) using CRC32^-1
static inline uint32 getZim1_10_32(uint32 zi_2_32)
static auto getZim1_10_32(std::uint32_t zi_2_32) -> std::uint32_t
{
return crc32inv(zi_2_32, 0) & MASK_10_32; // discard 10 least significant bits
return crc32inv(zi_2_32, 0) & mask<10, 32>; // discard 10 least significant bits
}

private:
// initialize lookup tables
Crc32Tab();

// lookup tables
u32arr<256> crctab;
u32arr<256> crcinvtab;

// CRC32 polynomial representation
enum : uint32
{
CRCPOL = 0xedb88320
};
std::array<std::uint32_t, 256> crctab;
std::array<std::uint32_t, 256> crcinvtab;

static const Crc32Tab instance;
};
Expand Down
19 changes: 9 additions & 10 deletions include/Data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@
/// Structure to hold the data needed for an attack
struct Data
{
enum : std::size_t
{
ENCRYPTION_HEADER_SIZE = 12
};
/// Size of the traditional PKWARE encryption header
static constexpr std::size_t encryptionHeaderSize = 12;

/// Exception thrown if data cannot be used to carry out an attack
class Error : public BaseError
{
public:
/// Constructor
Error(const std::string& description);
explicit Error(const std::string& description);
};

/// \brief Construct data and check it can be used to carry out an attack
Expand All @@ -28,17 +26,18 @@ struct Data
/// \param extraPlaintext Additional bytes of plaintext with their offset relative to ciphertext without encryption
/// header (may be negative)
/// \exception Error if the given data cannot be used to carry out an attack
Data(bytevec ciphertext, bytevec plaintext, int offset, const std::map<int, byte>& extraPlaintext);
Data(std::vector<std::uint8_t> ciphertext, std::vector<std::uint8_t> plaintext, int offset,
const std::map<int, std::uint8_t>& extraPlaintext);

bytevec ciphertext; ///< ciphertext bytes including encryption header
bytevec plaintext; ///< plaintext bytes
bytevec keystream; ///< keystream bytes
std::vector<std::uint8_t> ciphertext; ///< ciphertext bytes including encryption header
std::vector<std::uint8_t> plaintext; ///< plaintext bytes
std::vector<std::uint8_t> keystream; ///< keystream bytes

/// plaintext and keystream offset relative to ciphertext with encryption header
std::size_t offset;

/// additional bytes of plaintext with their offset relative to ciphertext with encryption header
std::vector<std::pair<std::size_t, byte>> extraPlaintext;
std::vector<std::pair<std::size_t, std::uint8_t>> extraPlaintext;
};

#endif // BKCRACK_DATA_HPP
37 changes: 21 additions & 16 deletions include/Keys.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,68 +9,73 @@
class Keys
{
public:
/// Constructor
Keys(uint32 x = 0x12345678, uint32 y = 0x23456789, uint32 z = 0x34567890);
/// Construct default state
Keys() = default;

/// Construct keys from given components
Keys(std::uint32_t x, std::uint32_t y, std::uint32_t z);

/// Construct keys associated to the given password
Keys(const std::string& password);
explicit Keys(const std::string& password);

/// Update the state with a plaintext byte
inline void update(byte p)
void update(std::uint8_t p)
{
x = Crc32Tab::crc32(x, p);
y = (y + lsb(x)) * MultTab::MULT + 1;
y = (y + lsb(x)) * MultTab::mult + 1;
z = Crc32Tab::crc32(z, msb(y));
}

/// Update the state forward to a target offset
void update(const bytevec& ciphertext, std::size_t current, std::size_t target);
void update(const std::vector<std::uint8_t>& ciphertext, std::size_t current, std::size_t target);

/// Update the state backward with a ciphertext byte
inline void updateBackward(byte c)
void updateBackward(std::uint8_t c)
{
z = Crc32Tab::crc32inv(z, msb(y));
y = (y - 1) * MultTab::MULTINV - lsb(x);
y = (y - 1) * MultTab::multInv - lsb(x);
x = Crc32Tab::crc32inv(x, c ^ getK());
}

/// Update the state backward with a plaintext byte
inline void updateBackwardPlaintext(byte p)
void updateBackwardPlaintext(std::uint8_t p)
{
z = Crc32Tab::crc32inv(z, msb(y));
y = (y - 1) * MultTab::MULTINV - lsb(x);
y = (y - 1) * MultTab::multInv - lsb(x);
x = Crc32Tab::crc32inv(x, p);
}

/// Update the state backward to a target offset
void updateBackward(const bytevec& ciphertext, std::size_t current, std::size_t target);
void updateBackward(const std::vector<std::uint8_t>& ciphertext, std::size_t current, std::size_t target);

/// \return X value
uint32 getX() const
auto getX() const -> std::uint32_t
{
return x;
}

/// \return Y value
uint32 getY() const
auto getY() const -> std::uint32_t
{
return y;
}

/// \return Z value
uint32 getZ() const
auto getZ() const -> std::uint32_t
{
return z;
}

/// \return the keystream byte derived from the keys
byte getK() const
auto getK() const -> std::uint8_t
{
return KeystreamTab::getByte(z);
}

private:
uint32 x, y, z;
std::uint32_t x = 0x12345678;
std::uint32_t y = 0x23456789;
std::uint32_t z = 0x34567890;
};

#endif // BKCRACK_KEYS_HPP
18 changes: 9 additions & 9 deletions include/KeystreamTab.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,34 @@ class KeystreamTab
public:
/// \return the keystream byte ki associated to a Zi value
/// \note Only Zi[2,16) is used
static inline byte getByte(uint32 zi)
static auto getByte(std::uint32_t zi) -> std::uint8_t
{
return instance.keystreamtab[(zi & MASK_0_16) >> 2];
return instance.keystreamtab[(zi & mask<0, 16>) >> 2];
}

/// \return a vector of Zi[2,16) values having given [10,16) bits
/// such that getByte(zi) is equal to ki
/// \note the vector contains one element on average
static inline const u32vec& getZi_2_16_vector(byte ki, uint32 zi_10_16)
static auto getZi_2_16_vector(std::uint8_t ki, std::uint32_t zi_10_16) -> const std::vector<std::uint32_t>&
{
return instance.keystreaminvfiltertab[ki][(zi_10_16 & MASK_0_16) >> 10];
return instance.keystreaminvfiltertab[ki][(zi_10_16 & mask<0, 16>) >> 10];
}

/// \return true if the vector returned by getZi_2_16_vector is not empty,
/// false otherwise
static inline bool hasZi_2_16(byte ki, uint32 zi_10_16)
static auto hasZi_2_16(std::uint8_t ki, std::uint32_t zi_10_16) -> bool
{
return instance.keystreaminvexists[ki][(zi_10_16 & MASK_0_16) >> 10];
return instance.keystreaminvexists[ki][(zi_10_16 & mask<0, 16>) >> 10];
}

private:
// initialize lookup tables
KeystreamTab();

// lookup tables
bytearr<1 << 14> keystreamtab;
std::array<std::array<u32vec, 64>, 256> keystreaminvfiltertab;
std::array<std::bitset<64>, 256> keystreaminvexists;
std::array<std::uint8_t, 1 << 14> keystreamtab;
std::array<std::array<std::vector<std::uint32_t>, 64>, 256> keystreaminvfiltertab;
std::array<std::bitset<64>, 256> keystreaminvexists;

static const KeystreamTab instance;
};
Expand Down
Loading

0 comments on commit 9481856

Please sign in to comment.