From a714d710a3274ea15fc26e870461f28741e7d86a Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 14:57:56 +0100 Subject: [PATCH 01/19] Use standard C++ types instead of custom aliases --- include/Arguments.hpp | 18 +++++----- include/Attack.hpp | 12 +++---- include/Crc32Tab.hpp | 14 ++++---- include/Data.hpp | 11 +++--- include/Keys.hpp | 22 ++++++------ include/KeystreamTab.hpp | 12 +++---- include/MultTab.hpp | 18 +++++----- include/Zip.hpp | 21 +++++------ include/Zreduction.hpp | 10 +++--- include/file.hpp | 10 +++--- include/password.hpp | 18 +++++----- include/types.hpp | 28 +++------------ src/Arguments.cpp | 24 ++++++------- src/Attack.cpp | 53 ++++++++++++++------------- src/Crc32Tab.cpp | 2 +- src/Data.cpp | 35 ++++++++++-------- src/Keys.cpp | 13 ++++--- src/KeystreamTab.cpp | 4 +-- src/MultTab.cpp | 4 +-- src/Zip.cpp | 78 ++++++++++++++++++++-------------------- src/Zreduction.cpp | 23 ++++++------ src/file.cpp | 6 ++-- src/main.cpp | 6 ++-- src/password.cpp | 52 +++++++++++++-------------- 24 files changed, 241 insertions(+), 253 deletions(-) diff --git a/include/Arguments.hpp b/include/Arguments.hpp index 22f5215..5cf23a7 100644 --- a/include/Arguments.hpp +++ b/include/Arguments.hpp @@ -50,7 +50,7 @@ class Arguments /// Additional bytes of plaintext with their offset relative to ciphertext without encryption header (may be /// negative) - std::map extraPlaintext; + std::map extraPlaintext; /// Tell not to use the check byte derived from ciphertext entry metadata as known plaintext bool ignoreCheckByte = false; @@ -92,7 +92,7 @@ class Arguments std::optional changeKeys; /// Characters to generate password candidates - std::optional bruteforce; + std::optional> bruteforce; /// Range of password lengths to try during password recovery struct LengthInterval @@ -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(); + 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); + std::vector readHex(const std::string& description); + std::uint32_t readKey(const std::string& description); + std::vector readCharset(); }; #endif // BKCRACK_ARGUMENTS_HPP diff --git a/include/Attack.hpp b/include/Attack.hpp index fb6ad0b..18b4149 100644 --- a/include/Attack.hpp +++ b/include/Attack.hpp @@ -26,7 +26,7 @@ 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 { @@ -56,9 +56,9 @@ class Attack const bool exhaustive; Progress& progress; - u32arr zlist; - u32arr ylist; // the first two elements are not used - u32arr xlist; // the first four elements are not used + std::array zlist; + std::array ylist; // the first two elements are not used + std::array xlist; // the first four elements are not used }; /// \brief Iterate on Zi[2,32) candidates to try and find complete internal keys @@ -71,7 +71,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 attack(const Data& data, const u32vec& zi_2_32_vector, int& start, std::size_t index, int jobs, - bool exhaustive, Progress& progress); +std::vector attack(const Data& data, const std::vector& zi_2_32_vector, int& start, + std::size_t index, int jobs, bool exhaustive, Progress& progress); #endif // BKCRACK_ATTACK_HPP diff --git a/include/Crc32Tab.hpp b/include/Crc32Tab.hpp index 226b295..5366a18 100644 --- a/include/Crc32Tab.hpp +++ b/include/Crc32Tab.hpp @@ -8,25 +8,25 @@ class Crc32Tab { public: /// \return CRC32 using a lookup table - static inline uint32 crc32(uint32 pval, byte b) + static inline std::uint32_t crc32(std::uint32_t pval, std::uint8_t b) { return pval >> 8 ^ instance.crctab[lsb(pval) ^ b]; } /// \return CRC32^-1 using a lookup table - static inline uint32 crc32inv(uint32 crc, byte b) + static inline std::uint32_t crc32inv(std::uint32_t crc, std::uint8_t b) { 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 inline std::uint32_t getYi_24_32(std::uint32_t zi, std::uint32_t zim1) { 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 inline std::uint32_t getZim1_10_32(std::uint32_t zi_2_32) { return crc32inv(zi_2_32, 0) & MASK_10_32; // discard 10 least significant bits } @@ -36,11 +36,11 @@ class Crc32Tab Crc32Tab(); // lookup tables - u32arr<256> crctab; - u32arr<256> crcinvtab; + std::array crctab; + std::array crcinvtab; // CRC32 polynomial representation - enum : uint32 + enum : std::uint32_t { CRCPOL = 0xedb88320 }; diff --git a/include/Data.hpp b/include/Data.hpp index 7819cdc..ee76f83 100644 --- a/include/Data.hpp +++ b/include/Data.hpp @@ -28,17 +28,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& extraPlaintext); + Data(std::vector ciphertext, std::vector plaintext, int offset, + const std::map& extraPlaintext); - bytevec ciphertext; ///< ciphertext bytes including encryption header - bytevec plaintext; ///< plaintext bytes - bytevec keystream; ///< keystream bytes + std::vector ciphertext; ///< ciphertext bytes including encryption header + std::vector plaintext; ///< plaintext bytes + std::vector 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> extraPlaintext; + std::vector> extraPlaintext; }; #endif // BKCRACK_DATA_HPP diff --git a/include/Keys.hpp b/include/Keys.hpp index 95e9359..ea81ded 100644 --- a/include/Keys.hpp +++ b/include/Keys.hpp @@ -10,13 +10,13 @@ class Keys { public: /// Constructor - Keys(uint32 x = 0x12345678, uint32 y = 0x23456789, uint32 z = 0x34567890); + Keys(std::uint32_t x = 0x12345678, std::uint32_t y = 0x23456789, std::uint32_t z = 0x34567890); /// Construct keys associated to the given password Keys(const std::string& password); /// Update the state with a plaintext byte - inline void update(byte p) + inline void update(std::uint8_t p) { x = Crc32Tab::crc32(x, p); y = (y + lsb(x)) * MultTab::MULT + 1; @@ -24,10 +24,10 @@ class Keys } /// 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& ciphertext, std::size_t current, std::size_t target); /// Update the state backward with a ciphertext byte - inline void updateBackward(byte c) + inline void updateBackward(std::uint8_t c) { z = Crc32Tab::crc32inv(z, msb(y)); y = (y - 1) * MultTab::MULTINV - lsb(x); @@ -35,7 +35,7 @@ class Keys } /// Update the state backward with a plaintext byte - inline void updateBackwardPlaintext(byte p) + inline void updateBackwardPlaintext(std::uint8_t p) { z = Crc32Tab::crc32inv(z, msb(y)); y = (y - 1) * MultTab::MULTINV - lsb(x); @@ -43,34 +43,34 @@ class Keys } /// 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& ciphertext, std::size_t current, std::size_t target); /// \return X value - uint32 getX() const + std::uint32_t getX() const { return x; } /// \return Y value - uint32 getY() const + std::uint32_t getY() const { return y; } /// \return Z value - uint32 getZ() const + std::uint32_t getZ() const { return z; } /// \return the keystream byte derived from the keys - byte getK() const + std::uint8_t getK() const { return KeystreamTab::getByte(z); } private: - uint32 x, y, z; + std::uint32_t x, y, z; }; #endif // BKCRACK_KEYS_HPP diff --git a/include/KeystreamTab.hpp b/include/KeystreamTab.hpp index a2de6d3..b55692f 100644 --- a/include/KeystreamTab.hpp +++ b/include/KeystreamTab.hpp @@ -11,7 +11,7 @@ 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 inline std::uint8_t getByte(std::uint32_t zi) { return instance.keystreamtab[(zi & MASK_0_16) >> 2]; } @@ -19,14 +19,14 @@ class KeystreamTab /// \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 inline const std::vector& getZi_2_16_vector(std::uint8_t ki, std::uint32_t zi_10_16) { 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 inline bool hasZi_2_16(std::uint8_t ki, std::uint32_t zi_10_16) { return instance.keystreaminvexists[ki][(zi_10_16 & MASK_0_16) >> 10]; } @@ -36,9 +36,9 @@ class KeystreamTab KeystreamTab(); // lookup tables - bytearr<1 << 14> keystreamtab; - std::array, 256> keystreaminvfiltertab; - std::array, 256> keystreaminvexists; + std::array keystreamtab; + std::array, 64>, 256> keystreaminvfiltertab; + std::array, 256> keystreaminvexists; static const KeystreamTab instance; }; diff --git a/include/MultTab.hpp b/include/MultTab.hpp index 55a1305..819b112 100644 --- a/include/MultTab.hpp +++ b/include/MultTab.hpp @@ -8,32 +8,32 @@ class MultTab { public: /// \return MULT * x using a lookup table - static inline uint32 getMult(byte x) + static inline std::uint32_t getMult(std::uint8_t x) { return instance.multtab[x]; } /// \return MULT^-1 * x using a lookup table - static inline uint32 getMultinv(byte x) + static inline std::uint32_t getMultinv(std::uint8_t x) { return instance.multinvtab[x]; } /// \return a vector of bytes x such that /// msb(x*MULT^-1) is equal to msbprod or msbprod-1 - static inline const bytevec& getMsbProdFiber2(byte msbprodinv) + static inline const std::vector& getMsbProdFiber2(std::uint8_t msbprodinv) { return instance.msbprodfiber2[msbprodinv]; } /// \return a vector of bytes x such that /// msb(x*MULT^-1) is equal to msbprod, msbprod-1 or msbprod+1 - static inline const bytevec& getMsbProdFiber3(byte msbprodinv) + static inline const std::vector& getMsbProdFiber3(std::uint8_t msbprodinv) { return instance.msbprodfiber3[msbprodinv]; } - enum : uint32 + enum : std::uint32_t { MULT = 0x08088405, MULTINV = 0xd94fa8cd @@ -44,10 +44,10 @@ class MultTab MultTab(); // lookup tables - u32arr<256> multtab; - u32arr<256> multinvtab; - std::array msbprodfiber2; - std::array msbprodfiber3; + std::array multtab; + std::array multinvtab; + std::array, 256> msbprodfiber2; + std::array, 256> msbprodfiber3; static const MultTab instance; }; diff --git a/include/Zip.hpp b/include/Zip.hpp index 17c7eb4..e7d5896 100644 --- a/include/Zip.hpp +++ b/include/Zip.hpp @@ -57,14 +57,14 @@ class Zip /// Information about a zip entry struct Entry { - std::string name; ///< File name - Encryption encryption; ///< Encryption method - Compression compression; ///< Compression method. \note It may take a value not listed in Compression - uint32 crc32; ///< CRC-32 checksum - uint64 offset; ///< Offset of local file header - uint64 packedSize; ///< Packed data size - uint64 uncompressedSize; ///< Uncompressed data size - byte checkByte; ///< Last byte of the encryption header after decryption + std::string name; ///< File name + Encryption encryption; ///< Encryption method + Compression compression; ///< Compression method. \note It may take a value not listed in Compression + std::uint32_t crc32; ///< CRC-32 checksum + std::uint64_t offset; ///< Offset of local file header + std::uint64_t packedSize; ///< Packed data size + std::uint64_t uncompressedSize; ///< Uncompressed data size + std::uint8_t checkByte; ///< Last byte of the encryption header after decryption }; /// Single-pass input iterator that reads successive Entry objects @@ -164,7 +164,8 @@ class Zip /// \brief Load at most \a count bytes of the given entry's raw data /// \exception Error if the given entry's data is not at the expected offset - bytevec load(const Entry& entry, std::size_t count = std::numeric_limits::max()) const; + std::vector load(const Entry& entry, + std::size_t count = std::numeric_limits::max()) const; /// \brief Copy the zip file into \a os changing the encrypted data using the given keys /// \exception Error if the archive is not a valid zip archive @@ -173,7 +174,7 @@ class Zip private: std::optional m_file; // optionally own the stream std::istream& m_is; - const uint64 m_centralDirectoryOffset; + const std::uint64_t m_centralDirectoryOffset; }; #endif // BKCRACK_ZIP_HPP diff --git a/include/Zreduction.hpp b/include/Zreduction.hpp index 0674fd8..8198cc4 100644 --- a/include/Zreduction.hpp +++ b/include/Zreduction.hpp @@ -9,7 +9,7 @@ class Zreduction { public: /// Constructor generating Zi[10,32) values from the last keystream byte - Zreduction(const bytevec& keystream); + Zreduction(const std::vector& keystream); /// Reduce Zi[10,32) number using extra contiguous keystream void reduce(Progress& progress); @@ -18,7 +18,7 @@ class Zreduction void generate(); /// \return the generated Zi[2,32) values - const u32vec& getCandidates() const; + const std::vector& getCandidates() const; /// \return the index of the Zi[2,32) values relative to keystream std::size_t getIndex() const; @@ -30,11 +30,11 @@ class Zreduction TRACK_SIZE = 1 << 16 }; - const bytevec& keystream; + const std::vector& keystream; // After constructor or reduce(), contains Z[10,32) values. // After generate(), contains Zi[2,32) values. - u32vec zi_vector; - std::size_t index; + std::vector zi_vector; + std::size_t index; }; #endif // BKCRACK_ZREDUCTION_HPP diff --git a/include/file.hpp b/include/file.hpp index ce8874b..fdc2394 100644 --- a/include/file.hpp +++ b/include/file.hpp @@ -12,11 +12,11 @@ /// /// input [ label="filename" ]; /// output [ label="filename" ]; -/// bytevec [ URL="\ref bytevec" ]; +/// buffer [ label="std::vector" ]; /// /// input -> "std::ifstream" [ label="openInput", URL="\ref openInput"]; -/// "std::ifstream" -> bytevec [ label="loadStream", URL="\ref loadStream"]; -/// input -> bytevec [ label="loadFile", URL="\ref loadFile"]; +/// "std::ifstream" -> buffer [ label="loadStream", URL="\ref loadStream"]; +/// input -> buffer [ label="loadFile", URL="\ref loadFile"]; /// /// output -> "std::ofstream" [ label="openOutput", URL="\ref openOutput"]; /// } @@ -39,11 +39,11 @@ class FileError : public BaseError std::ifstream openInput(const std::string& filename); /// Load at most \a size bytes from an input stream -bytevec loadStream(std::istream& is, std::size_t size); +std::vector loadStream(std::istream& is, std::size_t size); /// \brief Load at most \a size bytes from a file /// \exception FileError if the file cannot be opened -bytevec loadFile(const std::string& filename, std::size_t size); +std::vector loadFile(const std::string& filename, std::size_t size); /// \brief Open an output file stream /// \exception FileError if the file cannot be opened diff --git a/include/password.hpp b/include/password.hpp index 40c8445..734968d 100644 --- a/include/password.hpp +++ b/include/password.hpp @@ -14,8 +14,8 @@ class Recovery { public: /// Constructor - Recovery(const Keys& keys, const bytevec& charset, std::vector& solutions, std::mutex& solutionsMutex, - bool exhaustive, Progress& progress); + Recovery(const Keys& keys, const std::vector& charset, std::vector& solutions, + std::mutex& solutionsMutex, bool exhaustive, Progress& progress); /// \brief Look for a password of length 6 or less /// @@ -46,7 +46,7 @@ class Recovery std::string prefix; /// Set of characters to generate password candidates - const bytevec& charset; + const std::vector& charset; private: // iterate recursively on possible Y values @@ -60,10 +60,10 @@ class Recovery // cipher state (X,Y,Z)_i for index i in [0, 6] where the last state (X,Y,Z)_6 is // the representation of the password to recover - u32arr<7> x, y, z; - uint32 x0; // backup of candidate X value for convenience + std::array x, y, z; + std::uint32_t x0; // backup of candidate X value for convenience - bytearr<6> p; // password last 6 bytes + std::array p; // password last 6 bytes std::vector& solutions; // shared output vector of valid passwords std::mutex& solutionsMutex; @@ -85,8 +85,8 @@ class Recovery /// \return A vector of passwords associated with the given keys. /// A vector is needed instead of a single string because there can be /// collisions (i.e. several passwords for the same keys). -std::vector recoverPassword(const Keys& keys, const bytevec& charset, std::size_t minLength, - std::size_t maxLength, std::string& start, int jobs, bool exhaustive, - Progress& progress); +std::vector recoverPassword(const Keys& keys, const std::vector& charset, + std::size_t minLength, std::size_t maxLength, std::string& start, int jobs, + bool exhaustive, Progress& progress); #endif // BKCRACK_PASSWORD_HPP diff --git a/include/types.hpp b/include/types.hpp index d7b9658..82ef438 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -2,7 +2,7 @@ #define BKCRACK_TYPES_HPP /// \file types.hpp -/// \brief Typedefs, useful constants and utility functions +/// \brief Useful types, constants and utility functions #include #include @@ -18,34 +18,16 @@ class BaseError : public std::runtime_error BaseError(const std::string& type, const std::string& description); }; -// scalar types - -using byte = std::uint8_t; ///< Unsigned integer type with width of exactly 8 bits -using uint16 = std::uint16_t; ///< Unsigned integer type with width of exactly 16 bits -using uint32 = std::uint32_t; ///< Unsigned integer type with width of exactly 32 bits -using uint64 = std::uint64_t; ///< Unsigned integer type with width of exactly 64 bits - -// container types - -template -using bytearr = std::array; ///< Array of bytes - -template -using u32arr = std::array; ///< Array of 32-bits integers - -using bytevec = std::vector; ///< Vector of bytes -using u32vec = std::vector; ///< Vector of 32-bits integers - // utility functions /// \return the least significant byte of x -inline byte lsb(uint32 x) +inline std::uint8_t lsb(std::uint32_t x) { return x; } /// \return the most significant byte of x -inline byte msb(uint32 x) +inline std::uint8_t msb(std::uint32_t x) { return x >> 24; } @@ -59,7 +41,7 @@ inline std::size_t absdiff(std::size_t x, std::size_t y) // constants /// Useful constants for masking -enum : uint32 +enum : std::uint32_t { MASK_0_16 = 0x0000ffff, MASK_0_24 = 0x00ffffff, @@ -81,7 +63,7 @@ enum : uint32 /// A = B[0,x) + B[x,32) + b /// A - B[x,32) = B[0,x) + b /// A - B[x,32) <= 0xffffffff[0,x) + 0xff -enum : uint32 +enum : std::uint32_t { MAXDIFF_0_24 = MASK_0_24 + 0xff, MAXDIFF_0_26 = MASK_0_26 + 0xff diff --git a/src/Arguments.cpp b/src/Arguments.cpp index b18d4a9..d126127 100644 --- a/src/Arguments.cpp +++ b/src/Arguments.cpp @@ -148,7 +148,7 @@ Arguments::Arguments(int argc, const char* argv[]) Data Arguments::loadData() const { // load known plaintext - bytevec plaintext; + std::vector plaintext; if (plainArchive) { const auto archive = Zip{*plainArchive}; @@ -166,8 +166,8 @@ Data Arguments::loadData() const if (!extraPlaintext.empty()) needed = std::max(needed, Data::ENCRYPTION_HEADER_SIZE + extraPlaintext.rbegin()->first + 1); - bytevec ciphertext; - std::optional> extraPlaintextWithCheckByte; + std::vector ciphertext; + std::optional> extraPlaintextWithCheckByte; if (cipherArchive) { const auto archive = Zip{*cipherArchive}; @@ -229,7 +229,7 @@ void Arguments::parseArgument() case Option::extraPlaintext: { int i = readInt("offset"); - for (byte b : readHex("data")) + for (std::uint8_t b : readHex("data")) extraPlaintext[i++] = b; break; } @@ -287,7 +287,7 @@ void Arguments::parseArgument() break; case Option::recoveryStart: { - const bytevec checkpoint = readHex("checkpoint"); + const auto checkpoint = readHex("checkpoint"); recoveryStart.assign(checkpoint.begin(), checkpoint.end()); break; } @@ -373,7 +373,7 @@ std::size_t Arguments::readSize(const std::string& description) return parseSize(readString(description)); } -bytevec Arguments::readHex(const std::string& description) +std::vector Arguments::readHex(const std::string& description) { std::string str = readString(description); @@ -382,14 +382,14 @@ bytevec Arguments::readHex(const std::string& description) if (!std::all_of(str.begin(), str.end(), [](unsigned char c) { return std::isxdigit(c); })) throw Error("expected " + description + " in hexadecimal, got " + str); - bytevec data; + std::vector data; for (std::size_t i = 0; i < str.length(); i += 2) - data.push_back(static_cast(std::stoul(str.substr(i, 2), nullptr, 16))); + data.push_back(static_cast(std::stoul(str.substr(i, 2), nullptr, 16))); return data; } -uint32 Arguments::readKey(const std::string& description) +std::uint32_t Arguments::readKey(const std::string& description) { std::string str = readString(description); @@ -398,10 +398,10 @@ uint32 Arguments::readKey(const std::string& description) if (!std::all_of(str.begin(), str.end(), [](unsigned char c) { return std::isxdigit(c); })) throw Error("expected " + description + " in hexadecimal, got " + str); - return static_cast(std::stoul(str, nullptr, 16)); + return static_cast(std::stoul(str, nullptr, 16)); } -bytevec Arguments::readCharset() +std::vector Arguments::readCharset() { const std::bitset<256> lowercase = charRange('a', 'z'); const std::bitset<256> uppercase = charRange('A', 'Z'); @@ -446,7 +446,7 @@ bytevec Arguments::readCharset() charset.set(*it); } - bytevec result; + std::vector result; for (int c = 0; c < 256; c++) if (charset[c]) result.push_back(c); diff --git a/src/Attack.cpp b/src/Attack.cpp index a7e42e8..38af82b 100644 --- a/src/Attack.cpp +++ b/src/Attack.cpp @@ -20,7 +20,7 @@ Attack::Attack(const Data& data, std::size_t index, std::vector& solutions { } -void Attack::carryout(uint32 z7_2_32) +void Attack::carryout(std::uint32_t z7_2_32) { zlist[7] = z7_2_32; exploreZlists(7); @@ -31,10 +31,10 @@ void Attack::exploreZlists(int i) if (i != 0) // the Z-list is not complete so generate Z{i-1}[2,32) values { // get Z{i-1}[10,32) from CRC32^-1 - uint32 zim1_10_32 = Crc32Tab::getZim1_10_32(zlist[i]); + std::uint32_t zim1_10_32 = Crc32Tab::getZim1_10_32(zlist[i]); // get Z{i-1}[2,16) values from keystream byte k{i-1} and Z{i-1}[10,16) - for (uint32 zim1_2_16 : KeystreamTab::getZi_2_16_vector(data.keystream[index + i - 1], zim1_10_32)) + for (std::uint32_t zim1_2_16 : KeystreamTab::getZi_2_16_vector(data.keystream[index + i - 1], zim1_10_32)) { // add Z{i-1}[2,32) to the Z-list zlist[i - 1] = zim1_10_32 | zim1_2_16; @@ -53,10 +53,10 @@ void Attack::exploreZlists(int i) else // the Z-list is complete so iterate over possible Y values { // guess Y7[8,24) and keep prod == (Y7[8,32) - 1) * mult^-1 - for (uint32 y7_8_24 = 0, prod = (MultTab::getMultinv(msb(ylist[7])) << 24) - MultTab::MULTINV; + for (std::uint32_t y7_8_24 = 0, prod = (MultTab::getMultinv(msb(ylist[7])) << 24) - MultTab::MULTINV; y7_8_24 < 1 << 24; y7_8_24 += 1 << 8, prod += MultTab::MULTINV << 8) // get possible Y7[0,8) values - for (byte y7_0_8 : MultTab::getMsbProdFiber3(msb(ylist[6]) - msb(prod))) + for (std::uint8_t y7_0_8 : MultTab::getMsbProdFiber3(msb(ylist[6]) - msb(prod))) // filter Y7[0,8) using Y6[24,32) if (prod + MultTab::getMultinv(y7_0_8) - (ylist[6] & MASK_24_32) <= MAXDIFF_0_24) { @@ -70,14 +70,14 @@ void Attack::exploreYlists(int i) { if (i != 3) // the Y-list is not complete so generate Y{i-1} values { - uint32 fy = (ylist[i] - 1) * MultTab::MULTINV; - uint32 ffy = (fy - 1) * MultTab::MULTINV; + std::uint32_t fy = (ylist[i] - 1) * MultTab::MULTINV; + std::uint32_t ffy = (fy - 1) * MultTab::MULTINV; // get possible LSB(Xi) - for (byte xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (ylist[i - 2] & MASK_24_32)))) + for (std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (ylist[i - 2] & MASK_24_32)))) { // compute corresponding Y{i-1} - uint32 yim1 = fy - xi_0_8; + std::uint32_t yim1 = fy - xi_0_8; // filter values with Y{i-2}[24,32) if (ffy - MultTab::getMultinv(xi_0_8) - (ylist[i - 2] & MASK_24_32) <= MAXDIFF_0_24 && @@ -105,20 +105,19 @@ void Attack::testXlist() | lsb(xlist[i]); // set the LSB // compute X3 - uint32 x = xlist[7]; + std::uint32_t x = xlist[7]; for (int i = 6; i >= 3; i--) x = Crc32Tab::crc32inv(x, data.plaintext[index + i]); // check that X3 fits with Y1[26,32) - uint32 y1_26_32 = Crc32Tab::getYi_24_32(zlist[1], zlist[0]) & MASK_26_32; + std::uint32_t y1_26_32 = Crc32Tab::getYi_24_32(zlist[1], zlist[0]) & MASK_26_32; if (((ylist[3] - 1) * MultTab::MULTINV - lsb(x) - 1) * MultTab::MULTINV - y1_26_32 > MAXDIFF_0_26) return; // decipher and filter by comparing with remaining contiguous plaintext forward Keys keysForward(xlist[7], ylist[7], zlist[7]); keysForward.update(data.plaintext[index + 7]); - for (bytevec::const_iterator p = data.plaintext.begin() + index + 8, - c = data.ciphertext.begin() + data.offset + index + 8; + for (auto p = data.plaintext.begin() + index + 8, c = data.ciphertext.begin() + data.offset + index + 8; p != data.plaintext.end(); ++p, ++c) { if ((*c ^ keysForward.getK()) != *p) @@ -130,8 +129,8 @@ void Attack::testXlist() // and also backward Keys keysBackward(x, ylist[3], zlist[3]); - using rit = std::reverse_iterator; - for (rit p = rit(data.plaintext.begin() + index + 3), c = rit(data.ciphertext.begin() + data.offset + index + 3); + for (auto p = std::reverse_iterator{data.plaintext.begin() + index + 3}, + c = std::reverse_iterator{data.ciphertext.begin() + data.offset + index + 3}; p != data.plaintext.rend(); ++p, ++c) { keysBackward.updateBackward(*c); @@ -142,23 +141,23 @@ void Attack::testXlist() std::size_t indexBackward = data.offset; // continue filtering with extra known plaintext - for (const std::pair& extra : data.extraPlaintext) + for (const auto& [extraIndex, extraByte] : data.extraPlaintext) { - byte p; - if (extra.first < indexBackward) + std::uint8_t p; + if (extraIndex < indexBackward) { - keysBackward.updateBackward(data.ciphertext, indexBackward, extra.first); - indexBackward = extra.first; + keysBackward.updateBackward(data.ciphertext, indexBackward, extraIndex); + indexBackward = extraIndex; p = data.ciphertext[indexBackward] ^ keysBackward.getK(); } else { - keysForward.update(data.ciphertext, indexForward, extra.first); - indexForward = extra.first; + keysForward.update(data.ciphertext, indexForward, extraIndex); + indexForward = extraIndex; p = data.ciphertext[indexForward] ^ keysForward.getK(); } - if (p != extra.second) + if (p != extraByte) return; } @@ -178,11 +177,11 @@ void Attack::testXlist() progress.state = Progress::State::EarlyExit; } -std::vector attack(const Data& data, const u32vec& zi_2_32_vector, int& start, std::size_t index, int jobs, - const bool exhaustive, Progress& progress) +std::vector attack(const Data& data, const std::vector& zi_2_32_vector, int& start, + std::size_t index, int jobs, const bool exhaustive, Progress& progress) { - const uint32* candidates = zi_2_32_vector.data(); - const auto size = static_cast(zi_2_32_vector.size()); + const std::uint32_t* candidates = zi_2_32_vector.data(); + const auto size = static_cast(zi_2_32_vector.size()); std::vector solutions; std::mutex solutionsMutex; diff --git a/src/Crc32Tab.cpp b/src/Crc32Tab.cpp index dc811f0..b62cfe4 100644 --- a/src/Crc32Tab.cpp +++ b/src/Crc32Tab.cpp @@ -6,7 +6,7 @@ Crc32Tab::Crc32Tab() { for (int b = 0; b < 256; b++) { - uint32 crc = b; + std::uint32_t crc = b; // compute CRC32 from the original definition for (int i = 0; i < 8; i++) if (crc & 1) diff --git a/src/Data.cpp b/src/Data.cpp index 7575a49..a2664c5 100644 --- a/src/Data.cpp +++ b/src/Data.cpp @@ -21,7 +21,7 @@ struct Range return size() < other.size(); } - std::vector>::iterator begin, end; + std::vector>::iterator begin, end; }; } // namespace @@ -31,7 +31,8 @@ Data::Error::Error(const std::string& description) { } -Data::Data(bytevec ciphertextArg, bytevec plaintextArg, int offsetArg, const std::map& extraPlaintextArg) +Data::Data(std::vector ciphertextArg, std::vector plaintextArg, int offsetArg, + const std::map& extraPlaintextArg) : ciphertext(std::move(ciphertextArg)) , plaintext(std::move(plaintextArg)) { @@ -60,8 +61,9 @@ Data::Data(bytevec ciphertextArg, bytevec plaintextArg, int offsetArg, const std offset = ENCRYPTION_HEADER_SIZE + offsetArg; std::transform(extraPlaintextArg.begin(), extraPlaintextArg.end(), std::back_inserter(extraPlaintext), - [](const std::pair& extra) - { return std::make_pair(ENCRYPTION_HEADER_SIZE + extra.first, extra.second); }); + [](const std::pair& extra) { + return std::pair{ENCRYPTION_HEADER_SIZE + extra.first, extra.second}; + }); // merge contiguous plaintext with adjacent extra plaintext { @@ -70,12 +72,14 @@ Data::Data(bytevec ciphertextArg, bytevec plaintextArg, int offsetArg, const std // - [before, after) overlapping contiguous plaintext // - [after, extraPlaintext.end()) after contiguous plaintext - auto before = std::lower_bound(extraPlaintext.begin(), extraPlaintext.end(), std::make_pair(offset, byte())); - auto after = std::lower_bound(before, extraPlaintext.end(), std::make_pair(offset + plaintext.size(), byte())); + auto before = std::lower_bound(extraPlaintext.begin(), extraPlaintext.end(), std::pair{offset, std::uint8_t{}}); + auto after = + std::lower_bound(before, extraPlaintext.end(), std::pair{offset + plaintext.size(), std::uint8_t{}}); // overwrite overlapping plaintext std::for_each(before, after, - [this](const std::pair& e) { plaintext[e.first - offset] = e.second; }); + [this](const std::pair& e) + { plaintext[e.first - offset] = e.second; }); // merge contiguous plaintext with extra plaintext immediately before while (before != extraPlaintext.begin() && (before - 1)->first == offset - 1) @@ -122,7 +126,7 @@ Data::Data(bytevec ciphertextArg, bytevec plaintextArg, int offsetArg, const std // rotate extra plaintext so that it will be sorted at the end of this scope { auto before = - std::lower_bound(extraPlaintext.begin(), extraPlaintext.end(), std::make_pair(offset, byte())); + std::lower_bound(extraPlaintext.begin(), extraPlaintext.end(), std::pair{offset, std::uint8_t{}}); if (offset < rangeOffset) range = {before, std::rotate(before, range.begin, range.end)}; else @@ -150,16 +154,17 @@ Data::Data(bytevec ciphertextArg, bytevec plaintextArg, int offsetArg, const std // reorder remaining extra plaintext for filtering { - auto before = std::lower_bound(extraPlaintext.begin(), extraPlaintext.end(), std::make_pair(offset, byte())); + auto before = std::lower_bound(extraPlaintext.begin(), extraPlaintext.end(), std::pair{offset, std::uint8_t{}}); std::reverse(extraPlaintext.begin(), before); - std::inplace_merge(extraPlaintext.begin(), before, extraPlaintext.end(), - [this](const std::pair& a, const std::pair& b) { - return absdiff(a.first, offset + Attack::CONTIGUOUS_SIZE) < - absdiff(b.first, offset + Attack::CONTIGUOUS_SIZE); - }); + std::inplace_merge( + extraPlaintext.begin(), before, extraPlaintext.end(), + [this](const std::pair& a, const std::pair& b) { + return absdiff(a.first, offset + Attack::CONTIGUOUS_SIZE) < + absdiff(b.first, offset + Attack::CONTIGUOUS_SIZE); + }); } // compute keystream std::transform(plaintext.begin(), plaintext.end(), ciphertext.begin() + offset, std::back_inserter(keystream), - std::bit_xor()); + std::bit_xor()); } diff --git a/src/Keys.cpp b/src/Keys.cpp index c65c15c..ef310d5 100644 --- a/src/Keys.cpp +++ b/src/Keys.cpp @@ -1,6 +1,6 @@ #include "Keys.hpp" -Keys::Keys(uint32 x, uint32 y, uint32 z) +Keys::Keys(std::uint32_t x, std::uint32_t y, std::uint32_t z) : x(x) , y(y) , z(z) @@ -14,16 +14,15 @@ Keys::Keys(const std::string& password) update(p); } -void Keys::update(const bytevec& ciphertext, std::size_t current, std::size_t target) +void Keys::update(const std::vector& ciphertext, std::size_t current, std::size_t target) { - for (bytevec::const_iterator i = ciphertext.begin() + current; i != ciphertext.begin() + target; ++i) + for (auto i = ciphertext.begin() + current; i != ciphertext.begin() + target; ++i) update(*i ^ getK()); } -void Keys::updateBackward(const bytevec& ciphertext, std::size_t current, std::size_t target) +void Keys::updateBackward(const std::vector& ciphertext, std::size_t current, std::size_t target) { - using rit = std::reverse_iterator; - - for (rit i = rit(ciphertext.begin() + current); i != rit(ciphertext.begin() + target); ++i) + for (auto i = std::reverse_iterator{ciphertext.begin() + current}; + i != std::reverse_iterator{ciphertext.begin() + target}; ++i) updateBackward(*i); } diff --git a/src/KeystreamTab.cpp b/src/KeystreamTab.cpp index 0efe078..95f86df 100644 --- a/src/KeystreamTab.cpp +++ b/src/KeystreamTab.cpp @@ -4,9 +4,9 @@ const KeystreamTab KeystreamTab::instance; KeystreamTab::KeystreamTab() { - for (uint32 z_2_16 = 0; z_2_16 < 1 << 16; z_2_16 += 4) + for (std::uint32_t z_2_16 = 0; z_2_16 < 1 << 16; z_2_16 += 4) { - byte k = lsb((z_2_16 | 2) * (z_2_16 | 3) >> 8); + std::uint8_t k = lsb((z_2_16 | 2) * (z_2_16 | 3) >> 8); keystreamtab[z_2_16 >> 2] = k; keystreaminvfiltertab[k][z_2_16 >> 10].push_back(z_2_16); keystreaminvexists[k].set(z_2_16 >> 10); diff --git a/src/MultTab.cpp b/src/MultTab.cpp index 0f6d8f6..78abaaa 100644 --- a/src/MultTab.cpp +++ b/src/MultTab.cpp @@ -4,8 +4,8 @@ const MultTab MultTab::instance; MultTab::MultTab() { - uint32 prod = 0; // x * MULT - uint32 prodinv = 0; // x * MULT^-1 + std::uint32_t prod = 0; // x * MULT + std::uint32_t prodinv = 0; // x * MULT^-1 for (int x = 0; x < 256; x++, prod += MULT, prodinv += MULTINV) { multtab[x] = prod; diff --git a/src/Zip.cpp b/src/Zip.cpp index 0aa6fc7..f4f635c 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -40,7 +40,7 @@ std::ostream& write(std::ostream& os, const T& x) return os; } -enum class Signature : uint32 +enum class Signature : std::uint32_t { LOCAL_FILE_HEADER = 0x04034b50, CENTRAL_DIRECTORY_HEADER = 0x02014b50, @@ -51,35 +51,35 @@ enum class Signature : uint32 bool checkSignature(std::istream& is, const Signature& signature) { - uint32 sig; - return read(is, sig) && sig == static_cast(signature); + std::uint32_t sig; + return read(is, sig) && sig == static_cast(signature); } -uint64 findCentralDirectoryOffset(std::istream& is) +std::uint64_t findCentralDirectoryOffset(std::istream& is) { - uint64 centralDirectoryOffset; + std::uint64_t centralDirectoryOffset; // find end of central directory signature { - uint32 signature; - uint16 commentLength = 0; + std::uint32_t signature; + std::uint16_t commentLength = 0; do { is.seekg(-22 - commentLength, std::ios::end); - } while (read(is, signature) && signature != static_cast(Signature::EOCD) && + } while (read(is, signature) && signature != static_cast(Signature::EOCD) && commentLength++ < MASK_0_16); - if (!is || signature != static_cast(Signature::EOCD)) + if (!is || signature != static_cast(Signature::EOCD)) throw Zip::Error("could not find end of central directory signature"); } // read end of central directory record { - uint16 disk; + std::uint16_t disk; read(is, disk); is.seekg(10, std::ios::cur); - read(is, centralDirectoryOffset); + read(is, centralDirectoryOffset); if (!is) throw Zip::Error("could not read end of central directory record"); @@ -91,7 +91,7 @@ uint64 findCentralDirectoryOffset(std::istream& is) is.seekg(-40, std::ios::cur); if (checkSignature(is, Signature::ZIP64_EOCD_LOCATOR)) { - uint64 zip64EndOfCentralDirectoryOffset; + std::uint64_t zip64EndOfCentralDirectoryOffset; is.seekg(4, std::ios::cur); read(is, zip64EndOfCentralDirectoryOffset); @@ -103,7 +103,7 @@ uint64 findCentralDirectoryOffset(std::istream& is) is.seekg(zip64EndOfCentralDirectoryOffset, std::ios::beg); if (checkSignature(is, Signature::ZIP64_EOCD)) { - uint16 versionNeededToExtract; + std::uint16_t versionNeededToExtract; is.seekg(10, std::ios::cur); read(is, versionNeededToExtract); @@ -141,14 +141,14 @@ Zip::Iterator& Zip::Iterator::operator++() if (!checkSignature(*m_is, Signature::CENTRAL_DIRECTORY_HEADER)) return *this = Iterator{}; - uint16 flags; - uint16 method; - uint16 lastModTime; - uint16 lastModDate; + std::uint16_t flags; + std::uint16_t method; + std::uint16_t lastModTime; + std::uint16_t lastModDate; - uint16 filenameLength; - uint16 extraFieldLength; - uint16 fileCommentLength; + std::uint16_t filenameLength; + std::uint16_t extraFieldLength; + std::uint16_t fileCommentLength; m_is->seekg(4, std::ios::cur); read(*m_is, flags); @@ -156,13 +156,13 @@ Zip::Iterator& Zip::Iterator::operator++() read(*m_is, lastModTime); read(*m_is, lastModDate); read(*m_is, m_entry->crc32); - read(*m_is, m_entry->packedSize); - read(*m_is, m_entry->uncompressedSize); + read(*m_is, m_entry->packedSize); + read(*m_is, m_entry->uncompressedSize); read(*m_is, filenameLength); read(*m_is, extraFieldLength); read(*m_is, fileCommentLength); m_is->seekg(8, std::ios::cur); - read(*m_is, m_entry->offset); + read(*m_is, m_entry->offset); read(*m_is, m_entry->name, filenameLength); m_entry->encryption = flags & 1 @@ -171,13 +171,13 @@ Zip::Iterator& Zip::Iterator::operator++() m_entry->compression = static_cast(method); - m_entry->checkByte = (flags >> 3) & 1 ? static_cast(lastModTime >> 8) : msb(m_entry->crc32); + m_entry->checkByte = (flags >> 3) & 1 ? static_cast(lastModTime >> 8) : msb(m_entry->crc32); for (int remaining = extraFieldLength; remaining > 0;) { // read extra field header - uint16 id; - uint16 size; + std::uint16_t id; + std::uint16_t size; read(*m_is, id); read(*m_is, size); remaining -= 4 + size; @@ -205,12 +205,12 @@ Zip::Iterator& Zip::Iterator::operator++() case 0x7075: // Info-ZIP Unicode Path if (5 <= size) { - uint32 nameCrc32 = MASK_0_32; - for (byte b : m_entry->name) + std::uint32_t nameCrc32 = MASK_0_32; + for (std::uint8_t b : m_entry->name) nameCrc32 = Crc32Tab::crc32(nameCrc32, b); nameCrc32 ^= MASK_0_32; - uint32 expectedNameCrc32; + std::uint32_t expectedNameCrc32; m_is->seekg(1, std::ios::cur); read(*m_is, expectedNameCrc32); size -= 5; @@ -226,7 +226,7 @@ Zip::Iterator& Zip::Iterator::operator++() case 0x9901: // AE-x encryption structure if (7 <= size) { - uint16 method; + std::uint16_t method; m_is->seekg(5, std::ios::cur); read(*m_is, method); size -= 7; @@ -314,7 +314,7 @@ std::istream& Zip::seek(const Entry& entry) const throw Error("could not find local file header"); // skip local file header - uint16 nameSize, extraSize; + std::uint16_t nameSize, extraSize; m_is.seekg(22, std::ios::cur); read(m_is, nameSize); read(m_is, extraSize); @@ -323,23 +323,23 @@ std::istream& Zip::seek(const Entry& entry) const return m_is; } -bytevec Zip::load(const Entry& entry, std::size_t count) const +std::vector Zip::load(const Entry& entry, std::size_t count) const { - return loadStream(seek(entry), std::min(entry.packedSize, static_cast(count))); + return loadStream(seek(entry), std::min(entry.packedSize, static_cast(count))); } void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, Progress& progress) const { // Store encrypted entries local file header offset and packed size. // Use std::map to sort them by local file header offset. - std::map packedSizeByLocalOffset; + std::map packedSizeByLocalOffset; for (const auto& entry : *this) if (entry.encryption == Encryption::Traditional) packedSizeByLocalOffset.insert({entry.offset, entry.packedSize}); // Rewind input stream and iterate on encrypted entries to change the keys, copy the rest. m_is.seekg(0, std::ios::beg); - uint64 currentOffset = 0; + std::uint64_t currentOffset = 0; progress.done = 0; progress.total = packedSizeByLocalOffset.size(); @@ -356,12 +356,12 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, if (!checkSignature(m_is, Signature::LOCAL_FILE_HEADER)) throw Error("could not find local file header"); - write(os, static_cast(Signature::LOCAL_FILE_HEADER)); + write(os, static_cast(Signature::LOCAL_FILE_HEADER)); std::copy_n(std::istreambuf_iterator(m_is), 22, std::ostreambuf_iterator(os)); m_is.get(); - uint16 filenameLength, extraSize; + std::uint16_t filenameLength, extraSize; read(m_is, filenameLength); read(m_is, extraSize); write(os, filenameLength); @@ -380,8 +380,8 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, std::generate_n(std::ostreambuf_iterator(os), packedSize, [&in, &decrypt, &encrypt]() -> char { - byte p = *in++ ^ decrypt.getK(); - byte c = p ^ encrypt.getK(); + std::uint8_t p = *in++ ^ decrypt.getK(); + std::uint8_t c = p ^ encrypt.getK(); decrypt.update(p); encrypt.update(p); return c; diff --git a/src/Zreduction.cpp b/src/Zreduction.cpp index cee857e..abdcfcd 100644 --- a/src/Zreduction.cpp +++ b/src/Zreduction.cpp @@ -7,13 +7,13 @@ #include #include -Zreduction::Zreduction(const bytevec& keystream) +Zreduction::Zreduction(const std::vector& keystream) : keystream(keystream) { index = keystream.size() - 1; zi_vector.reserve(1 << 22); - for (uint32 zi_10_32_shifted = 0; zi_10_32_shifted < 1 << 22; zi_10_32_shifted++) + for (std::uint32_t zi_10_32_shifted = 0; zi_10_32_shifted < 1 << 22; zi_10_32_shifted++) if (KeystreamTab::hasZi_2_16(keystream[index], zi_10_32_shifted << 10)) zi_vector.push_back(zi_10_32_shifted << 10); } @@ -21,15 +21,15 @@ Zreduction::Zreduction(const bytevec& keystream) void Zreduction::reduce(Progress& progress) { // variables to keep track of the smallest Zi[2,32) vector - bool tracking = false; - u32vec bestCopy; - std::size_t bestIndex = index, bestSize = TRACK_SIZE; + bool tracking = false; + std::vector bestCopy; + std::size_t bestIndex = index, bestSize = TRACK_SIZE; // variables to wait for a limited number of steps when a small enough vector is found bool waiting = false; std::size_t wait = 0; - u32vec zim1_10_32_vector; + std::vector zim1_10_32_vector; zim1_10_32_vector.reserve(1 << 22); std::bitset<1 << 22> zim1_10_32_set; @@ -43,11 +43,11 @@ void Zreduction::reduce(Progress& progress) std::size_t number_of_zim1_2_32 = 0; // generate the Z{i-1}[10,32) values - for (uint32 zi_10_32 : zi_vector) - for (uint32 zi_2_16 : KeystreamTab::getZi_2_16_vector(keystream[i], zi_10_32)) + for (std::uint32_t zi_10_32 : zi_vector) + for (std::uint32_t zi_2_16 : KeystreamTab::getZi_2_16_vector(keystream[i], zi_10_32)) { // get Z{i-1}[10,32) from CRC32^-1 - uint32 zim1_10_32 = Crc32Tab::getZim1_10_32(zi_10_32 | zi_2_16); + std::uint32_t zim1_10_32 = Crc32Tab::getZim1_10_32(zi_10_32 | zi_2_16); // collect without duplicates only those that are compatible with keystream{i-1} if (!zim1_10_32_set[zim1_10_32 >> 10] && KeystreamTab::hasZi_2_16(keystream[i - 1], zim1_10_32)) { @@ -106,14 +106,15 @@ void Zreduction::generate() std::size_t number_of_zi_10_32 = zi_vector.size(); for (std::size_t i = 0; i < number_of_zi_10_32; i++) { - const u32vec& zi_2_16_vector = KeystreamTab::getZi_2_16_vector(keystream[index], zi_vector[i]); + const std::vector& zi_2_16_vector = + KeystreamTab::getZi_2_16_vector(keystream[index], zi_vector[i]); for (std::size_t j = 1; j < zi_2_16_vector.size(); j++) zi_vector.push_back(zi_vector[i] | zi_2_16_vector[j]); zi_vector[i] |= zi_2_16_vector[0]; } } -const u32vec& Zreduction::getCandidates() const +const std::vector& Zreduction::getCandidates() const { return zi_vector; } diff --git a/src/file.cpp b/src/file.cpp index 96e12b6..8c6944d 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -13,9 +13,9 @@ std::ifstream openInput(const std::string& filename) throw FileError("could not open input file " + filename); } -bytevec loadStream(std::istream& is, std::size_t size) +std::vector loadStream(std::istream& is, std::size_t size) { - bytevec content; + std::vector content; std::istreambuf_iterator it(is); for (std::size_t i = 0; i < size && it != std::istreambuf_iterator(); i++, ++it) content.push_back(*it); @@ -23,7 +23,7 @@ bytevec loadStream(std::istream& is, std::size_t size) return content; } -bytevec loadFile(const std::string& filename, std::size_t size) +std::vector loadFile(const std::string& filename, std::size_t size) { std::ifstream is = openInput(filename); return loadStream(is, size); diff --git a/src/main.cpp b/src/main.cpp index d1ebff4..08e5c6d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -306,7 +306,7 @@ try const auto fillBefore = std::cout.fill('0'); std::cout << "You may resume the password recovery with the option: --continue-recovery "; - for (byte c : restart) + for (std::uint8_t c : restart) std::cout << std::setw(2) << static_cast(c); std::cout << std::endl; @@ -331,7 +331,7 @@ try for (const auto& password : passwords) { std::cout << "as bytes: "; - for (byte c : password) + for (std::uint8_t c : password) std::cout << std::setw(2) << static_cast(c) << ' '; std::cout << std::endl; std::cout << "as text: " << password << std::endl; @@ -449,7 +449,7 @@ void decipher(std::istream& is, std::size_t size, std::size_t discard, std::ostr for (std::ostreambuf_iterator plain(os); i < size && cipher != std::istreambuf_iterator(); i++, ++cipher, ++plain) { - byte p = *cipher ^ keys.getK(); + std::uint8_t p = *cipher ^ keys.getK(); keys.update(p); *plain = p; } diff --git a/src/password.cpp b/src/password.cpp index 54236a4..37d08a0 100644 --- a/src/password.cpp +++ b/src/password.cpp @@ -8,7 +8,7 @@ #include #include -Recovery::Recovery(const Keys& keys, const bytevec& charset, std::vector& solutions, +Recovery::Recovery(const Keys& keys, const std::vector& charset, std::vector& solutions, std::mutex& solutionsMutex, bool exhaustive, Progress& progress) : charset(charset) , solutions(solutions) @@ -29,13 +29,13 @@ Recovery::Recovery(const Keys& keys, const bytevec& charset, std::vector(c); os << ')' << std::endl; @@ -256,7 +256,7 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c { for (auto i = nextCandidateIndex++; i < charsetSize; i = nextCandidateIndex++) { - byte pm4 = worker.charset[i]; + std::uint8_t pm4 = worker.charset[i]; Keys init = initial; init.update(pm4); @@ -315,8 +315,8 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c { for (auto i = nextCandidateIndex++; i < charsetSize * charsetSize; i = nextCandidateIndex++) { - byte pm4 = worker.charset[i / charsetSize]; - byte pm3 = worker.charset[i % charsetSize]; + std::uint8_t pm4 = worker.charset[i / charsetSize]; + std::uint8_t pm3 = worker.charset[i % charsetSize]; Keys init = initial; init.update(pm4); @@ -361,7 +361,7 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c for (int i = index_start; i < charsetSize; i++) { - byte pi = worker.charset[i]; + std::uint8_t pi = worker.charset[i]; Keys init = initial; init.update(pi); @@ -386,9 +386,9 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c } // namespace -std::vector recoverPassword(const Keys& keys, const bytevec& charset, std::size_t minLength, - std::size_t maxLength, std::string& start, int jobs, bool exhaustive, - Progress& progress) +std::vector recoverPassword(const Keys& keys, const std::vector& charset, + std::size_t minLength, std::size_t maxLength, std::string& start, int jobs, + bool exhaustive, Progress& progress) { std::vector solutions; std::mutex solutionsMutex; From 3e675092565638eeb409e2c3e7f336b2d4bc67ad Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 14:58:49 +0100 Subject: [PATCH 02/19] Replace some enums by constexpr values --- include/Attack.hpp | 13 +++++-------- include/Crc32Tab.hpp | 6 ------ include/Data.hpp | 6 ++---- include/MultTab.hpp | 11 ++++++----- include/Zreduction.hpp | 6 ------ src/Crc32Tab.cpp | 3 +++ src/Zreduction.cpp | 8 +++++--- 7 files changed, 21 insertions(+), 32 deletions(-) diff --git a/include/Attack.hpp b/include/Attack.hpp index 18b4149..7146884 100644 --- a/include/Attack.hpp +++ b/include/Attack.hpp @@ -28,14 +28,11 @@ class Attack /// Carry out the attack for the given Z[2,32) value 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, - - /// Total number of known plaintext bytes required by the attack - ATTACK_SIZE = 12 - }; + /// Number of contiguous known plaintext bytes required by the attack + static constexpr std::size_t CONTIGUOUS_SIZE = 8; + + /// Total number of known plaintext bytes required by the attack + static constexpr std::size_t ATTACK_SIZE = 12; private: // iterate recursively over Z-lists diff --git a/include/Crc32Tab.hpp b/include/Crc32Tab.hpp index 5366a18..0492b87 100644 --- a/include/Crc32Tab.hpp +++ b/include/Crc32Tab.hpp @@ -39,12 +39,6 @@ class Crc32Tab std::array crctab; std::array crcinvtab; - // CRC32 polynomial representation - enum : std::uint32_t - { - CRCPOL = 0xedb88320 - }; - static const Crc32Tab instance; }; diff --git a/include/Data.hpp b/include/Data.hpp index ee76f83..c633ac1 100644 --- a/include/Data.hpp +++ b/include/Data.hpp @@ -8,10 +8,8 @@ /// 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 ENCRYPTION_HEADER_SIZE = 12; /// Exception thrown if data cannot be used to carry out an attack class Error : public BaseError diff --git a/include/MultTab.hpp b/include/MultTab.hpp index 819b112..2d060b1 100644 --- a/include/MultTab.hpp +++ b/include/MultTab.hpp @@ -33,11 +33,12 @@ class MultTab return instance.msbprodfiber3[msbprodinv]; } - enum : std::uint32_t - { - MULT = 0x08088405, - MULTINV = 0xd94fa8cd - }; + /// Multiplicative constant used in traditional PKWARE encryption + static constexpr std::uint32_t MULT = 0x08088405; + + /// Multiplicative inverse of MULT modulo 2^32 + static constexpr std::uint32_t MULTINV = 0xd94fa8cd; + static_assert(MULT * MULTINV == 1); private: // initialize lookup tables diff --git a/include/Zreduction.hpp b/include/Zreduction.hpp index 8198cc4..f484210 100644 --- a/include/Zreduction.hpp +++ b/include/Zreduction.hpp @@ -24,12 +24,6 @@ class Zreduction std::size_t getIndex() const; private: - enum : std::size_t - { - WAIT_SIZE = 1 << 8, - TRACK_SIZE = 1 << 16 - }; - const std::vector& keystream; // After constructor or reduce(), contains Z[10,32) values. // After generate(), contains Zi[2,32) values. diff --git a/src/Crc32Tab.cpp b/src/Crc32Tab.cpp index b62cfe4..56203f5 100644 --- a/src/Crc32Tab.cpp +++ b/src/Crc32Tab.cpp @@ -4,6 +4,9 @@ const Crc32Tab Crc32Tab::instance; Crc32Tab::Crc32Tab() { + // CRC32 polynomial representation + constexpr std::uint32_t CRCPOL = 0xedb88320; + for (int b = 0; b < 256; b++) { std::uint32_t crc = b; diff --git a/src/Zreduction.cpp b/src/Zreduction.cpp index abdcfcd..2021255 100644 --- a/src/Zreduction.cpp +++ b/src/Zreduction.cpp @@ -21,13 +21,15 @@ Zreduction::Zreduction(const std::vector& keystream) void Zreduction::reduce(Progress& progress) { // variables to keep track of the smallest Zi[2,32) vector - bool tracking = false; + constexpr std::size_t TRACK_SIZE = 1 << 16; + bool tracking = false; std::vector bestCopy; std::size_t bestIndex = index, bestSize = TRACK_SIZE; // variables to wait for a limited number of steps when a small enough vector is found - bool waiting = false; - std::size_t wait = 0; + constexpr std::size_t WAIT_SIZE = 1 << 8; + bool waiting = false; + std::size_t wait = 0; std::vector zim1_10_32_vector; zim1_10_32_vector.reserve(1 << 22); From c554376d1a3e5512bb690a19f66ab60a8eed8c71 Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 14:59:28 +0100 Subject: [PATCH 03/19] Replace remaining unscoped enums by template constexprs --- include/Crc32Tab.hpp | 2 +- include/KeystreamTab.hpp | 6 +++--- include/types.hpp | 23 +++++------------------ src/Attack.cpp | 18 +++++++++--------- src/Zip.cpp | 12 ++++++------ src/password.cpp | 4 ++-- 6 files changed, 26 insertions(+), 39 deletions(-) diff --git a/include/Crc32Tab.hpp b/include/Crc32Tab.hpp index 0492b87..2372312 100644 --- a/include/Crc32Tab.hpp +++ b/include/Crc32Tab.hpp @@ -28,7 +28,7 @@ class Crc32Tab /// \return Z{i-1}[10,32) from Zi[2,32) using CRC32^-1 static inline std::uint32_t getZim1_10_32(std::uint32_t zi_2_32) { - 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: diff --git a/include/KeystreamTab.hpp b/include/KeystreamTab.hpp index b55692f..f660bf8 100644 --- a/include/KeystreamTab.hpp +++ b/include/KeystreamTab.hpp @@ -13,7 +13,7 @@ class KeystreamTab /// \note Only Zi[2,16) is used static inline std::uint8_t getByte(std::uint32_t zi) { - 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 @@ -21,14 +21,14 @@ class KeystreamTab /// \note the vector contains one element on average static inline const std::vector& getZi_2_16_vector(std::uint8_t ki, std::uint32_t zi_10_16) { - 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(std::uint8_t ki, std::uint32_t zi_10_16) { - return instance.keystreaminvexists[ki][(zi_10_16 & MASK_0_16) >> 10]; + return instance.keystreaminvexists[ki][(zi_10_16 & mask<0, 16>) >> 10]; } private: diff --git a/include/types.hpp b/include/types.hpp index 82ef438..fbfb823 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -40,19 +40,9 @@ inline std::size_t absdiff(std::size_t x, std::size_t y) // constants -/// Useful constants for masking -enum : std::uint32_t -{ - MASK_0_16 = 0x0000ffff, - MASK_0_24 = 0x00ffffff, - MASK_0_26 = 0x03ffffff, - MASK_0_32 = 0xffffffff, - MASK_26_32 = 0xfc000000, - MASK_24_32 = 0xff000000, - MASK_10_32 = 0xfffffc00, - MASK_8_32 = 0xffffff00, - MASK_2_32 = 0xfffffffc -}; +/// Constant value for bit masking +template +constexpr std::uint32_t mask = ~0u << begin & ~0u >> (32 - end); /// \brief Maximum difference between 32-bits integers A and B[x,32) /// knowing that A = B + b and b is a byte. @@ -63,10 +53,7 @@ enum : std::uint32_t /// A = B[0,x) + B[x,32) + b /// A - B[x,32) = B[0,x) + b /// A - B[x,32) <= 0xffffffff[0,x) + 0xff -enum : std::uint32_t -{ - MAXDIFF_0_24 = MASK_0_24 + 0xff, - MAXDIFF_0_26 = MASK_0_26 + 0xff -}; +template +constexpr std::uint32_t maxdiff = mask<0, x> + 0xff; #endif // BKCRACK_TYPES_HPP diff --git a/src/Attack.cpp b/src/Attack.cpp index 38af82b..5a1154e 100644 --- a/src/Attack.cpp +++ b/src/Attack.cpp @@ -40,7 +40,7 @@ void Attack::exploreZlists(int i) zlist[i - 1] = zim1_10_32 | zim1_2_16; // find Zi[0,2) from CRC32^1 - zlist[i] &= MASK_2_32; // discard 2 least significant bits + zlist[i] &= mask<2, 32>; // discard 2 least significant bits zlist[i] |= (Crc32Tab::crc32inv(zlist[i], 0) ^ zlist[i - 1]) >> 8; // get Y{i+1}[24,32) @@ -58,9 +58,9 @@ void Attack::exploreZlists(int i) // get possible Y7[0,8) values for (std::uint8_t y7_0_8 : MultTab::getMsbProdFiber3(msb(ylist[6]) - msb(prod))) // filter Y7[0,8) using Y6[24,32) - if (prod + MultTab::getMultinv(y7_0_8) - (ylist[6] & MASK_24_32) <= MAXDIFF_0_24) + if (prod + MultTab::getMultinv(y7_0_8) - (ylist[6] & mask<24, 32>) <= maxdiff<24>) { - ylist[7] = y7_0_8 | y7_8_24 | (ylist[7] & MASK_24_32); + ylist[7] = y7_0_8 | y7_8_24 | (ylist[7] & mask<24, 32>); exploreYlists(7); } } @@ -74,13 +74,13 @@ void Attack::exploreYlists(int i) std::uint32_t ffy = (fy - 1) * MultTab::MULTINV; // get possible LSB(Xi) - for (std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (ylist[i - 2] & MASK_24_32)))) + for (std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (ylist[i - 2] & mask<24, 32>)))) { // compute corresponding Y{i-1} std::uint32_t yim1 = fy - xi_0_8; // filter values with Y{i-2}[24,32) - if (ffy - MultTab::getMultinv(xi_0_8) - (ylist[i - 2] & MASK_24_32) <= MAXDIFF_0_24 && + if (ffy - MultTab::getMultinv(xi_0_8) - (ylist[i - 2] & mask<24, 32>) <= maxdiff<24> && msb(yim1) == msb(ylist[i - 1])) { // add Y{i-1} to the Y-list @@ -101,8 +101,8 @@ void Attack::testXlist() { // compute X7 for (int i = 5; i <= 7; i++) - xlist[i] = (Crc32Tab::crc32(xlist[i - 1], data.plaintext[index + i - 1]) & MASK_8_32) // discard the LSB - | lsb(xlist[i]); // set the LSB + xlist[i] = (Crc32Tab::crc32(xlist[i - 1], data.plaintext[index + i - 1]) & mask<8, 32>) // discard the LSB + | lsb(xlist[i]); // set the LSB // compute X3 std::uint32_t x = xlist[7]; @@ -110,8 +110,8 @@ void Attack::testXlist() x = Crc32Tab::crc32inv(x, data.plaintext[index + i]); // check that X3 fits with Y1[26,32) - std::uint32_t y1_26_32 = Crc32Tab::getYi_24_32(zlist[1], zlist[0]) & MASK_26_32; - if (((ylist[3] - 1) * MultTab::MULTINV - lsb(x) - 1) * MultTab::MULTINV - y1_26_32 > MAXDIFF_0_26) + std::uint32_t y1_26_32 = Crc32Tab::getYi_24_32(zlist[1], zlist[0]) & mask<26, 32>; + if (((ylist[3] - 1) * MultTab::MULTINV - lsb(x) - 1) * MultTab::MULTINV - y1_26_32 > maxdiff<26>) return; // decipher and filter by comparing with remaining contiguous plaintext forward diff --git a/src/Zip.cpp b/src/Zip.cpp index f4f635c..29b1061 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -67,7 +67,7 @@ std::uint64_t findCentralDirectoryOffset(std::istream& is) { is.seekg(-22 - commentLength, std::ios::end); } while (read(is, signature) && signature != static_cast(Signature::EOCD) && - commentLength++ < MASK_0_16); + commentLength++ < mask<0, 16>); if (!is || signature != static_cast(Signature::EOCD)) throw Zip::Error("could not find end of central directory signature"); @@ -185,17 +185,17 @@ Zip::Iterator& Zip::Iterator::operator++() switch (id) { case 0x0001: // Zip64 extended information - if (8 <= size && m_entry->uncompressedSize == MASK_0_32) + if (8 <= size && m_entry->uncompressedSize == mask<0, 32>) { read(*m_is, m_entry->uncompressedSize); size -= 8; } - if (8 <= size && m_entry->packedSize == MASK_0_32) + if (8 <= size && m_entry->packedSize == mask<0, 32>) { read(*m_is, m_entry->packedSize); size -= 8; } - if (8 <= size && m_entry->offset == MASK_0_32) + if (8 <= size && m_entry->offset == mask<0, 32>) { read(*m_is, m_entry->offset); size -= 8; @@ -205,10 +205,10 @@ Zip::Iterator& Zip::Iterator::operator++() case 0x7075: // Info-ZIP Unicode Path if (5 <= size) { - std::uint32_t nameCrc32 = MASK_0_32; + std::uint32_t nameCrc32 = mask<0, 32>; for (std::uint8_t b : m_entry->name) nameCrc32 = Crc32Tab::crc32(nameCrc32, b); - nameCrc32 ^= MASK_0_32; + nameCrc32 ^= mask<0, 32>; std::uint32_t expectedNameCrc32; m_is->seekg(1, std::ios::cur); diff --git a/src/password.cpp b/src/password.cpp index 37d08a0..d15c8fe 100644 --- a/src/password.cpp +++ b/src/password.cpp @@ -148,13 +148,13 @@ void Recovery::recursion(int i) const std::uint32_t ffy = (fy - 1) * MultTab::MULTINV; // get possible LSB(Xi) - for (std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (y[i - 2] & MASK_24_32)))) + for (std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (y[i - 2] & mask<24, 32>)))) { // compute corresponding Y{i-1} const std::uint32_t yim1 = fy - xi_0_8; // filter values with Y{i-2}[24,32) - if (ffy - MultTab::getMultinv(xi_0_8) - (y[i - 2] & MASK_24_32) <= MAXDIFF_0_24 && + if (ffy - MultTab::getMultinv(xi_0_8) - (y[i - 2] & mask<24, 32>) <= maxdiff<24> && msb(yim1) == msb(y[i - 1])) { // add Y{i-1} to the Y-list From 1cd4e41d7092ee0f60f2eaa3a3acd89242100237 Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 14:59:49 +0100 Subject: [PATCH 04/19] Replace version defines by constexprs --- include/version.hpp.in | 4 ++-- src/main.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/version.hpp.in b/include/version.hpp.in index 27ea1f3..7a8063a 100644 --- a/include/version.hpp.in +++ b/include/version.hpp.in @@ -1,7 +1,7 @@ #ifndef BKCRACK_VERSION_HPP #define BKCRACK_VERSION_HPP -#define BKCRACK_VERSION "@bkcrack_VERSION@" -#define BKCRACK_VERSION_DATE "@bkcrack_VERSION_DATE@" +constexpr auto BKCRACK_VERSION = "@bkcrack_VERSION@"; +constexpr auto BKCRACK_VERSION_DATE = "@bkcrack_VERSION_DATE@"; #endif // BKCRACK_VERSION_HPP diff --git a/src/main.cpp b/src/main.cpp index 08e5c6d..e1efa0f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -109,7 +109,7 @@ try VirtualTerminalSupport vtSupport; // version information - std::cout << "bkcrack " BKCRACK_VERSION " - " BKCRACK_VERSION_DATE << std::endl; + std::cout << "bkcrack " << BKCRACK_VERSION << " - " << BKCRACK_VERSION_DATE << std::endl; const Arguments args(argc, argv); if (args.help) From 69e0428312ea656788b605407808d75f2ca09202 Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:00:12 +0100 Subject: [PATCH 05/19] Let lsb and msb functions be constexpr because they can! --- include/types.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/types.hpp b/include/types.hpp index fbfb823..b2a1314 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -21,13 +21,13 @@ class BaseError : public std::runtime_error // utility functions /// \return the least significant byte of x -inline std::uint8_t lsb(std::uint32_t x) +constexpr std::uint8_t lsb(std::uint32_t x) { return x; } /// \return the most significant byte of x -inline std::uint8_t msb(std::uint32_t x) +constexpr std::uint8_t msb(std::uint32_t x) { return x >> 24; } From 15037b99e4b1360f26fbd243175bf6d78e9bd136 Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:01:38 +0100 Subject: [PATCH 06/19] Avoid naming constants like macros --- include/Attack.hpp | 10 +++++----- include/Data.hpp | 2 +- include/Keys.hpp | 6 +++--- include/MultTab.hpp | 16 ++++++++-------- include/version.hpp.in | 4 ++-- src/Arguments.cpp | 8 ++++---- src/Attack.cpp | 12 ++++++------ src/Crc32Tab.cpp | 4 ++-- src/Data.cpp | 26 +++++++++++++------------- src/MultTab.cpp | 6 +++--- src/Zip.cpp | 26 +++++++++++++------------- src/Zreduction.cpp | 22 +++++++++++----------- src/main.cpp | 10 +++++----- src/password.cpp | 14 +++++++------- 14 files changed, 83 insertions(+), 83 deletions(-) diff --git a/include/Attack.hpp b/include/Attack.hpp index 7146884..0dcc2c1 100644 --- a/include/Attack.hpp +++ b/include/Attack.hpp @@ -29,10 +29,10 @@ class Attack void carryout(std::uint32_t z7_2_32); /// Number of contiguous known plaintext bytes required by the attack - static constexpr std::size_t CONTIGUOUS_SIZE = 8; + static constexpr std::size_t contiguousSize = 8; /// Total number of known plaintext bytes required by the attack - static constexpr std::size_t ATTACK_SIZE = 12; + static constexpr std::size_t attackSize = 12; private: // iterate recursively over Z-lists @@ -53,9 +53,9 @@ class Attack const bool exhaustive; Progress& progress; - std::array zlist; - std::array ylist; // the first two elements are not used - std::array xlist; // the first four elements are not used + std::array zlist; + std::array ylist; // the first two elements are not used + std::array xlist; // the first four elements are not used }; /// \brief Iterate on Zi[2,32) candidates to try and find complete internal keys diff --git a/include/Data.hpp b/include/Data.hpp index c633ac1..2c57ac8 100644 --- a/include/Data.hpp +++ b/include/Data.hpp @@ -9,7 +9,7 @@ struct Data { /// Size of the traditional PKWARE encryption header - static constexpr std::size_t ENCRYPTION_HEADER_SIZE = 12; + static constexpr std::size_t encryptionHeaderSize = 12; /// Exception thrown if data cannot be used to carry out an attack class Error : public BaseError diff --git a/include/Keys.hpp b/include/Keys.hpp index ea81ded..96491bf 100644 --- a/include/Keys.hpp +++ b/include/Keys.hpp @@ -19,7 +19,7 @@ class Keys inline 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)); } @@ -30,7 +30,7 @@ class Keys inline 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()); } @@ -38,7 +38,7 @@ class Keys inline 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); } diff --git a/include/MultTab.hpp b/include/MultTab.hpp index 2d060b1..e51ce6c 100644 --- a/include/MultTab.hpp +++ b/include/MultTab.hpp @@ -7,38 +7,38 @@ class MultTab { public: - /// \return MULT * x using a lookup table + /// \return mult * x using a lookup table static inline std::uint32_t getMult(std::uint8_t x) { return instance.multtab[x]; } - /// \return MULT^-1 * x using a lookup table + /// \return mult^-1 * x using a lookup table static inline std::uint32_t getMultinv(std::uint8_t x) { return instance.multinvtab[x]; } /// \return a vector of bytes x such that - /// msb(x*MULT^-1) is equal to msbprod or msbprod-1 + /// msb(x*mult^-1) is equal to msbprod or msbprod-1 static inline const std::vector& getMsbProdFiber2(std::uint8_t msbprodinv) { return instance.msbprodfiber2[msbprodinv]; } /// \return a vector of bytes x such that - /// msb(x*MULT^-1) is equal to msbprod, msbprod-1 or msbprod+1 + /// msb(x*mult^-1) is equal to msbprod, msbprod-1 or msbprod+1 static inline const std::vector& getMsbProdFiber3(std::uint8_t msbprodinv) { return instance.msbprodfiber3[msbprodinv]; } /// Multiplicative constant used in traditional PKWARE encryption - static constexpr std::uint32_t MULT = 0x08088405; + static constexpr std::uint32_t mult = 0x08088405; - /// Multiplicative inverse of MULT modulo 2^32 - static constexpr std::uint32_t MULTINV = 0xd94fa8cd; - static_assert(MULT * MULTINV == 1); + /// Multiplicative inverse of mult modulo 2^32 + static constexpr std::uint32_t multInv = 0xd94fa8cd; + static_assert(mult * multInv == 1); private: // initialize lookup tables diff --git a/include/version.hpp.in b/include/version.hpp.in index 7a8063a..50281c5 100644 --- a/include/version.hpp.in +++ b/include/version.hpp.in @@ -1,7 +1,7 @@ #ifndef BKCRACK_VERSION_HPP #define BKCRACK_VERSION_HPP -constexpr auto BKCRACK_VERSION = "@bkcrack_VERSION@"; -constexpr auto BKCRACK_VERSION_DATE = "@bkcrack_VERSION_DATE@"; +constexpr auto bkcrackVersion = "@bkcrack_VERSION@"; +constexpr auto bkcrackVersionDate = "@bkcrack_VERSION_DATE@"; #endif // BKCRACK_VERSION_HPP diff --git a/src/Arguments.cpp b/src/Arguments.cpp index d126127..d87b5e5 100644 --- a/src/Arguments.cpp +++ b/src/Arguments.cpp @@ -120,7 +120,7 @@ Arguments::Arguments(int argc, const char* argv[]) if (plainIndex && !plainArchive) throw Error("-P parameter is missing (required by --plain-index)"); - constexpr int minimumOffset = -static_cast(Data::ENCRYPTION_HEADER_SIZE); + constexpr int minimumOffset = -static_cast(Data::encryptionHeaderSize); if (offset < minimumOffset) throw Error("plaintext offset " + std::to_string(offset) + " is too small (minimum is " + std::to_string(minimumOffset) + ")"); @@ -160,11 +160,11 @@ Data Arguments::loadData() const plaintext = loadFile(*plainFile, plainFilePrefix); // load ciphertext needed by the attack - std::size_t needed = Data::ENCRYPTION_HEADER_SIZE; + std::size_t needed = Data::encryptionHeaderSize; if (!plaintext.empty()) - needed = std::max(needed, Data::ENCRYPTION_HEADER_SIZE + offset + plaintext.size()); + needed = std::max(needed, Data::encryptionHeaderSize + offset + plaintext.size()); if (!extraPlaintext.empty()) - needed = std::max(needed, Data::ENCRYPTION_HEADER_SIZE + extraPlaintext.rbegin()->first + 1); + needed = std::max(needed, Data::encryptionHeaderSize + extraPlaintext.rbegin()->first + 1); std::vector ciphertext; std::optional> extraPlaintextWithCheckByte; diff --git a/src/Attack.cpp b/src/Attack.cpp index 5a1154e..405025b 100644 --- a/src/Attack.cpp +++ b/src/Attack.cpp @@ -12,7 +12,7 @@ Attack::Attack(const Data& data, std::size_t index, std::vector& solutions, std::mutex& solutionsMutex, bool exhaustive, Progress& progress) : data(data) -, index(index + 1 - Attack::CONTIGUOUS_SIZE) +, index(index + 1 - Attack::contiguousSize) , solutions(solutions) , solutionsMutex(solutionsMutex) , exhaustive(exhaustive) @@ -53,8 +53,8 @@ void Attack::exploreZlists(int i) else // the Z-list is complete so iterate over possible Y values { // guess Y7[8,24) and keep prod == (Y7[8,32) - 1) * mult^-1 - for (std::uint32_t y7_8_24 = 0, prod = (MultTab::getMultinv(msb(ylist[7])) << 24) - MultTab::MULTINV; - y7_8_24 < 1 << 24; y7_8_24 += 1 << 8, prod += MultTab::MULTINV << 8) + for (std::uint32_t y7_8_24 = 0, prod = (MultTab::getMultinv(msb(ylist[7])) << 24) - MultTab::multInv; + y7_8_24 < 1 << 24; y7_8_24 += 1 << 8, prod += MultTab::multInv << 8) // get possible Y7[0,8) values for (std::uint8_t y7_0_8 : MultTab::getMsbProdFiber3(msb(ylist[6]) - msb(prod))) // filter Y7[0,8) using Y6[24,32) @@ -70,8 +70,8 @@ void Attack::exploreYlists(int i) { if (i != 3) // the Y-list is not complete so generate Y{i-1} values { - std::uint32_t fy = (ylist[i] - 1) * MultTab::MULTINV; - std::uint32_t ffy = (fy - 1) * MultTab::MULTINV; + std::uint32_t fy = (ylist[i] - 1) * MultTab::multInv; + std::uint32_t ffy = (fy - 1) * MultTab::multInv; // get possible LSB(Xi) for (std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (ylist[i - 2] & mask<24, 32>)))) @@ -111,7 +111,7 @@ void Attack::testXlist() // check that X3 fits with Y1[26,32) std::uint32_t y1_26_32 = Crc32Tab::getYi_24_32(zlist[1], zlist[0]) & mask<26, 32>; - if (((ylist[3] - 1) * MultTab::MULTINV - lsb(x) - 1) * MultTab::MULTINV - y1_26_32 > maxdiff<26>) + if (((ylist[3] - 1) * MultTab::multInv - lsb(x) - 1) * MultTab::multInv - y1_26_32 > maxdiff<26>) return; // decipher and filter by comparing with remaining contiguous plaintext forward diff --git a/src/Crc32Tab.cpp b/src/Crc32Tab.cpp index 56203f5..7bec4f1 100644 --- a/src/Crc32Tab.cpp +++ b/src/Crc32Tab.cpp @@ -5,7 +5,7 @@ const Crc32Tab Crc32Tab::instance; Crc32Tab::Crc32Tab() { // CRC32 polynomial representation - constexpr std::uint32_t CRCPOL = 0xedb88320; + constexpr std::uint32_t crcPolynom = 0xedb88320; for (int b = 0; b < 256; b++) { @@ -13,7 +13,7 @@ Crc32Tab::Crc32Tab() // compute CRC32 from the original definition for (int i = 0; i < 8; i++) if (crc & 1) - crc = crc >> 1 ^ CRCPOL; + crc = crc >> 1 ^ crcPolynom; else crc = crc >> 1; diff --git a/src/Data.cpp b/src/Data.cpp index a2664c5..5a71d73 100644 --- a/src/Data.cpp +++ b/src/Data.cpp @@ -37,32 +37,32 @@ Data::Data(std::vector ciphertextArg, std::vector pl , plaintext(std::move(plaintextArg)) { // validate lengths - if (ciphertext.size() < Attack::ATTACK_SIZE) - throw Error("ciphertext is too small for an attack (minimum length is " + std::to_string(Attack::ATTACK_SIZE) + + if (ciphertext.size() < Attack::attackSize) + throw Error("ciphertext is too small for an attack (minimum length is " + std::to_string(Attack::attackSize) + ")"); if (ciphertext.size() < plaintext.size()) throw Error("ciphertext is smaller than plaintext"); // validate offsets - constexpr int minimumOffset = -static_cast(ENCRYPTION_HEADER_SIZE); + constexpr int minimumOffset = -static_cast(encryptionHeaderSize); if (offsetArg < minimumOffset) throw Error("plaintext offset " + std::to_string(offsetArg) + " is too small (minimum is " + std::to_string(minimumOffset) + ")"); - if (ciphertext.size() < ENCRYPTION_HEADER_SIZE + offsetArg + plaintext.size()) + if (ciphertext.size() < encryptionHeaderSize + offsetArg + plaintext.size()) throw Error("plaintext offset " + std::to_string(offsetArg) + " is too large"); if (!extraPlaintextArg.empty() && extraPlaintextArg.begin()->first < minimumOffset) throw Error("extra plaintext offset " + std::to_string(extraPlaintextArg.begin()->first) + " is too small (minimum is " + std::to_string(minimumOffset) + ")"); - if (!extraPlaintextArg.empty() && ciphertext.size() <= ENCRYPTION_HEADER_SIZE + extraPlaintextArg.rbegin()->first) + if (!extraPlaintextArg.empty() && ciphertext.size() <= encryptionHeaderSize + extraPlaintextArg.rbegin()->first) throw Error("extra plaintext offset " + std::to_string(extraPlaintextArg.rbegin()->first) + " is too large"); // shift offsets to absolute values - offset = ENCRYPTION_HEADER_SIZE + offsetArg; + offset = encryptionHeaderSize + offsetArg; std::transform(extraPlaintextArg.begin(), extraPlaintextArg.end(), std::back_inserter(extraPlaintext), [](const std::pair& extra) { - return std::pair{ENCRYPTION_HEADER_SIZE + extra.first, extra.second}; + return std::pair{encryptionHeaderSize + extra.first, extra.second}; }); // merge contiguous plaintext with adjacent extra plaintext @@ -145,12 +145,12 @@ Data::Data(std::vector ciphertextArg, std::vector pl } // check that there is enough known plaintext - if (plaintext.size() < Attack::CONTIGUOUS_SIZE) + if (plaintext.size() < Attack::contiguousSize) throw Error("not enough contiguous plaintext (" + std::to_string(plaintext.size()) + - " bytes available, minimum is " + std::to_string(Attack::CONTIGUOUS_SIZE) + ")"); - if (plaintext.size() + extraPlaintext.size() < Attack::ATTACK_SIZE) + " bytes available, minimum is " + std::to_string(Attack::contiguousSize) + ")"); + if (plaintext.size() + extraPlaintext.size() < Attack::attackSize) throw Error("not enough plaintext (" + std::to_string(plaintext.size() + extraPlaintext.size()) + - " bytes available, minimum is " + std::to_string(Attack::ATTACK_SIZE) + ")"); + " bytes available, minimum is " + std::to_string(Attack::attackSize) + ")"); // reorder remaining extra plaintext for filtering { @@ -159,8 +159,8 @@ Data::Data(std::vector ciphertextArg, std::vector pl std::inplace_merge( extraPlaintext.begin(), before, extraPlaintext.end(), [this](const std::pair& a, const std::pair& b) { - return absdiff(a.first, offset + Attack::CONTIGUOUS_SIZE) < - absdiff(b.first, offset + Attack::CONTIGUOUS_SIZE); + return absdiff(a.first, offset + Attack::contiguousSize) < + absdiff(b.first, offset + Attack::contiguousSize); }); } diff --git a/src/MultTab.cpp b/src/MultTab.cpp index 78abaaa..f18a6d2 100644 --- a/src/MultTab.cpp +++ b/src/MultTab.cpp @@ -4,9 +4,9 @@ const MultTab MultTab::instance; MultTab::MultTab() { - std::uint32_t prod = 0; // x * MULT - std::uint32_t prodinv = 0; // x * MULT^-1 - for (int x = 0; x < 256; x++, prod += MULT, prodinv += MULTINV) + std::uint32_t prod = 0; // x * mult + std::uint32_t prodinv = 0; // x * mult^-1 + for (int x = 0; x < 256; x++, prod += mult, prodinv += multInv) { multtab[x] = prod; multinvtab[x] = prodinv; diff --git a/src/Zip.cpp b/src/Zip.cpp index 29b1061..17d8ce0 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -42,11 +42,11 @@ std::ostream& write(std::ostream& os, const T& x) enum class Signature : std::uint32_t { - LOCAL_FILE_HEADER = 0x04034b50, - CENTRAL_DIRECTORY_HEADER = 0x02014b50, - ZIP64_EOCD = 0x06064b50, - ZIP64_EOCD_LOCATOR = 0x07064b50, - EOCD = 0x06054b50 + LocalFileHeader = 0x04034b50, + CentralDirectoryHeader = 0x02014b50, + Zip64Eocd = 0x06064b50, + Zip64EocdLocator = 0x07064b50, + Eocd = 0x06054b50 }; bool checkSignature(std::istream& is, const Signature& signature) @@ -66,10 +66,10 @@ std::uint64_t findCentralDirectoryOffset(std::istream& is) do { is.seekg(-22 - commentLength, std::ios::end); - } while (read(is, signature) && signature != static_cast(Signature::EOCD) && + } while (read(is, signature) && signature != static_cast(Signature::Eocd) && commentLength++ < mask<0, 16>); - if (!is || signature != static_cast(Signature::EOCD)) + if (!is || signature != static_cast(Signature::Eocd)) throw Zip::Error("could not find end of central directory signature"); } @@ -89,7 +89,7 @@ std::uint64_t findCentralDirectoryOffset(std::istream& is) // look for Zip64 end of central directory locator is.seekg(-40, std::ios::cur); - if (checkSignature(is, Signature::ZIP64_EOCD_LOCATOR)) + if (checkSignature(is, Signature::Zip64EocdLocator)) { std::uint64_t zip64EndOfCentralDirectoryOffset; @@ -101,7 +101,7 @@ std::uint64_t findCentralDirectoryOffset(std::istream& is) // read Zip64 end of central directory record is.seekg(zip64EndOfCentralDirectoryOffset, std::ios::beg); - if (checkSignature(is, Signature::ZIP64_EOCD)) + if (checkSignature(is, Signature::Zip64Eocd)) { std::uint16_t versionNeededToExtract; @@ -138,7 +138,7 @@ Zip::Iterator::Iterator(const Zip& archive) Zip::Iterator& Zip::Iterator::operator++() { - if (!checkSignature(*m_is, Signature::CENTRAL_DIRECTORY_HEADER)) + if (!checkSignature(*m_is, Signature::CentralDirectoryHeader)) return *this = Iterator{}; std::uint16_t flags; @@ -310,7 +310,7 @@ void Zip::checkEncryption(const Entry& entry, Encryption expected) std::istream& Zip::seek(const Entry& entry) const { m_is.seekg(entry.offset, std::ios::beg); - if (!checkSignature(m_is, Signature::LOCAL_FILE_HEADER)) + if (!checkSignature(m_is, Signature::LocalFileHeader)) throw Error("could not find local file header"); // skip local file header @@ -353,10 +353,10 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, m_is.get(); } - if (!checkSignature(m_is, Signature::LOCAL_FILE_HEADER)) + if (!checkSignature(m_is, Signature::LocalFileHeader)) throw Error("could not find local file header"); - write(os, static_cast(Signature::LOCAL_FILE_HEADER)); + write(os, static_cast(Signature::LocalFileHeader)); std::copy_n(std::istreambuf_iterator(m_is), 22, std::ostreambuf_iterator(os)); m_is.get(); diff --git a/src/Zreduction.cpp b/src/Zreduction.cpp index 2021255..30aa48b 100644 --- a/src/Zreduction.cpp +++ b/src/Zreduction.cpp @@ -21,24 +21,24 @@ Zreduction::Zreduction(const std::vector& keystream) void Zreduction::reduce(Progress& progress) { // variables to keep track of the smallest Zi[2,32) vector - constexpr std::size_t TRACK_SIZE = 1 << 16; - bool tracking = false; + constexpr std::size_t trackSizeThreshold = 1 << 16; + bool tracking = false; std::vector bestCopy; - std::size_t bestIndex = index, bestSize = TRACK_SIZE; + std::size_t bestIndex = index, bestSize = trackSizeThreshold; // variables to wait for a limited number of steps when a small enough vector is found - constexpr std::size_t WAIT_SIZE = 1 << 8; - bool waiting = false; - std::size_t wait = 0; + constexpr std::size_t waitSizeThreshold = 1 << 8; + bool waiting = false; + std::size_t wait = 0; std::vector zim1_10_32_vector; zim1_10_32_vector.reserve(1 << 22); std::bitset<1 << 22> zim1_10_32_set; progress.done = 0; - progress.total = keystream.size() - Attack::CONTIGUOUS_SIZE; + progress.total = keystream.size() - Attack::contiguousSize; - for (std::size_t i = index; i >= Attack::CONTIGUOUS_SIZE; i--) + for (std::size_t i = index; i >= Attack::contiguousSize; i--) { zim1_10_32_vector.clear(); zim1_10_32_set.reset(); @@ -74,7 +74,7 @@ void Zreduction::reduce(Progress& progress) // keep a copy of the vector because size is about to grow std::swap(bestCopy, zi_vector); - if (bestSize <= WAIT_SIZE) + if (bestSize <= waitSizeThreshold) { // enable waiting waiting = true; @@ -95,12 +95,12 @@ void Zreduction::reduce(Progress& progress) if (tracking) { // put bestCopy in zi_vector only if bestIndex is not the index of zi_vector - if (bestIndex != Attack::CONTIGUOUS_SIZE - 1) + if (bestIndex != Attack::contiguousSize - 1) std::swap(zi_vector, bestCopy); index = bestIndex; } else - index = Attack::CONTIGUOUS_SIZE - 1; + index = Attack::contiguousSize - 1; } void Zreduction::generate() diff --git a/src/main.cpp b/src/main.cpp index e1efa0f..fdf54a3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -109,7 +109,7 @@ try VirtualTerminalSupport vtSupport; // version information - std::cout << "bkcrack " << BKCRACK_VERSION << " - " << BKCRACK_VERSION_DATE << std::endl; + std::cout << "bkcrack " << bkcrackVersion << " - " << bkcrackVersionDate << std::endl; const Arguments args(argc, argv); if (args.help) @@ -146,9 +146,9 @@ try // generate and reduce Zi[10,32) values Zreduction zr(data.keystream); - if (data.keystream.size() > Attack::CONTIGUOUS_SIZE) + if (data.keystream.size() > Attack::contiguousSize) { - std::cout << "[" << put_time << "] Z reduction using " << (data.keystream.size() - Attack::CONTIGUOUS_SIZE) + std::cout << "[" << put_time << "] Z reduction using " << (data.keystream.size() - Attack::contiguousSize) << " bytes of known plaintext" << std::endl; ConsoleProgress progress(std::cout); @@ -160,7 +160,7 @@ try // carry out the attack on the remaining Zi[2,32) values std::cout << "[" << put_time << "] Attack on " << zr.getCandidates().size() << " Z values at index " - << (static_cast(data.offset + zr.getIndex()) - static_cast(Data::ENCRYPTION_HEADER_SIZE)) + << (static_cast(data.offset + zr.getIndex()) - static_cast(Data::encryptionHeaderSize)) << std::endl; const auto [state, restart] = [&]() -> std::pair @@ -229,7 +229,7 @@ try std::ofstream decipheredstream = openOutput(*args.decipheredFile); decipher(cipherstream, ciphersize, - args.keepHeader ? 0 : static_cast(Data::ENCRYPTION_HEADER_SIZE), decipheredstream, + args.keepHeader ? 0 : static_cast(Data::encryptionHeaderSize), decipheredstream, keys); } diff --git a/src/password.cpp b/src/password.cpp index d15c8fe..e53dfe8 100644 --- a/src/password.cpp +++ b/src/password.cpp @@ -22,7 +22,7 @@ Recovery::Recovery(const Keys& keys, const std::vector& charset, s z[6] = keys.getZ(); // derive Y5 - y[5] = (y[6] - 1) * MultTab::MULTINV - lsb(x[6]); + y[5] = (y[6] - 1) * MultTab::multInv - lsb(x[6]); // derive more Z bytes for (int i = 6; 1 < i; i--) @@ -32,13 +32,13 @@ Recovery::Recovery(const Keys& keys, const std::vector& charset, s for (std::uint8_t p5 : charset) { x[5] = Crc32Tab::crc32inv(x[6], p5); - y[4] = (y[5] - 1) * MultTab::MULTINV - lsb(x[5]); + y[4] = (y[5] - 1) * MultTab::multInv - lsb(x[5]); z[3] = Crc32Tab::crc32inv(z[4], msb(y[4])); for (std::uint8_t p4 : charset) { x[4] = Crc32Tab::crc32inv(x[5], p4); - y[3] = (y[4] - 1) * MultTab::MULTINV - lsb(x[4]); + y[3] = (y[4] - 1) * MultTab::multInv - lsb(x[4]); z[2] = Crc32Tab::crc32inv(z[3], msb(y[3])); z[1] = Crc32Tab::crc32inv(z[2], 0); z[0] = Crc32Tab::crc32inv(z[1], 0); @@ -83,7 +83,7 @@ void Recovery::recoverLongPassword(const Keys& initial) // precompute as much as we can about the next cipher state without knowing the password byte const std::uint32_t x0_partial = Crc32Tab::crc32(initial.getX(), 0); - const std::uint32_t y0_partial = initial.getY() * MultTab::MULT + 1; + const std::uint32_t y0_partial = initial.getY() * MultTab::mult + 1; const std::uint32_t z0_partial = Crc32Tab::crc32(initial.getZ(), 0); for (std::uint8_t pi : charset) @@ -144,8 +144,8 @@ void Recovery::recursion(int i) { if (i != 1) // the Y-list is not complete so generate Y{i-1} values { - const std::uint32_t fy = (y[i] - 1) * MultTab::MULTINV; - const std::uint32_t ffy = (fy - 1) * MultTab::MULTINV; + const std::uint32_t fy = (y[i] - 1) * MultTab::multInv; + const std::uint32_t ffy = (fy - 1) * MultTab::multInv; // get possible LSB(Xi) for (std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (y[i - 2] & mask<24, 32>)))) @@ -170,7 +170,7 @@ void Recovery::recursion(int i) else // the Y-list is complete { // only the X1 LSB was not set yet, so do it here - x[1] = (y[1] - 1) * MultTab::MULTINV - y[0]; + x[1] = (y[1] - 1) * MultTab::multInv - y[0]; if (x[1] > 0xff) return; From 2ef735e8a254fa8ba4e77b47997e0a45174f350c Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:02:42 +0100 Subject: [PATCH 07/19] Make single-argument constructors explicit --- include/Arguments.hpp | 2 +- include/ConsoleProgress.hpp | 3 ++- include/Data.hpp | 2 +- include/Keys.hpp | 11 +++++++---- include/Progress.hpp | 2 +- include/SigintHandler.hpp | 2 +- include/Zip.hpp | 2 +- include/Zreduction.hpp | 2 +- include/file.hpp | 2 +- include/types.hpp | 2 +- src/Keys.cpp | 1 - 11 files changed, 17 insertions(+), 14 deletions(-) diff --git a/include/Arguments.hpp b/include/Arguments.hpp index 5cf23a7..f12a2f6 100644 --- a/include/Arguments.hpp +++ b/include/Arguments.hpp @@ -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 diff --git a/include/ConsoleProgress.hpp b/include/ConsoleProgress.hpp index 6109731..3289da0 100644 --- a/include/ConsoleProgress.hpp +++ b/include/ConsoleProgress.hpp @@ -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(); diff --git a/include/Data.hpp b/include/Data.hpp index 2c57ac8..3c50584 100644 --- a/include/Data.hpp +++ b/include/Data.hpp @@ -16,7 +16,7 @@ struct Data { 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 diff --git a/include/Keys.hpp b/include/Keys.hpp index 96491bf..043ca8c 100644 --- a/include/Keys.hpp +++ b/include/Keys.hpp @@ -9,11 +9,14 @@ class Keys { public: - /// Constructor - Keys(std::uint32_t x = 0x12345678, std::uint32_t y = 0x23456789, std::uint32_t 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(std::uint8_t p) @@ -70,7 +73,7 @@ class Keys } private: - std::uint32_t x, y, z; + std::uint32_t x = 0x12345678, y = 0x23456789, z = 0x34567890; }; #endif // BKCRACK_KEYS_HPP diff --git a/include/Progress.hpp b/include/Progress.hpp index 055fdb3..18d8c80 100644 --- a/include/Progress.hpp +++ b/include/Progress.hpp @@ -18,7 +18,7 @@ class Progress }; /// Constructor - Progress(std::ostream& os); + explicit Progress(std::ostream& os); /// Get exclusive access to the shared output stream and output progress /// information with the given function diff --git a/include/SigintHandler.hpp b/include/SigintHandler.hpp index 071f17a..84836e7 100644 --- a/include/SigintHandler.hpp +++ b/include/SigintHandler.hpp @@ -10,7 +10,7 @@ class SigintHandler { public: /// Enable the signal handler - SigintHandler(std::atomic& destination); + explicit SigintHandler(std::atomic& destination); /// Disable the signal handler ~SigintHandler(); diff --git a/include/Zip.hpp b/include/Zip.hpp index e7d5896..2bd2e8c 100644 --- a/include/Zip.hpp +++ b/include/Zip.hpp @@ -25,7 +25,7 @@ class Zip { public: /// Constructor - Error(const std::string& description); + explicit Error(const std::string& description); }; /// Encryption algorithm diff --git a/include/Zreduction.hpp b/include/Zreduction.hpp index f484210..a9b74cc 100644 --- a/include/Zreduction.hpp +++ b/include/Zreduction.hpp @@ -9,7 +9,7 @@ class Zreduction { public: /// Constructor generating Zi[10,32) values from the last keystream byte - Zreduction(const std::vector& keystream); + explicit Zreduction(const std::vector& keystream); /// Reduce Zi[10,32) number using extra contiguous keystream void reduce(Progress& progress); diff --git a/include/file.hpp b/include/file.hpp index fdc2394..df94eba 100644 --- a/include/file.hpp +++ b/include/file.hpp @@ -31,7 +31,7 @@ class FileError : public BaseError { public: /// Constructor - FileError(const std::string& description); + explicit FileError(const std::string& description); }; /// \brief Open an input file stream diff --git a/include/types.hpp b/include/types.hpp index b2a1314..fbdfc51 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -15,7 +15,7 @@ class BaseError : public std::runtime_error { public: /// Constructor - BaseError(const std::string& type, const std::string& description); + explicit BaseError(const std::string& type, const std::string& description); }; // utility functions diff --git a/src/Keys.cpp b/src/Keys.cpp index ef310d5..be14ac6 100644 --- a/src/Keys.cpp +++ b/src/Keys.cpp @@ -8,7 +8,6 @@ Keys::Keys(std::uint32_t x, std::uint32_t y, std::uint32_t z) } Keys::Keys(const std::string& password) -: Keys() { for (char p : password) update(p); From 16a01783e31c10c577c9adb26f252ef3ff2b5bb8 Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:05:14 +0100 Subject: [PATCH 08/19] Remove inline specifier for methods that are implicitly inline anyways --- include/Crc32Tab.hpp | 8 ++++---- include/Keys.hpp | 6 +++--- include/KeystreamTab.hpp | 6 +++--- include/MultTab.hpp | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/Crc32Tab.hpp b/include/Crc32Tab.hpp index 2372312..a78eae9 100644 --- a/include/Crc32Tab.hpp +++ b/include/Crc32Tab.hpp @@ -8,25 +8,25 @@ class Crc32Tab { public: /// \return CRC32 using a lookup table - static inline std::uint32_t crc32(std::uint32_t pval, std::uint8_t b) + static std::uint32_t crc32(std::uint32_t pval, std::uint8_t b) { return pval >> 8 ^ instance.crctab[lsb(pval) ^ b]; } /// \return CRC32^-1 using a lookup table - static inline std::uint32_t crc32inv(std::uint32_t crc, std::uint8_t b) + static std::uint32_t crc32inv(std::uint32_t crc, std::uint8_t b) { return crc << 8 ^ instance.crcinvtab[msb(crc)] ^ b; } /// \return Yi[24,32) from Zi and Z{i-1} using CRC32^-1 - static inline std::uint32_t getYi_24_32(std::uint32_t zi, std::uint32_t zim1) + static std::uint32_t getYi_24_32(std::uint32_t zi, std::uint32_t zim1) { return (crc32inv(zi, 0) ^ zim1) << 24; } /// \return Z{i-1}[10,32) from Zi[2,32) using CRC32^-1 - static inline std::uint32_t getZim1_10_32(std::uint32_t zi_2_32) + static std::uint32_t getZim1_10_32(std::uint32_t zi_2_32) { return crc32inv(zi_2_32, 0) & mask<10, 32>; // discard 10 least significant bits } diff --git a/include/Keys.hpp b/include/Keys.hpp index 043ca8c..f786032 100644 --- a/include/Keys.hpp +++ b/include/Keys.hpp @@ -19,7 +19,7 @@ class Keys explicit Keys(const std::string& password); /// Update the state with a plaintext byte - inline void update(std::uint8_t p) + void update(std::uint8_t p) { x = Crc32Tab::crc32(x, p); y = (y + lsb(x)) * MultTab::mult + 1; @@ -30,7 +30,7 @@ class Keys void update(const std::vector& ciphertext, std::size_t current, std::size_t target); /// Update the state backward with a ciphertext byte - inline void updateBackward(std::uint8_t c) + void updateBackward(std::uint8_t c) { z = Crc32Tab::crc32inv(z, msb(y)); y = (y - 1) * MultTab::multInv - lsb(x); @@ -38,7 +38,7 @@ class Keys } /// Update the state backward with a plaintext byte - inline void updateBackwardPlaintext(std::uint8_t p) + void updateBackwardPlaintext(std::uint8_t p) { z = Crc32Tab::crc32inv(z, msb(y)); y = (y - 1) * MultTab::multInv - lsb(x); diff --git a/include/KeystreamTab.hpp b/include/KeystreamTab.hpp index f660bf8..da876dc 100644 --- a/include/KeystreamTab.hpp +++ b/include/KeystreamTab.hpp @@ -11,7 +11,7 @@ class KeystreamTab public: /// \return the keystream byte ki associated to a Zi value /// \note Only Zi[2,16) is used - static inline std::uint8_t getByte(std::uint32_t zi) + static std::uint8_t getByte(std::uint32_t zi) { return instance.keystreamtab[(zi & mask<0, 16>) >> 2]; } @@ -19,14 +19,14 @@ class KeystreamTab /// \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 std::vector& getZi_2_16_vector(std::uint8_t ki, std::uint32_t zi_10_16) + static const std::vector& getZi_2_16_vector(std::uint8_t ki, std::uint32_t zi_10_16) { 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(std::uint8_t ki, std::uint32_t zi_10_16) + static bool hasZi_2_16(std::uint8_t ki, std::uint32_t zi_10_16) { return instance.keystreaminvexists[ki][(zi_10_16 & mask<0, 16>) >> 10]; } diff --git a/include/MultTab.hpp b/include/MultTab.hpp index e51ce6c..d33a928 100644 --- a/include/MultTab.hpp +++ b/include/MultTab.hpp @@ -8,27 +8,27 @@ class MultTab { public: /// \return mult * x using a lookup table - static inline std::uint32_t getMult(std::uint8_t x) + static std::uint32_t getMult(std::uint8_t x) { return instance.multtab[x]; } /// \return mult^-1 * x using a lookup table - static inline std::uint32_t getMultinv(std::uint8_t x) + static std::uint32_t getMultinv(std::uint8_t x) { return instance.multinvtab[x]; } /// \return a vector of bytes x such that /// msb(x*mult^-1) is equal to msbprod or msbprod-1 - static inline const std::vector& getMsbProdFiber2(std::uint8_t msbprodinv) + static const std::vector& getMsbProdFiber2(std::uint8_t msbprodinv) { return instance.msbprodfiber2[msbprodinv]; } /// \return a vector of bytes x such that /// msb(x*mult^-1) is equal to msbprod, msbprod-1 or msbprod+1 - static inline const std::vector& getMsbProdFiber3(std::uint8_t msbprodinv) + static const std::vector& getMsbProdFiber3(std::uint8_t msbprodinv) { return instance.msbprodfiber3[msbprodinv]; } From 5ca06b938b5698d5c325688b31c6a8969a30aaec Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:06:13 +0100 Subject: [PATCH 09/19] Make const what can be const --- include/Progress.hpp | 2 +- src/Arguments.cpp | 6 +++--- src/Attack.cpp | 16 ++++++++-------- src/ConsoleProgress.cpp | 6 +++--- src/Keys.cpp | 2 +- src/KeystreamTab.cpp | 2 +- src/Zip.cpp | 4 ++-- src/Zreduction.cpp | 8 ++++---- src/log.cpp | 2 +- src/main.cpp | 14 +++++++------- src/password.cpp | 20 ++++++++++---------- 11 files changed, 41 insertions(+), 41 deletions(-) diff --git a/include/Progress.hpp b/include/Progress.hpp index 18d8c80..7e6f64b 100644 --- a/include/Progress.hpp +++ b/include/Progress.hpp @@ -25,7 +25,7 @@ class Progress template void log(F f) { - std::scoped_lock lock{m_os_mutex}; + const std::scoped_lock lock{m_os_mutex}; f(m_os); } diff --git a/src/Arguments.cpp b/src/Arguments.cpp index d87b5e5..b3feec2 100644 --- a/src/Arguments.cpp +++ b/src/Arguments.cpp @@ -229,7 +229,7 @@ void Arguments::parseArgument() case Option::extraPlaintext: { int i = readInt("offset"); - for (std::uint8_t b : readHex("data")) + for (const std::uint8_t b : readHex("data")) extraPlaintext[i++] = b; break; } @@ -356,8 +356,8 @@ Arguments::Option Arguments::readOption(const std::string& description) #undef PAIR #undef PAIRS - std::string str = readString(description); - if (auto it = stringToOption.find(str); it == stringToOption.end()) + const std::string str = readString(description); + if (const auto it = stringToOption.find(str); it == stringToOption.end()) throw Error("unknown option " + str); else return it->second; diff --git a/src/Attack.cpp b/src/Attack.cpp index 405025b..31614b7 100644 --- a/src/Attack.cpp +++ b/src/Attack.cpp @@ -31,10 +31,10 @@ void Attack::exploreZlists(int i) if (i != 0) // the Z-list is not complete so generate Z{i-1}[2,32) values { // get Z{i-1}[10,32) from CRC32^-1 - std::uint32_t zim1_10_32 = Crc32Tab::getZim1_10_32(zlist[i]); + const std::uint32_t zim1_10_32 = Crc32Tab::getZim1_10_32(zlist[i]); // get Z{i-1}[2,16) values from keystream byte k{i-1} and Z{i-1}[10,16) - for (std::uint32_t zim1_2_16 : KeystreamTab::getZi_2_16_vector(data.keystream[index + i - 1], zim1_10_32)) + for (const std::uint32_t zim1_2_16 : KeystreamTab::getZi_2_16_vector(data.keystream[index + i - 1], zim1_10_32)) { // add Z{i-1}[2,32) to the Z-list zlist[i - 1] = zim1_10_32 | zim1_2_16; @@ -56,7 +56,7 @@ void Attack::exploreZlists(int i) for (std::uint32_t y7_8_24 = 0, prod = (MultTab::getMultinv(msb(ylist[7])) << 24) - MultTab::multInv; y7_8_24 < 1 << 24; y7_8_24 += 1 << 8, prod += MultTab::multInv << 8) // get possible Y7[0,8) values - for (std::uint8_t y7_0_8 : MultTab::getMsbProdFiber3(msb(ylist[6]) - msb(prod))) + for (const std::uint8_t y7_0_8 : MultTab::getMsbProdFiber3(msb(ylist[6]) - msb(prod))) // filter Y7[0,8) using Y6[24,32) if (prod + MultTab::getMultinv(y7_0_8) - (ylist[6] & mask<24, 32>) <= maxdiff<24>) { @@ -70,14 +70,14 @@ void Attack::exploreYlists(int i) { if (i != 3) // the Y-list is not complete so generate Y{i-1} values { - std::uint32_t fy = (ylist[i] - 1) * MultTab::multInv; - std::uint32_t ffy = (fy - 1) * MultTab::multInv; + const std::uint32_t fy = (ylist[i] - 1) * MultTab::multInv; + const std::uint32_t ffy = (fy - 1) * MultTab::multInv; // get possible LSB(Xi) - for (std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (ylist[i - 2] & mask<24, 32>)))) + for (const std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (ylist[i - 2] & mask<24, 32>)))) { // compute corresponding Y{i-1} - std::uint32_t yim1 = fy - xi_0_8; + const std::uint32_t yim1 = fy - xi_0_8; // filter values with Y{i-2}[24,32) if (ffy - MultTab::getMultinv(xi_0_8) - (ylist[i - 2] & mask<24, 32>) <= maxdiff<24> && @@ -110,7 +110,7 @@ void Attack::testXlist() x = Crc32Tab::crc32inv(x, data.plaintext[index + i]); // check that X3 fits with Y1[26,32) - std::uint32_t y1_26_32 = Crc32Tab::getYi_24_32(zlist[1], zlist[0]) & mask<26, 32>; + const std::uint32_t y1_26_32 = Crc32Tab::getYi_24_32(zlist[1], zlist[0]) & mask<26, 32>; if (((ylist[3] - 1) * MultTab::multInv - lsb(x) - 1) * MultTab::multInv - y1_26_32 > maxdiff<26>) return; diff --git a/src/ConsoleProgress.cpp b/src/ConsoleProgress.cpp index a816d53..ce15b26 100644 --- a/src/ConsoleProgress.cpp +++ b/src/ConsoleProgress.cpp @@ -13,7 +13,7 @@ ConsoleProgress::ConsoleProgress(std::ostream& os, const std::chrono::millisecon ConsoleProgress::~ConsoleProgress() { { - std::scoped_lock lock{m_in_destructor_mutex}; + const std::scoped_lock lock{m_in_destructor_mutex}; m_in_destructor = true; } @@ -34,7 +34,7 @@ void ConsoleProgress::printerFunction() while (repeat) { - if (int total = this->total.load()) + if (const int total = this->total.load()) log( [done = done.load(), total](std::ostream& os) { @@ -52,7 +52,7 @@ void ConsoleProgress::printerFunction() repeat = !m_in_destructor_cv.wait_for(lock, m_interval, [this] { return m_in_destructor; }); } - if (int total = this->total.load()) + if (const int total = this->total.load()) log( [done = done.load(), total](std::ostream& os) { diff --git a/src/Keys.cpp b/src/Keys.cpp index be14ac6..64a8602 100644 --- a/src/Keys.cpp +++ b/src/Keys.cpp @@ -9,7 +9,7 @@ Keys::Keys(std::uint32_t x, std::uint32_t y, std::uint32_t z) Keys::Keys(const std::string& password) { - for (char p : password) + for (const char p : password) update(p); } diff --git a/src/KeystreamTab.cpp b/src/KeystreamTab.cpp index 95f86df..c3a7dc1 100644 --- a/src/KeystreamTab.cpp +++ b/src/KeystreamTab.cpp @@ -6,7 +6,7 @@ KeystreamTab::KeystreamTab() { for (std::uint32_t z_2_16 = 0; z_2_16 < 1 << 16; z_2_16 += 4) { - std::uint8_t k = lsb((z_2_16 | 2) * (z_2_16 | 3) >> 8); + const std::uint8_t k = lsb((z_2_16 | 2) * (z_2_16 | 3) >> 8); keystreamtab[z_2_16 >> 2] = k; keystreaminvfiltertab[k][z_2_16 >> 10].push_back(z_2_16); keystreaminvexists[k].set(z_2_16 >> 10); diff --git a/src/Zip.cpp b/src/Zip.cpp index 17d8ce0..71ead50 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -380,8 +380,8 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, std::generate_n(std::ostreambuf_iterator(os), packedSize, [&in, &decrypt, &encrypt]() -> char { - std::uint8_t p = *in++ ^ decrypt.getK(); - std::uint8_t c = p ^ encrypt.getK(); + const std::uint8_t p = *in++ ^ decrypt.getK(); + const std::uint8_t c = p ^ encrypt.getK(); decrypt.update(p); encrypt.update(p); return c; diff --git a/src/Zreduction.cpp b/src/Zreduction.cpp index 30aa48b..c989f91 100644 --- a/src/Zreduction.cpp +++ b/src/Zreduction.cpp @@ -45,11 +45,11 @@ void Zreduction::reduce(Progress& progress) std::size_t number_of_zim1_2_32 = 0; // generate the Z{i-1}[10,32) values - for (std::uint32_t zi_10_32 : zi_vector) - for (std::uint32_t zi_2_16 : KeystreamTab::getZi_2_16_vector(keystream[i], zi_10_32)) + for (const std::uint32_t zi_10_32 : zi_vector) + for (const std::uint32_t zi_2_16 : KeystreamTab::getZi_2_16_vector(keystream[i], zi_10_32)) { // get Z{i-1}[10,32) from CRC32^-1 - std::uint32_t zim1_10_32 = Crc32Tab::getZim1_10_32(zi_10_32 | zi_2_16); + const std::uint32_t zim1_10_32 = Crc32Tab::getZim1_10_32(zi_10_32 | zi_2_16); // collect without duplicates only those that are compatible with keystream{i-1} if (!zim1_10_32_set[zim1_10_32 >> 10] && KeystreamTab::hasZi_2_16(keystream[i - 1], zim1_10_32)) { @@ -105,7 +105,7 @@ void Zreduction::reduce(Progress& progress) void Zreduction::generate() { - std::size_t number_of_zi_10_32 = zi_vector.size(); + const std::size_t number_of_zi_10_32 = zi_vector.size(); for (std::size_t i = 0; i < number_of_zi_10_32; i++) { const std::vector& zi_2_16_vector = diff --git a/src/log.cpp b/src/log.cpp index d3aedec..f7a8e21 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -7,7 +7,7 @@ std::ostream& put_time(std::ostream& os) { - std::time_t t = std::time(nullptr); + const std::time_t t = std::time(nullptr); return os << std::put_time(std::localtime(&t), "%T"); } diff --git a/src/main.cpp b/src/main.cpp index fdf54a3..c160116 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,7 @@ namespace { -const char* usage = R"_(usage: bkcrack [options] +const char* const usage = R"_(usage: bkcrack [options] Crack legacy zip encryption with Biham and Kocher's known plaintext attack. Options to get the internal password representation: @@ -165,9 +165,9 @@ try const auto [state, restart] = [&]() -> std::pair { - int start = args.attackStart; - ConsoleProgress progress(std::cout); - SigintHandler sigintHandler{progress.state}; + int start = args.attackStart; + ConsoleProgress progress(std::cout); + const SigintHandler sigintHandler{progress.state}; keysvec = attack(data, zr.getCandidates(), start, zr.getIndex(), args.jobs, args.exhaustive, progress); return {progress.state, start}; }(); @@ -286,8 +286,8 @@ try const auto& [minLength, maxLength] = args.length.value_or(Arguments::LengthInterval{}); std::string start = args.recoveryStart; - ConsoleProgress progress(std::cout); - SigintHandler sigintHandler(progress.state); + ConsoleProgress progress(std::cout); + const SigintHandler sigintHandler(progress.state); passwords = recoverPassword(keysvec.front(), charset, minLength, maxLength, start, args.jobs, args.exhaustive, progress); return {progress.state, start}; @@ -449,7 +449,7 @@ void decipher(std::istream& is, std::size_t size, std::size_t discard, std::ostr for (std::ostreambuf_iterator plain(os); i < size && cipher != std::istreambuf_iterator(); i++, ++cipher, ++plain) { - std::uint8_t p = *cipher ^ keys.getK(); + const std::uint8_t p = *cipher ^ keys.getK(); keys.update(p); *plain = p; } diff --git a/src/password.cpp b/src/password.cpp index e53dfe8..3963d6e 100644 --- a/src/password.cpp +++ b/src/password.cpp @@ -29,13 +29,13 @@ Recovery::Recovery(const Keys& keys, const std::vector& charset, s z[i - 1] = Crc32Tab::crc32inv(z[i], msb(y[i])); // precompute possible Z0[16,32) and Z{-1}[24,32) - for (std::uint8_t p5 : charset) + for (const std::uint8_t p5 : charset) { x[5] = Crc32Tab::crc32inv(x[6], p5); y[4] = (y[5] - 1) * MultTab::multInv - lsb(x[5]); z[3] = Crc32Tab::crc32inv(z[4], msb(y[4])); - for (std::uint8_t p4 : charset) + for (const std::uint8_t p4 : charset) { x[4] = Crc32Tab::crc32inv(x[5], p4); y[3] = (y[4] - 1) * MultTab::multInv - lsb(x[4]); @@ -86,7 +86,7 @@ void Recovery::recoverLongPassword(const Keys& initial) const std::uint32_t y0_partial = initial.getY() * MultTab::mult + 1; const std::uint32_t z0_partial = Crc32Tab::crc32(initial.getZ(), 0); - for (std::uint8_t pi : charset) + for (const std::uint8_t pi : charset) { // finish to update the cipher state const std::uint32_t x0 = x0_partial ^ Crc32Tab::crc32(0, pi); @@ -126,7 +126,7 @@ void Recovery::recoverLongPassword(const Keys& initial) { prefix.push_back(charset[0]); - for (std::uint8_t pi : charset) + for (const std::uint8_t pi : charset) { Keys init = initial; init.update(pi); @@ -148,7 +148,7 @@ void Recovery::recursion(int i) const std::uint32_t ffy = (fy - 1) * MultTab::multInv; // get possible LSB(Xi) - for (std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (y[i - 2] & mask<24, 32>)))) + for (const std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (y[i - 2] & mask<24, 32>)))) { // compute corresponding Y{i-1} const std::uint32_t yim1 = fy - xi_0_8; @@ -201,7 +201,7 @@ void Recovery::recursion(int i) const auto fillBefore = os.fill('0'); os << "Password: " << password << " (as bytes:"; - for (std::uint8_t c : password) + for (const std::uint8_t c : password) os << ' ' << std::setw(2) << static_cast(c); os << ')' << std::endl; @@ -256,7 +256,7 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c { for (auto i = nextCandidateIndex++; i < charsetSize; i = nextCandidateIndex++) { - std::uint8_t pm4 = worker.charset[i]; + const std::uint8_t pm4 = worker.charset[i]; Keys init = initial; init.update(pm4); @@ -315,8 +315,8 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c { for (auto i = nextCandidateIndex++; i < charsetSize * charsetSize; i = nextCandidateIndex++) { - std::uint8_t pm4 = worker.charset[i / charsetSize]; - std::uint8_t pm3 = worker.charset[i % charsetSize]; + const std::uint8_t pm4 = worker.charset[i / charsetSize]; + const std::uint8_t pm3 = worker.charset[i % charsetSize]; Keys init = initial; init.update(pm4); @@ -361,7 +361,7 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c for (int i = index_start; i < charsetSize; i++) { - std::uint8_t pi = worker.charset[i]; + const std::uint8_t pi = worker.charset[i]; Keys init = initial; init.update(pi); From 4274537f34f592101b2406f6f7b6b4239423a271 Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:04:44 +0100 Subject: [PATCH 10/19] Avoid shadowing variables --- include/password.hpp | 2 +- src/Zip.cpp | 6 +++--- src/password.cpp | 22 +++++++++++----------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/password.hpp b/include/password.hpp index 734968d..58cc34e 100644 --- a/include/password.hpp +++ b/include/password.hpp @@ -61,7 +61,7 @@ class Recovery // cipher state (X,Y,Z)_i for index i in [0, 6] where the last state (X,Y,Z)_6 is // the representation of the password to recover std::array x, y, z; - std::uint32_t x0; // backup of candidate X value for convenience + std::uint32_t candidateX0; // backup of candidate X value for convenience std::array p; // password last 6 bytes diff --git a/src/Zip.cpp b/src/Zip.cpp index 71ead50..42a8c34 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -226,12 +226,12 @@ Zip::Iterator& Zip::Iterator::operator++() case 0x9901: // AE-x encryption structure if (7 <= size) { - std::uint16_t method; + std::uint16_t actualMethod; m_is->seekg(5, std::ios::cur); - read(*m_is, method); + read(*m_is, actualMethod); size -= 7; - m_entry->compression = static_cast(method); + m_entry->compression = static_cast(actualMethod); } break; diff --git a/src/password.cpp b/src/password.cpp index 3963d6e..4be65e1 100644 --- a/src/password.cpp +++ b/src/password.cpp @@ -56,9 +56,9 @@ void Recovery::recoverShortPassword(const Keys& initial) return; // initialize starting X, Y and Z values - x[0] = x0 = initial.getX(); - y[0] = initial.getY(); - z[0] = initial.getZ(); + x[0] = candidateX0 = initial.getX(); + y[0] = initial.getY(); + z[0] = initial.getZ(); // complete Z values and derive Y[24,32) values for (int i = 1; i <= 4; i++) @@ -102,9 +102,9 @@ void Recovery::recoverLongPassword(const Keys& initial) prefix.back() = pi; // initialize starting X, Y and Z values - x[0] = this->x0 = x0; - y[0] = y0; - z[0] = z0; + x[0] = candidateX0 = x0; + y[0] = y0; + z[0] = z0; // complete Z values and derive Y[24,32) values y[1] = Crc32Tab::getYi_24_32(z[1], z[1 - 1]); @@ -175,14 +175,14 @@ void Recovery::recursion(int i) return; // complete X values and derive password - for (int i = 5; 0 <= i; i--) + for (int j = 5; 0 <= j; j--) { - const std::uint32_t xi_xor_pi = Crc32Tab::crc32inv(x[i + 1], 0); - p[i] = lsb(xi_xor_pi ^ x[i]); - x[i] = xi_xor_pi ^ p[i]; + const std::uint32_t xi_xor_pi = Crc32Tab::crc32inv(x[j + 1], 0); + p[j] = lsb(xi_xor_pi ^ x[j]); + x[j] = xi_xor_pi ^ p[j]; } - if (x[0] == x0) // the password is successfully recovered + if (x[0] == candidateX0) // the password is successfully recovered { std::string password = std::string(prefix.begin(), prefix.end()); password.append(p.begin(), p.end()); From 29bbfb20423b437c125ced9925f9c5694e98e656 Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:02:14 +0100 Subject: [PATCH 11/19] Use std::accumulate instead of raw loop The value can become const, which is nice. --- src/Zip.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Zip.cpp b/src/Zip.cpp index 42a8c34..c80b9d8 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace { @@ -205,10 +206,9 @@ Zip::Iterator& Zip::Iterator::operator++() case 0x7075: // Info-ZIP Unicode Path if (5 <= size) { - std::uint32_t nameCrc32 = mask<0, 32>; - for (std::uint8_t b : m_entry->name) - nameCrc32 = Crc32Tab::crc32(nameCrc32, b); - nameCrc32 ^= mask<0, 32>; + const auto nameCrc32 = + std::accumulate(m_entry->name.begin(), m_entry->name.end(), mask<0, 32>, Crc32Tab::crc32) ^ + mask<0, 32>; std::uint32_t expectedNameCrc32; m_is->seekg(1, std::ios::cur); From 93c486caca8c0955ce1fb19e6e654adb2963a92a Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:03:51 +0100 Subject: [PATCH 12/19] Move absdiff function to the only place it is used --- include/types.hpp | 6 ------ src/Data.cpp | 4 +++- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/include/types.hpp b/include/types.hpp index fbdfc51..f855886 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -32,12 +32,6 @@ constexpr std::uint8_t msb(std::uint32_t x) return x >> 24; } -/// \return the absolute difference between two unsigned values -inline std::size_t absdiff(std::size_t x, std::size_t y) -{ - return x < y ? y - x : x - y; -} - // constants /// Constant value for bit masking diff --git a/src/Data.cpp b/src/Data.cpp index 5a71d73..9bf5c73 100644 --- a/src/Data.cpp +++ b/src/Data.cpp @@ -158,7 +158,9 @@ Data::Data(std::vector ciphertextArg, std::vector pl std::reverse(extraPlaintext.begin(), before); std::inplace_merge( extraPlaintext.begin(), before, extraPlaintext.end(), - [this](const std::pair& a, const std::pair& b) { + [this](const std::pair& a, const std::pair& b) + { + constexpr auto absdiff = [](std::size_t x, std::size_t y) { return x < y ? y - x : x - y; }; return absdiff(a.first, offset + Attack::contiguousSize) < absdiff(b.first, offset + Attack::contiguousSize); }); From 67c2f34101e169b2b945ee7a9936cdfeeb77969e Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:06:49 +0100 Subject: [PATCH 13/19] Use transparent std::bix_xor --- src/Data.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data.cpp b/src/Data.cpp index 9bf5c73..958b119 100644 --- a/src/Data.cpp +++ b/src/Data.cpp @@ -168,5 +168,5 @@ Data::Data(std::vector ciphertextArg, std::vector pl // compute keystream std::transform(plaintext.begin(), plaintext.end(), ciphertext.begin() + offset, std::back_inserter(keystream), - std::bit_xor()); + std::bit_xor<>()); } From 3f6ba93805b1d607c5e205b08fb74c4b0c5300df Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:07:26 +0100 Subject: [PATCH 14/19] Use data() instead of address of first character --- src/Zip.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Zip.cpp b/src/Zip.cpp index c80b9d8..e2112b3 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -26,7 +26,7 @@ std::istream& read(std::istream& is, T& x) std::istream& read(std::istream& is, std::string& string, std::size_t length) { string.resize(length); - return is.read(&string[0], string.size()); + return is.read(string.data(), string.size()); } template From 37e75cef1c06047568c835ae35fbb05302d25a8b Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:12:38 +0100 Subject: [PATCH 15/19] Avoid having multiple declarations in a single statement for readability --- include/Keys.hpp | 4 +++- src/Data.cpp | 3 ++- src/Zip.cpp | 6 ++++-- src/Zreduction.cpp | 3 ++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/Keys.hpp b/include/Keys.hpp index f786032..c19cc1e 100644 --- a/include/Keys.hpp +++ b/include/Keys.hpp @@ -73,7 +73,9 @@ class Keys } private: - std::uint32_t x = 0x12345678, y = 0x23456789, z = 0x34567890; + std::uint32_t x = 0x12345678; + std::uint32_t y = 0x23456789; + std::uint32_t z = 0x34567890; }; #endif // BKCRACK_KEYS_HPP diff --git a/src/Data.cpp b/src/Data.cpp index 958b119..fe4c2c2 100644 --- a/src/Data.cpp +++ b/src/Data.cpp @@ -21,7 +21,8 @@ struct Range return size() < other.size(); } - std::vector>::iterator begin, end; + std::vector>::iterator begin; + std::vector>::iterator end; }; } // namespace diff --git a/src/Zip.cpp b/src/Zip.cpp index e2112b3..c0ec6b8 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -314,7 +314,8 @@ std::istream& Zip::seek(const Entry& entry) const throw Error("could not find local file header"); // skip local file header - std::uint16_t nameSize, extraSize; + std::uint16_t nameSize; + std::uint16_t extraSize; m_is.seekg(22, std::ios::cur); read(m_is, nameSize); read(m_is, extraSize); @@ -361,7 +362,8 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, std::copy_n(std::istreambuf_iterator(m_is), 22, std::ostreambuf_iterator(os)); m_is.get(); - std::uint16_t filenameLength, extraSize; + std::uint16_t filenameLength; + std::uint16_t extraSize; read(m_is, filenameLength); read(m_is, extraSize); write(os, filenameLength); diff --git a/src/Zreduction.cpp b/src/Zreduction.cpp index c989f91..2ea41c6 100644 --- a/src/Zreduction.cpp +++ b/src/Zreduction.cpp @@ -24,7 +24,8 @@ void Zreduction::reduce(Progress& progress) constexpr std::size_t trackSizeThreshold = 1 << 16; bool tracking = false; std::vector bestCopy; - std::size_t bestIndex = index, bestSize = trackSizeThreshold; + std::size_t bestIndex = index; + std::size_t bestSize = trackSizeThreshold; // variables to wait for a limited number of steps when a small enough vector is found constexpr std::size_t waitSizeThreshold = 1 << 8; From 136cdb605f1731261760909a45b5755e488ac68f Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 15:27:03 +0100 Subject: [PATCH 16/19] Switch to trailing return type style --- include/Arguments.hpp | 20 ++++++++++---------- include/Attack.hpp | 4 ++-- include/Crc32Tab.hpp | 8 ++++---- include/Keys.hpp | 8 ++++---- include/KeystreamTab.hpp | 6 +++--- include/MultTab.hpp | 8 ++++---- include/SigintHandler.hpp | 2 +- include/Zip.hpp | 26 +++++++++++++------------- include/Zreduction.hpp | 4 ++-- include/file.hpp | 8 ++++---- include/log.hpp | 4 ++-- include/password.hpp | 6 +++--- include/types.hpp | 4 ++-- src/Arguments.cpp | 28 ++++++++++++++-------------- src/Attack.cpp | 4 ++-- src/Data.cpp | 4 ++-- src/Zip.cpp | 22 +++++++++++----------- src/Zreduction.cpp | 4 ++-- src/file.cpp | 8 ++++---- src/log.cpp | 4 ++-- src/main.cpp | 6 +++--- src/password.cpp | 6 +++--- 22 files changed, 97 insertions(+), 97 deletions(-) diff --git a/include/Arguments.hpp b/include/Arguments.hpp index f12a2f6..76251e0 100644 --- a/include/Arguments.hpp +++ b/include/Arguments.hpp @@ -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 cipherFile; ///< File containing the ciphertext std::optional cipherIndex; ///< Index of the zip entry containing ciphertext @@ -104,7 +104,7 @@ class Arguments std::size_t maxLength{std::numeric_limits::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 length; @@ -131,7 +131,7 @@ class Arguments const char** m_current; const char** const m_end; - bool finished() const; + auto finished() const -> bool; void parseArgument(); @@ -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); - std::vector readHex(const std::string& description); - std::uint32_t readKey(const std::string& description); - std::vector 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; + auto readKey(const std::string& description) -> std::uint32_t; + auto readCharset() -> std::vector; }; #endif // BKCRACK_ARGUMENTS_HPP diff --git a/include/Attack.hpp b/include/Attack.hpp index 0dcc2c1..651f8d1 100644 --- a/include/Attack.hpp +++ b/include/Attack.hpp @@ -68,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 attack(const Data& data, const std::vector& zi_2_32_vector, int& start, - std::size_t index, int jobs, bool exhaustive, Progress& progress); +auto attack(const Data& data, const std::vector& zi_2_32_vector, int& start, std::size_t index, int jobs, + bool exhaustive, Progress& progress) -> std::vector; #endif // BKCRACK_ATTACK_HPP diff --git a/include/Crc32Tab.hpp b/include/Crc32Tab.hpp index a78eae9..3cd2407 100644 --- a/include/Crc32Tab.hpp +++ b/include/Crc32Tab.hpp @@ -8,25 +8,25 @@ class Crc32Tab { public: /// \return CRC32 using a lookup table - static std::uint32_t crc32(std::uint32_t pval, std::uint8_t 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 std::uint32_t crc32inv(std::uint32_t crc, std::uint8_t 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 std::uint32_t getYi_24_32(std::uint32_t zi, std::uint32_t 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 std::uint32_t getZim1_10_32(std::uint32_t 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 } diff --git a/include/Keys.hpp b/include/Keys.hpp index c19cc1e..7b0fb5e 100644 --- a/include/Keys.hpp +++ b/include/Keys.hpp @@ -49,25 +49,25 @@ class Keys void updateBackward(const std::vector& ciphertext, std::size_t current, std::size_t target); /// \return X value - std::uint32_t getX() const + auto getX() const -> std::uint32_t { return x; } /// \return Y value - std::uint32_t getY() const + auto getY() const -> std::uint32_t { return y; } /// \return Z value - std::uint32_t getZ() const + auto getZ() const -> std::uint32_t { return z; } /// \return the keystream byte derived from the keys - std::uint8_t getK() const + auto getK() const -> std::uint8_t { return KeystreamTab::getByte(z); } diff --git a/include/KeystreamTab.hpp b/include/KeystreamTab.hpp index da876dc..9eaf80a 100644 --- a/include/KeystreamTab.hpp +++ b/include/KeystreamTab.hpp @@ -11,7 +11,7 @@ class KeystreamTab public: /// \return the keystream byte ki associated to a Zi value /// \note Only Zi[2,16) is used - static std::uint8_t getByte(std::uint32_t zi) + static auto getByte(std::uint32_t zi) -> std::uint8_t { return instance.keystreamtab[(zi & mask<0, 16>) >> 2]; } @@ -19,14 +19,14 @@ class KeystreamTab /// \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 const std::vector& getZi_2_16_vector(std::uint8_t ki, std::uint32_t zi_10_16) + static auto getZi_2_16_vector(std::uint8_t ki, std::uint32_t zi_10_16) -> const std::vector& { 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 bool hasZi_2_16(std::uint8_t ki, std::uint32_t 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]; } diff --git a/include/MultTab.hpp b/include/MultTab.hpp index d33a928..c9a0380 100644 --- a/include/MultTab.hpp +++ b/include/MultTab.hpp @@ -8,27 +8,27 @@ class MultTab { public: /// \return mult * x using a lookup table - static std::uint32_t getMult(std::uint8_t x) + static auto getMult(std::uint8_t x) -> std::uint32_t { return instance.multtab[x]; } /// \return mult^-1 * x using a lookup table - static std::uint32_t getMultinv(std::uint8_t x) + static auto getMultinv(std::uint8_t x) -> std::uint32_t { return instance.multinvtab[x]; } /// \return a vector of bytes x such that /// msb(x*mult^-1) is equal to msbprod or msbprod-1 - static const std::vector& getMsbProdFiber2(std::uint8_t msbprodinv) + static auto getMsbProdFiber2(std::uint8_t msbprodinv) -> const std::vector& { return instance.msbprodfiber2[msbprodinv]; } /// \return a vector of bytes x such that /// msb(x*mult^-1) is equal to msbprod, msbprod-1 or msbprod+1 - static const std::vector& getMsbProdFiber3(std::uint8_t msbprodinv) + static auto getMsbProdFiber3(std::uint8_t msbprodinv) -> const std::vector& { return instance.msbprodfiber3[msbprodinv]; } diff --git a/include/SigintHandler.hpp b/include/SigintHandler.hpp index 84836e7..64d2d54 100644 --- a/include/SigintHandler.hpp +++ b/include/SigintHandler.hpp @@ -19,7 +19,7 @@ class SigintHandler SigintHandler(const SigintHandler& other) = delete; /// Deleted assignment operator - SigintHandler& operator=(const SigintHandler& other) = delete; + auto operator=(const SigintHandler& other) -> SigintHandler& = delete; }; #endif // BKCRACK_SIGINTHANDLER_HPP diff --git a/include/Zip.hpp b/include/Zip.hpp index 2bd2e8c..861c2b2 100644 --- a/include/Zip.hpp +++ b/include/Zip.hpp @@ -89,33 +89,33 @@ class Zip /// \brief Get the current entry /// \pre The iterator must be valid - const Entry& operator*() const + auto operator*() const -> const Entry& { return *m_entry; } /// \brief Access a member of the current entry /// \pre The iterator must be valid - const Entry* operator->() const + auto operator->() const -> const Entry* { return &(*m_entry); } /// \brief Read the next central directory record if any or assign end-of-stream iterator /// \pre The iterator must be valid - Iterator& operator++(); + auto operator++() -> Iterator&; /// \copydoc operator++ - Iterator operator++(int); + auto operator++(int) -> Iterator; /// Test if iterators are equivalent, i.e. both are end-of-stream or both are valid - bool operator==(const Zip::Iterator& other) const + auto operator==(const Zip::Iterator& other) const -> bool { return (m_is == nullptr) == (other.m_is == nullptr); } /// Test if iterators are not equivalent - bool operator!=(const Zip::Iterator& other) const + auto operator!=(const Zip::Iterator& other) const -> bool { return !(*this == other); } @@ -135,24 +135,24 @@ class Zip explicit Zip(const std::string& filename); /// Get an iterator pointing to the first entry - Iterator begin() const + auto begin() const -> Iterator { return Iterator{*this}; } /// Get an end-of-stream iterator - Iterator end() const + auto end() const -> Iterator { return Iterator{}; } /// \brief Get the first entry having the given name /// \exception Error if the archive does not contain an entry with the given name - Entry operator[](const std::string& name) const; + auto operator[](const std::string& name) const -> Entry; /// \brief Get the entry at the given index /// \exception Error if the index is out of bounds - Entry operator[](std::size_t index) const; + auto operator[](std::size_t index) const -> Entry; /// \brief Check that the given entry uses the expected encryption algorithm /// \exception Error if the given entry does not use the expected encryption algorithm @@ -160,12 +160,12 @@ class Zip /// \brief Set the underlying stream's input position indicator at the beginning the given entry's raw data /// \exception Error if the given entry's data is not at the expected offset - std::istream& seek(const Entry& entry) const; + auto seek(const Entry& entry) const -> std::istream&; /// \brief Load at most \a count bytes of the given entry's raw data /// \exception Error if the given entry's data is not at the expected offset - std::vector load(const Entry& entry, - std::size_t count = std::numeric_limits::max()) const; + auto load(const Entry& entry, std::size_t count = std::numeric_limits::max()) const + -> std::vector; /// \brief Copy the zip file into \a os changing the encrypted data using the given keys /// \exception Error if the archive is not a valid zip archive diff --git a/include/Zreduction.hpp b/include/Zreduction.hpp index a9b74cc..19ab1f9 100644 --- a/include/Zreduction.hpp +++ b/include/Zreduction.hpp @@ -18,10 +18,10 @@ class Zreduction void generate(); /// \return the generated Zi[2,32) values - const std::vector& getCandidates() const; + auto getCandidates() const -> const std::vector&; /// \return the index of the Zi[2,32) values relative to keystream - std::size_t getIndex() const; + auto getIndex() const -> std::size_t; private: const std::vector& keystream; diff --git a/include/file.hpp b/include/file.hpp index df94eba..a2cb0ad 100644 --- a/include/file.hpp +++ b/include/file.hpp @@ -36,17 +36,17 @@ class FileError : public BaseError /// \brief Open an input file stream /// \exception FileError if the file cannot be opened -std::ifstream openInput(const std::string& filename); +auto openInput(const std::string& filename) -> std::ifstream; /// Load at most \a size bytes from an input stream -std::vector loadStream(std::istream& is, std::size_t size); +auto loadStream(std::istream& is, std::size_t size) -> std::vector; /// \brief Load at most \a size bytes from a file /// \exception FileError if the file cannot be opened -std::vector loadFile(const std::string& filename, std::size_t size); +auto loadFile(const std::string& filename, std::size_t size) -> std::vector; /// \brief Open an output file stream /// \exception FileError if the file cannot be opened -std::ofstream openOutput(const std::string& filename); +auto openOutput(const std::string& filename) -> std::ofstream; #endif // BKCRACK_FILE_HPP diff --git a/include/log.hpp b/include/log.hpp index bdaea9d..f6351b3 100644 --- a/include/log.hpp +++ b/include/log.hpp @@ -7,12 +7,12 @@ /// \brief Output stream manipulators /// Insert the current local time into the output stream -std::ostream& put_time(std::ostream& os); +auto put_time(std::ostream& os) -> std::ostream&; class Keys; // forward declaration /// \brief Insert a representation of keys into the stream \a os /// \relates Keys -std::ostream& operator<<(std::ostream& os, const Keys& keys); +auto operator<<(std::ostream& os, const Keys& keys) -> std::ostream&; #endif // BKCRACK_LOG_HPP diff --git a/include/password.hpp b/include/password.hpp index 58cc34e..cd56d63 100644 --- a/include/password.hpp +++ b/include/password.hpp @@ -85,8 +85,8 @@ class Recovery /// \return A vector of passwords associated with the given keys. /// A vector is needed instead of a single string because there can be /// collisions (i.e. several passwords for the same keys). -std::vector recoverPassword(const Keys& keys, const std::vector& charset, - std::size_t minLength, std::size_t maxLength, std::string& start, int jobs, - bool exhaustive, Progress& progress); +auto recoverPassword(const Keys& keys, const std::vector& charset, std::size_t minLength, + std::size_t maxLength, std::string& start, int jobs, bool exhaustive, Progress& progress) + -> std::vector; #endif // BKCRACK_PASSWORD_HPP diff --git a/include/types.hpp b/include/types.hpp index f855886..2d3eb21 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -21,13 +21,13 @@ class BaseError : public std::runtime_error // utility functions /// \return the least significant byte of x -constexpr std::uint8_t lsb(std::uint32_t x) +constexpr auto lsb(std::uint32_t x) -> std::uint8_t { return x; } /// \return the most significant byte of x -constexpr std::uint8_t msb(std::uint32_t x) +constexpr auto msb(std::uint32_t x) -> std::uint8_t { return x >> 24; } diff --git a/src/Arguments.cpp b/src/Arguments.cpp index b3feec2..b81af73 100644 --- a/src/Arguments.cpp +++ b/src/Arguments.cpp @@ -12,7 +12,7 @@ namespace { -std::bitset<256> charRange(char first, char last) +auto charRange(char first, char last) -> std::bitset<256> { std::bitset<256> bitset; @@ -41,17 +41,17 @@ auto translateIntParseError(F&& f, const std::string& value) } } -int parseInt(const std::string& value) +auto parseInt(const std::string& value) -> int { return translateIntParseError([](const std::string& value) { return std::stoi(value, nullptr, 0); }, value); } -std::size_t parseSize(const std::string& value) +auto parseSize(const std::string& value) -> std::size_t { return translateIntParseError([](const std::string& value) { return std::stoull(value, nullptr, 0); }, value); } -std::variant parseInterval(const std::string& value) +auto parseInterval(const std::string& value) -> std::variant { const std::string separator = ".."; @@ -145,7 +145,7 @@ Arguments::Arguments(int argc, const char* argv[]) throw Error("--bruteforce parameter is missing (required by --length)"); } -Data Arguments::loadData() const +auto Arguments::loadData() const -> Data { // load known plaintext std::vector plaintext; @@ -188,12 +188,12 @@ Data Arguments::loadData() const extraPlaintextWithCheckByte.value_or(extraPlaintext)); } -Arguments::LengthInterval Arguments::LengthInterval::operator&(const Arguments::LengthInterval& other) const +auto Arguments::LengthInterval::operator&(const Arguments::LengthInterval& other) const -> Arguments::LengthInterval { return {std::max(minLength, other.minLength), std::min(maxLength, other.maxLength)}; } -bool Arguments::finished() const +auto Arguments::finished() const -> bool { return m_current == m_end; } @@ -309,7 +309,7 @@ void Arguments::parseArgument() } } -std::string Arguments::readString(const std::string& description) +auto Arguments::readString(const std::string& description) -> std::string { if (finished()) throw Error("expected " + description + ", got nothing"); @@ -317,7 +317,7 @@ std::string Arguments::readString(const std::string& description) return *m_current++; } -Arguments::Option Arguments::readOption(const std::string& description) +auto Arguments::readOption(const std::string& description) -> Arguments::Option { // clang-format off #define PAIR(string, option) {#string, Option::option} @@ -363,17 +363,17 @@ Arguments::Option Arguments::readOption(const std::string& description) return it->second; } -int Arguments::readInt(const std::string& description) +auto Arguments::readInt(const std::string& description) -> int { return parseInt(readString(description)); } -std::size_t Arguments::readSize(const std::string& description) +auto Arguments::readSize(const std::string& description) -> std::size_t { return parseSize(readString(description)); } -std::vector Arguments::readHex(const std::string& description) +auto Arguments::readHex(const std::string& description) -> std::vector { std::string str = readString(description); @@ -389,7 +389,7 @@ std::vector Arguments::readHex(const std::string& description) return data; } -std::uint32_t Arguments::readKey(const std::string& description) +auto Arguments::readKey(const std::string& description) -> std::uint32_t { std::string str = readString(description); @@ -401,7 +401,7 @@ std::uint32_t Arguments::readKey(const std::string& description) return static_cast(std::stoul(str, nullptr, 16)); } -std::vector Arguments::readCharset() +auto Arguments::readCharset() -> std::vector { const std::bitset<256> lowercase = charRange('a', 'z'); const std::bitset<256> uppercase = charRange('A', 'Z'); diff --git a/src/Attack.cpp b/src/Attack.cpp index 31614b7..d626115 100644 --- a/src/Attack.cpp +++ b/src/Attack.cpp @@ -177,8 +177,8 @@ void Attack::testXlist() progress.state = Progress::State::EarlyExit; } -std::vector attack(const Data& data, const std::vector& zi_2_32_vector, int& start, - std::size_t index, int jobs, const bool exhaustive, Progress& progress) +auto attack(const Data& data, const std::vector& zi_2_32_vector, int& start, std::size_t index, int jobs, + const bool exhaustive, Progress& progress) -> std::vector { const std::uint32_t* candidates = zi_2_32_vector.data(); const auto size = static_cast(zi_2_32_vector.size()); diff --git a/src/Data.cpp b/src/Data.cpp index fe4c2c2..acfd4ca 100644 --- a/src/Data.cpp +++ b/src/Data.cpp @@ -11,12 +11,12 @@ namespace struct Range { - std::size_t size() const + auto size() const -> std::size_t { return std::distance(begin, end); } - bool operator<(const Range& other) const + auto operator<(const Range& other) const -> bool { return size() < other.size(); } diff --git a/src/Zip.cpp b/src/Zip.cpp index c0ec6b8..7772589 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -11,7 +11,7 @@ namespace { template -std::istream& read(std::istream& is, T& x) +auto read(std::istream& is, T& x) -> std::istream& { static_assert(N <= sizeof(T), "read requires output type to have at least N bytes"); @@ -23,14 +23,14 @@ std::istream& read(std::istream& is, T& x) return is; } -std::istream& read(std::istream& is, std::string& string, std::size_t length) +auto read(std::istream& is, std::string& string, std::size_t length) -> std::istream& { string.resize(length); return is.read(string.data(), string.size()); } template -std::ostream& write(std::ostream& os, const T& x) +auto write(std::ostream& os, const T& x) -> std::ostream& { static_assert(N <= sizeof(T), "write requires input type to have at least N bytes"); @@ -50,13 +50,13 @@ enum class Signature : std::uint32_t Eocd = 0x06054b50 }; -bool checkSignature(std::istream& is, const Signature& signature) +auto checkSignature(std::istream& is, const Signature& signature) -> bool { std::uint32_t sig; return read(is, sig) && sig == static_cast(signature); } -std::uint64_t findCentralDirectoryOffset(std::istream& is) +auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t { std::uint64_t centralDirectoryOffset; @@ -137,7 +137,7 @@ Zip::Iterator::Iterator(const Zip& archive) ++(*this); } -Zip::Iterator& Zip::Iterator::operator++() +auto Zip::Iterator::operator++() -> Zip::Iterator& { if (!checkSignature(*m_is, Signature::CentralDirectoryHeader)) return *this = Iterator{}; @@ -251,7 +251,7 @@ Zip::Iterator& Zip::Iterator::operator++() return *this; } -Zip::Iterator Zip::Iterator::operator++(int) +auto Zip::Iterator::operator++(int) -> Zip::Iterator { auto copy = *this; ++(*this); @@ -272,7 +272,7 @@ Zip::Zip(const std::string& filename) { } -Zip::Entry Zip::operator[](const std::string& name) const +auto Zip::operator[](const std::string& name) const -> Zip::Entry { const auto it = std::find_if(begin(), end(), [&name](const Entry& entry) { return entry.name == name; }); @@ -282,7 +282,7 @@ Zip::Entry Zip::operator[](const std::string& name) const return *it; } -Zip::Entry Zip::operator[](std::size_t index) const +auto Zip::operator[](std::size_t index) const -> Zip::Entry { std::size_t nextIndex = 0; const auto it = std::find_if(begin(), end(), [&nextIndex, index](const Entry&) { return nextIndex++ == index; }); @@ -307,7 +307,7 @@ void Zip::checkEncryption(const Entry& entry, Encryption expected) } } -std::istream& Zip::seek(const Entry& entry) const +auto Zip::seek(const Entry& entry) const -> std::istream& { m_is.seekg(entry.offset, std::ios::beg); if (!checkSignature(m_is, Signature::LocalFileHeader)) @@ -324,7 +324,7 @@ std::istream& Zip::seek(const Entry& entry) const return m_is; } -std::vector Zip::load(const Entry& entry, std::size_t count) const +auto Zip::load(const Entry& entry, std::size_t count) const -> std::vector { return loadStream(seek(entry), std::min(entry.packedSize, static_cast(count))); } diff --git a/src/Zreduction.cpp b/src/Zreduction.cpp index 2ea41c6..b4ed926 100644 --- a/src/Zreduction.cpp +++ b/src/Zreduction.cpp @@ -117,12 +117,12 @@ void Zreduction::generate() } } -const std::vector& Zreduction::getCandidates() const +auto Zreduction::getCandidates() const -> const std::vector& { return zi_vector; } -std::size_t Zreduction::getIndex() const +auto Zreduction::getIndex() const -> std::size_t { return index; } diff --git a/src/file.cpp b/src/file.cpp index 8c6944d..840dbf9 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -5,7 +5,7 @@ FileError::FileError(const std::string& description) { } -std::ifstream openInput(const std::string& filename) +auto openInput(const std::string& filename) -> std::ifstream { if (std::ifstream is = std::ifstream(filename, std::ios::binary)) return is; @@ -13,7 +13,7 @@ std::ifstream openInput(const std::string& filename) throw FileError("could not open input file " + filename); } -std::vector loadStream(std::istream& is, std::size_t size) +auto loadStream(std::istream& is, std::size_t size) -> std::vector { std::vector content; std::istreambuf_iterator it(is); @@ -23,13 +23,13 @@ std::vector loadStream(std::istream& is, std::size_t size) return content; } -std::vector loadFile(const std::string& filename, std::size_t size) +auto loadFile(const std::string& filename, std::size_t size) -> std::vector { std::ifstream is = openInput(filename); return loadStream(is, size); } -std::ofstream openOutput(const std::string& filename) +auto openOutput(const std::string& filename) -> std::ofstream { if (std::ofstream os = std::ofstream(filename, std::ios::binary)) return os; diff --git a/src/log.cpp b/src/log.cpp index f7a8e21..54037ff 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -5,13 +5,13 @@ #include #include -std::ostream& put_time(std::ostream& os) +auto put_time(std::ostream& os) -> std::ostream& { const std::time_t t = std::time(nullptr); return os << std::put_time(std::localtime(&t), "%T"); } -std::ostream& operator<<(std::ostream& os, const Keys& keys) +auto operator<<(std::ostream& os, const Keys& keys) -> std::ostream& { const auto flagsBefore = os.setf(std::ios::hex, std::ios::basefield); const auto fillBefore = os.fill('0'); diff --git a/src/main.cpp b/src/main.cpp index c160116..474d564 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -102,7 +102,7 @@ void decipher(std::istream& is, std::size_t size, std::size_t discard, std::ostr } // namespace -int main(int argc, const char* argv[]) +auto main(int argc, const char* argv[]) -> int try { // enable virtual terminal support on Windows, no-op on other platforms @@ -359,7 +359,7 @@ catch (const BaseError& e) namespace { -std::string getEncryptionDescription(Zip::Encryption encryption) +auto getEncryptionDescription(Zip::Encryption encryption) -> std::string { switch (encryption) { @@ -375,7 +375,7 @@ std::string getEncryptionDescription(Zip::Encryption encryption) return ""; } -std::string getCompressionDescription(Zip::Compression compression) +auto getCompressionDescription(Zip::Compression compression) -> std::string { switch (compression) { diff --git a/src/password.cpp b/src/password.cpp index 4be65e1..96380d1 100644 --- a/src/password.cpp +++ b/src/password.cpp @@ -386,9 +386,9 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c } // namespace -std::vector recoverPassword(const Keys& keys, const std::vector& charset, - std::size_t minLength, std::size_t maxLength, std::string& start, int jobs, - bool exhaustive, Progress& progress) +auto recoverPassword(const Keys& keys, const std::vector& charset, std::size_t minLength, + std::size_t maxLength, std::string& start, int jobs, bool exhaustive, Progress& progress) + -> std::vector { std::vector solutions; std::mutex solutionsMutex; From aa9a625c7ff30acf5389f5b4629ec0b2166c14c4 Mon Sep 17 00:00:00 2001 From: kimci86 Date: Sun, 25 Feb 2024 17:50:28 +0100 Subject: [PATCH 17/19] More uniform initialization and AAA style --- include/ConsoleProgress.hpp | 2 +- include/Progress.hpp | 2 +- include/types.hpp | 4 +- src/Arguments.cpp | 119 ++++++++++++++++----------------- src/Attack.cpp | 56 ++++++++-------- src/ConsoleProgress.cpp | 16 ++--- src/Crc32Tab.cpp | 8 +-- src/Data.cpp | 46 ++++++------- src/Keys.cpp | 8 +-- src/KeystreamTab.cpp | 5 +- src/MultTab.cpp | 6 +- src/VirtualTerminalSupport.cpp | 2 +- src/Zip.cpp | 118 ++++++++++++++++---------------- src/Zreduction.cpp | 45 +++++++------ src/file.cpp | 18 ++--- src/log.cpp | 2 +- src/main.cpp | 67 +++++++++---------- src/password.cpp | 102 ++++++++++++++-------------- src/types.cpp | 2 +- 19 files changed, 314 insertions(+), 314 deletions(-) diff --git a/include/ConsoleProgress.hpp b/include/ConsoleProgress.hpp index 3289da0..ca42304 100644 --- a/include/ConsoleProgress.hpp +++ b/include/ConsoleProgress.hpp @@ -13,7 +13,7 @@ class ConsoleProgress : public Progress public: /// Start a thread to print progress explicit ConsoleProgress(std::ostream& os, - const std::chrono::milliseconds& interval = std::chrono::milliseconds(200)); + const std::chrono::milliseconds& interval = std::chrono::milliseconds{200}); /// Notify and stop the printing thread ~ConsoleProgress(); diff --git a/include/Progress.hpp b/include/Progress.hpp index 7e6f64b..6cd6d42 100644 --- a/include/Progress.hpp +++ b/include/Progress.hpp @@ -25,7 +25,7 @@ class Progress template void log(F f) { - const std::scoped_lock lock{m_os_mutex}; + const auto lock = std::scoped_lock{m_os_mutex}; f(m_os); } diff --git a/include/types.hpp b/include/types.hpp index 2d3eb21..439f114 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -36,7 +36,7 @@ constexpr auto msb(std::uint32_t x) -> std::uint8_t /// Constant value for bit masking template -constexpr std::uint32_t mask = ~0u << begin & ~0u >> (32 - end); +constexpr auto mask = std::uint32_t{~0u << begin & ~0u >> (32 - end)}; /// \brief Maximum difference between 32-bits integers A and B[x,32) /// knowing that A = B + b and b is a byte. @@ -48,6 +48,6 @@ constexpr std::uint32_t mask = ~0u << begin & ~0u >> (32 - end); /// A - B[x,32) = B[0,x) + b /// A - B[x,32) <= 0xffffffff[0,x) + 0xff template -constexpr std::uint32_t maxdiff = mask<0, x> + 0xff; +constexpr auto maxdiff = std::uint32_t{mask<0, x> + 0xff}; #endif // BKCRACK_TYPES_HPP diff --git a/src/Arguments.cpp b/src/Arguments.cpp index b81af73..164cbb2 100644 --- a/src/Arguments.cpp +++ b/src/Arguments.cpp @@ -14,7 +14,7 @@ namespace auto charRange(char first, char last) -> std::bitset<256> { - std::bitset<256> bitset; + auto bitset = std::bitset<256>{}; do { @@ -33,11 +33,11 @@ auto translateIntParseError(F&& f, const std::string& value) } catch (const std::invalid_argument&) { - throw Arguments::Error("expected an integer, got \"" + value + "\""); + throw Arguments::Error{"expected an integer, got \"" + value + "\""}; } catch (const std::out_of_range&) { - throw Arguments::Error("integer value " + value + " is out of range"); + throw Arguments::Error{"integer value " + value + " is out of range"}; } } @@ -53,11 +53,11 @@ auto parseSize(const std::string& value) -> std::size_t auto parseInterval(const std::string& value) -> std::variant { - const std::string separator = ".."; + const auto separator = std::string{".."}; if (const auto minEnd = value.find(separator); minEnd != std::string::npos) { - Arguments::LengthInterval interval; + auto interval = Arguments::LengthInterval{}; if (0 < minEnd) interval.minLength = parseSize(value.substr(0, minEnd)); @@ -74,7 +74,7 @@ auto parseInterval(const std::string& value) -> std::variant(Data::encryptionHeaderSize); + constexpr auto minimumOffset = -static_cast(Data::encryptionHeaderSize); if (offset < minimumOffset) - throw Error("plaintext offset " + std::to_string(offset) + " is too small (minimum is " + - std::to_string(minimumOffset) + ")"); + throw Error{"plaintext offset " + std::to_string(offset) + " is too small (minimum is " + + std::to_string(minimumOffset) + ")"}; } if (decipheredFile && !cipherFile && !cipherIndex) - throw Error("-c or --cipher-index parameter is missing (required by -d)"); + throw Error{"-c or --cipher-index parameter is missing (required by -d)"}; if (decipheredFile && !cipherArchive && decipheredFile == cipherFile) - throw Error("-c and -d parameters must point to different files"); + throw Error{"-c and -d parameters must point to different files"}; if (changePassword && !cipherArchive) - throw Error("-C parameter is missing (required by -U)"); + throw Error{"-C parameter is missing (required by -U)"}; if (changePassword && changePassword->unlockedArchive == cipherArchive) - throw Error("-C and -U parameters must point to different files"); + throw Error{"-C and -U parameters must point to different files"}; if (changeKeys && !cipherArchive) - throw Error("-C parameter is missing (required by --change-keys)"); + throw Error{"-C parameter is missing (required by --change-keys)"}; if (changeKeys && changeKeys->unlockedArchive == cipherArchive) - throw Error("-C and --change-keys parameters must point to different files"); + throw Error{"-C and --change-keys parameters must point to different files"}; if (length && !bruteforce) - throw Error("--bruteforce parameter is missing (required by --length)"); + throw Error{"--bruteforce parameter is missing (required by --length)"}; } auto Arguments::loadData() const -> Data { // load known plaintext - std::vector plaintext; + auto plaintext = std::vector{}; if (plainArchive) { const auto archive = Zip{*plainArchive}; @@ -160,14 +160,14 @@ auto Arguments::loadData() const -> Data plaintext = loadFile(*plainFile, plainFilePrefix); // load ciphertext needed by the attack - std::size_t needed = Data::encryptionHeaderSize; + auto needed = Data::encryptionHeaderSize; if (!plaintext.empty()) needed = std::max(needed, Data::encryptionHeaderSize + offset + plaintext.size()); if (!extraPlaintext.empty()) needed = std::max(needed, Data::encryptionHeaderSize + extraPlaintext.rbegin()->first + 1); - std::vector ciphertext; - std::optional> extraPlaintextWithCheckByte; + auto ciphertext = std::vector{}; + auto extraPlaintextWithCheckByte = std::optional>{}; if (cipherArchive) { const auto archive = Zip{*cipherArchive}; @@ -184,8 +184,7 @@ auto Arguments::loadData() const -> Data else ciphertext = loadFile(*cipherFile, needed); - return Data(std::move(ciphertext), std::move(plaintext), offset, - extraPlaintextWithCheckByte.value_or(extraPlaintext)); + return {std::move(ciphertext), std::move(plaintext), offset, extraPlaintextWithCheckByte.value_or(extraPlaintext)}; } auto Arguments::LengthInterval::operator&(const Arguments::LengthInterval& other) const -> Arguments::LengthInterval @@ -228,8 +227,8 @@ void Arguments::parseArgument() break; case Option::extraPlaintext: { - int i = readInt("offset"); - for (const std::uint8_t b : readHex("data")) + auto i = readInt("offset"); + for (const auto b : readHex("data")) extraPlaintext[i++] = b; break; } @@ -255,7 +254,7 @@ void Arguments::parseArgument() changePassword = {readString("unlockedzip"), readString("password")}; break; case Option::changeKeys: - changeKeys = {readString("unlockedzip"), Keys{readKey("X"), readKey("Y"), readKey("Z")}}; + changeKeys = {readString("unlockedzip"), {readKey("X"), readKey("Y"), readKey("Z")}}; break; case Option::bruteforce: bruteforce = readCharset(); @@ -312,7 +311,7 @@ void Arguments::parseArgument() auto Arguments::readString(const std::string& description) -> std::string { if (finished()) - throw Error("expected " + description + ", got nothing"); + throw Error{"expected " + description + ", got nothing"}; return *m_current++; } @@ -323,7 +322,7 @@ auto Arguments::readOption(const std::string& description) -> Arguments::Option #define PAIR(string, option) {#string, Option::option} #define PAIRS(short, long, option) PAIR(short, option), PAIR(long, option) - static const std::map stringToOption = { + static const auto stringToOption = std::map{ PAIRS(-c, --cipher-file, cipherFile), PAIR ( --cipher-index, cipherIndex), PAIRS(-C, --cipher-zip, cipherArchive), @@ -356,9 +355,9 @@ auto Arguments::readOption(const std::string& description) -> Arguments::Option #undef PAIR #undef PAIRS - const std::string str = readString(description); + const auto str = readString(description); if (const auto it = stringToOption.find(str); it == stringToOption.end()) - throw Error("unknown option " + str); + throw Error{"unknown option " + str}; else return it->second; } @@ -375,15 +374,15 @@ auto Arguments::readSize(const std::string& description) -> std::size_t auto Arguments::readHex(const std::string& description) -> std::vector { - std::string str = readString(description); + const auto str = readString(description); if (str.size() % 2) - throw Error("expected an even-length string, got " + str); - if (!std::all_of(str.begin(), str.end(), [](unsigned char c) { return std::isxdigit(c); })) - throw Error("expected " + description + " in hexadecimal, got " + str); + throw Error{"expected an even-length string, got " + str}; + if (!std::all_of(str.begin(), str.end(), [](char c) { return std::isxdigit(static_cast(c)); })) + throw Error{"expected " + description + " in hexadecimal, got " + str}; - std::vector data; - for (std::size_t i = 0; i < str.length(); i += 2) + auto data = std::vector{}; + for (auto i = std::size_t{}; i < str.length(); i += 2) data.push_back(static_cast(std::stoul(str.substr(i, 2), nullptr, 16))); return data; @@ -391,30 +390,30 @@ auto Arguments::readHex(const std::string& description) -> std::vector std::uint32_t { - std::string str = readString(description); + const auto str = readString(description); if (str.size() > 8) - throw Error("expected a string of length 8 or less, got " + str); - if (!std::all_of(str.begin(), str.end(), [](unsigned char c) { return std::isxdigit(c); })) - throw Error("expected " + description + " in hexadecimal, got " + str); + throw Error{"expected a string of length 8 or less, got " + str}; + if (!std::all_of(str.begin(), str.end(), [](char c) { return std::isxdigit(static_cast(c)); })) + throw Error{"expected " + description + " in hexadecimal, got " + str}; return static_cast(std::stoul(str, nullptr, 16)); } auto Arguments::readCharset() -> std::vector { - const std::bitset<256> lowercase = charRange('a', 'z'); - const std::bitset<256> uppercase = charRange('A', 'Z'); - const std::bitset<256> digits = charRange('0', '9'); - const std::bitset<256> alphanum = lowercase | uppercase | digits; - const std::bitset<256> printable = charRange(' ', '~'); - const std::bitset<256> punctuation = printable & ~alphanum; - - const std::string charsetArg = readString("charset"); + const auto lowercase = charRange('a', 'z'); + const auto uppercase = charRange('A', 'Z'); + const auto digits = charRange('0', '9'); + const auto alphanum = lowercase | uppercase | digits; + const auto printable = charRange(' ', '~'); + const auto punctuation = printable & ~alphanum; + + const auto charsetArg = readString("charset"); if (charsetArg.empty()) - throw Error("the charset for password recovery is empty"); + throw Error{"the charset for password recovery is empty"}; - std::bitset<256> charset; + auto charset = std::bitset<256>{}; for (auto it = charsetArg.begin(); it != charsetArg.end(); ++it) { @@ -439,15 +438,15 @@ auto Arguments::readCharset() -> std::vector case '?': charset.set('?'); break; // clang-format on default: - throw Error(std::string("unknown charset ?") + *it); + throw Error{std::string{"unknown charset ?"} + *it}; } } else charset.set(*it); } - std::vector result; - for (int c = 0; c < 256; c++) + auto result = std::vector{}; + for (auto c = 0; c < 256; c++) if (charset[c]) result.push_back(c); diff --git a/src/Attack.cpp b/src/Attack.cpp index d626115..b37926a 100644 --- a/src/Attack.cpp +++ b/src/Attack.cpp @@ -11,12 +11,12 @@ Attack::Attack(const Data& data, std::size_t index, std::vector& solutions, std::mutex& solutionsMutex, bool exhaustive, Progress& progress) -: data(data) -, index(index + 1 - Attack::contiguousSize) -, solutions(solutions) -, solutionsMutex(solutionsMutex) -, exhaustive(exhaustive) -, progress(progress) +: data{data} +, index{index + 1 - Attack::contiguousSize} +, solutions{solutions} +, solutionsMutex{solutionsMutex} +, exhaustive{exhaustive} +, progress{progress} { } @@ -31,10 +31,10 @@ void Attack::exploreZlists(int i) if (i != 0) // the Z-list is not complete so generate Z{i-1}[2,32) values { // get Z{i-1}[10,32) from CRC32^-1 - const std::uint32_t zim1_10_32 = Crc32Tab::getZim1_10_32(zlist[i]); + const auto zim1_10_32 = Crc32Tab::getZim1_10_32(zlist[i]); // get Z{i-1}[2,16) values from keystream byte k{i-1} and Z{i-1}[10,16) - for (const std::uint32_t zim1_2_16 : KeystreamTab::getZi_2_16_vector(data.keystream[index + i - 1], zim1_10_32)) + for (const auto zim1_2_16 : KeystreamTab::getZi_2_16_vector(data.keystream[index + i - 1], zim1_10_32)) { // add Z{i-1}[2,32) to the Z-list zlist[i - 1] = zim1_10_32 | zim1_2_16; @@ -53,10 +53,10 @@ void Attack::exploreZlists(int i) else // the Z-list is complete so iterate over possible Y values { // guess Y7[8,24) and keep prod == (Y7[8,32) - 1) * mult^-1 - for (std::uint32_t y7_8_24 = 0, prod = (MultTab::getMultinv(msb(ylist[7])) << 24) - MultTab::multInv; + for (auto y7_8_24 = std::uint32_t{}, prod = (MultTab::getMultinv(msb(ylist[7])) << 24) - MultTab::multInv; y7_8_24 < 1 << 24; y7_8_24 += 1 << 8, prod += MultTab::multInv << 8) // get possible Y7[0,8) values - for (const std::uint8_t y7_0_8 : MultTab::getMsbProdFiber3(msb(ylist[6]) - msb(prod))) + for (const auto y7_0_8 : MultTab::getMsbProdFiber3(msb(ylist[6]) - msb(prod))) // filter Y7[0,8) using Y6[24,32) if (prod + MultTab::getMultinv(y7_0_8) - (ylist[6] & mask<24, 32>) <= maxdiff<24>) { @@ -70,14 +70,14 @@ void Attack::exploreYlists(int i) { if (i != 3) // the Y-list is not complete so generate Y{i-1} values { - const std::uint32_t fy = (ylist[i] - 1) * MultTab::multInv; - const std::uint32_t ffy = (fy - 1) * MultTab::multInv; + const auto fy = (ylist[i] - 1) * MultTab::multInv; + const auto ffy = (fy - 1) * MultTab::multInv; // get possible LSB(Xi) - for (const std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (ylist[i - 2] & mask<24, 32>)))) + for (const auto xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (ylist[i - 2] & mask<24, 32>)))) { // compute corresponding Y{i-1} - const std::uint32_t yim1 = fy - xi_0_8; + const auto yim1 = fy - xi_0_8; // filter values with Y{i-2}[24,32) if (ffy - MultTab::getMultinv(xi_0_8) - (ylist[i - 2] & mask<24, 32>) <= maxdiff<24> && @@ -100,22 +100,22 @@ void Attack::exploreYlists(int i) void Attack::testXlist() { // compute X7 - for (int i = 5; i <= 7; i++) + for (auto i = 5; i <= 7; i++) xlist[i] = (Crc32Tab::crc32(xlist[i - 1], data.plaintext[index + i - 1]) & mask<8, 32>) // discard the LSB | lsb(xlist[i]); // set the LSB // compute X3 - std::uint32_t x = xlist[7]; - for (int i = 6; i >= 3; i--) + auto x = xlist[7]; + for (auto i = 6; i >= 3; i--) x = Crc32Tab::crc32inv(x, data.plaintext[index + i]); // check that X3 fits with Y1[26,32) - const std::uint32_t y1_26_32 = Crc32Tab::getYi_24_32(zlist[1], zlist[0]) & mask<26, 32>; + const auto y1_26_32 = Crc32Tab::getYi_24_32(zlist[1], zlist[0]) & mask<26, 32>; if (((ylist[3] - 1) * MultTab::multInv - lsb(x) - 1) * MultTab::multInv - y1_26_32 > maxdiff<26>) return; // decipher and filter by comparing with remaining contiguous plaintext forward - Keys keysForward(xlist[7], ylist[7], zlist[7]); + auto keysForward = Keys{xlist[7], ylist[7], zlist[7]}; keysForward.update(data.plaintext[index + 7]); for (auto p = data.plaintext.begin() + index + 8, c = data.ciphertext.begin() + data.offset + index + 8; p != data.plaintext.end(); ++p, ++c) @@ -125,10 +125,10 @@ void Attack::testXlist() keysForward.update(*p); } - std::size_t indexForward = data.offset + data.plaintext.size(); + auto indexForward = data.offset + data.plaintext.size(); // and also backward - Keys keysBackward(x, ylist[3], zlist[3]); + auto keysBackward = Keys{x, ylist[3], zlist[3]}; for (auto p = std::reverse_iterator{data.plaintext.begin() + index + 3}, c = std::reverse_iterator{data.ciphertext.begin() + data.offset + index + 3}; p != data.plaintext.rend(); ++p, ++c) @@ -138,12 +138,12 @@ void Attack::testXlist() return; } - std::size_t indexBackward = data.offset; + auto indexBackward = data.offset; // continue filtering with extra known plaintext for (const auto& [extraIndex, extraByte] : data.extraPlaintext) { - std::uint8_t p; + auto p = std::uint8_t{}; if (extraIndex < indexBackward) { keysBackward.updateBackward(data.ciphertext, indexBackward, extraIndex); @@ -180,12 +180,12 @@ void Attack::testXlist() auto attack(const Data& data, const std::vector& zi_2_32_vector, int& start, std::size_t index, int jobs, const bool exhaustive, Progress& progress) -> std::vector { - const std::uint32_t* candidates = zi_2_32_vector.data(); - const auto size = static_cast(zi_2_32_vector.size()); + const auto* candidates = zi_2_32_vector.data(); + const auto size = static_cast(zi_2_32_vector.size()); - std::vector solutions; - std::mutex solutionsMutex; - Attack worker(data, index, solutions, solutionsMutex, exhaustive, progress); + auto solutions = std::vector{}; + auto solutionsMutex = std::mutex{}; + auto worker = Attack{data, index, solutions, solutionsMutex, exhaustive, progress}; progress.done = start; progress.total = size; diff --git a/src/ConsoleProgress.cpp b/src/ConsoleProgress.cpp index ce15b26..6d774f0 100644 --- a/src/ConsoleProgress.cpp +++ b/src/ConsoleProgress.cpp @@ -13,7 +13,7 @@ ConsoleProgress::ConsoleProgress(std::ostream& os, const std::chrono::millisecon ConsoleProgress::~ConsoleProgress() { { - const std::scoped_lock lock{m_in_destructor_mutex}; + const auto lock = std::scoped_lock{m_in_destructor_mutex}; m_in_destructor = true; } @@ -23,18 +23,18 @@ ConsoleProgress::~ConsoleProgress() void ConsoleProgress::printerFunction() { - bool repeat = true; + auto repeat = true; // Give a small delay before the first time progress is printed so that // the running operation is likely to have initialized the total number of steps. { - std::unique_lock lock(m_in_destructor_mutex); - repeat = !m_in_destructor_cv.wait_for(lock, std::chrono::milliseconds(1), [this] { return m_in_destructor; }); + auto lock = std::unique_lock{m_in_destructor_mutex}; + repeat = !m_in_destructor_cv.wait_for(lock, std::chrono::milliseconds{1}, [this] { return m_in_destructor; }); } while (repeat) { - if (const int total = this->total.load()) + if (const auto total = this->total.load()) log( [done = done.load(), total](std::ostream& os) { @@ -48,11 +48,11 @@ void ConsoleProgress::printerFunction() os.flags(flagsBefore); }); - std::unique_lock lock(m_in_destructor_mutex); - repeat = !m_in_destructor_cv.wait_for(lock, m_interval, [this] { return m_in_destructor; }); + auto lock = std::unique_lock{m_in_destructor_mutex}; + repeat = !m_in_destructor_cv.wait_for(lock, m_interval, [this] { return m_in_destructor; }); } - if (const int total = this->total.load()) + if (const auto total = this->total.load()) log( [done = done.load(), total](std::ostream& os) { diff --git a/src/Crc32Tab.cpp b/src/Crc32Tab.cpp index 7bec4f1..010188a 100644 --- a/src/Crc32Tab.cpp +++ b/src/Crc32Tab.cpp @@ -5,13 +5,13 @@ const Crc32Tab Crc32Tab::instance; Crc32Tab::Crc32Tab() { // CRC32 polynomial representation - constexpr std::uint32_t crcPolynom = 0xedb88320; + constexpr auto crcPolynom = 0xedb88320; - for (int b = 0; b < 256; b++) + for (auto b = 0; b < 256; b++) { - std::uint32_t crc = b; + auto crc = static_cast(b); // compute CRC32 from the original definition - for (int i = 0; i < 8; i++) + for (auto i = 0; i < 8; i++) if (crc & 1) crc = crc >> 1 ^ crcPolynom; else diff --git a/src/Data.cpp b/src/Data.cpp index acfd4ca..2d8ff62 100644 --- a/src/Data.cpp +++ b/src/Data.cpp @@ -28,35 +28,35 @@ struct Range } // namespace Data::Error::Error(const std::string& description) -: BaseError("Data error", description) +: BaseError{"Data error", description} { } Data::Data(std::vector ciphertextArg, std::vector plaintextArg, int offsetArg, const std::map& extraPlaintextArg) -: ciphertext(std::move(ciphertextArg)) -, plaintext(std::move(plaintextArg)) +: ciphertext{std::move(ciphertextArg)} +, plaintext{std::move(plaintextArg)} { // validate lengths if (ciphertext.size() < Attack::attackSize) - throw Error("ciphertext is too small for an attack (minimum length is " + std::to_string(Attack::attackSize) + - ")"); + throw Error{"ciphertext is too small for an attack (minimum length is " + std::to_string(Attack::attackSize) + + ")"}; if (ciphertext.size() < plaintext.size()) - throw Error("ciphertext is smaller than plaintext"); + throw Error{"ciphertext is smaller than plaintext"}; // validate offsets - constexpr int minimumOffset = -static_cast(encryptionHeaderSize); + constexpr auto minimumOffset = -static_cast(encryptionHeaderSize); if (offsetArg < minimumOffset) - throw Error("plaintext offset " + std::to_string(offsetArg) + " is too small (minimum is " + - std::to_string(minimumOffset) + ")"); + throw Error{"plaintext offset " + std::to_string(offsetArg) + " is too small (minimum is " + + std::to_string(minimumOffset) + ")"}; if (ciphertext.size() < encryptionHeaderSize + offsetArg + plaintext.size()) - throw Error("plaintext offset " + std::to_string(offsetArg) + " is too large"); + throw Error{"plaintext offset " + std::to_string(offsetArg) + " is too large"}; if (!extraPlaintextArg.empty() && extraPlaintextArg.begin()->first < minimumOffset) - throw Error("extra plaintext offset " + std::to_string(extraPlaintextArg.begin()->first) + - " is too small (minimum is " + std::to_string(minimumOffset) + ")"); + throw Error{"extra plaintext offset " + std::to_string(extraPlaintextArg.begin()->first) + + " is too small (minimum is " + std::to_string(minimumOffset) + ")"}; if (!extraPlaintextArg.empty() && ciphertext.size() <= encryptionHeaderSize + extraPlaintextArg.rbegin()->first) - throw Error("extra plaintext offset " + std::to_string(extraPlaintextArg.rbegin()->first) + " is too large"); + throw Error{"extra plaintext offset " + std::to_string(extraPlaintextArg.rbegin()->first) + " is too large"}; // shift offsets to absolute values offset = encryptionHeaderSize + offsetArg; @@ -99,11 +99,11 @@ Data::Data(std::vector ciphertextArg, std::vector pl // find the longest contiguous sequence in extra plaintext and use is as contiguous plaintext if sensible { - Range range = {extraPlaintext.begin(), extraPlaintext.begin()}; // empty + auto range = Range{extraPlaintext.begin(), extraPlaintext.begin()}; // empty for (auto it = extraPlaintext.begin(); it != extraPlaintext.end();) { - Range current = {it, ++it}; + auto current = Range{it, ++it}; while (it != extraPlaintext.end() && it->first == (current.end - 1)->first + 1) current.end = ++it; @@ -112,11 +112,11 @@ Data::Data(std::vector ciphertextArg, std::vector pl if (plaintext.size() < range.size()) { - const std::size_t plaintextSize = plaintext.size(); - const std::size_t rangeOffset = range.begin->first; + const auto plaintextSize = plaintext.size(); + const auto rangeOffset = range.begin->first; // append last bytes from the range to contiguous plaintext - for (std::size_t i = plaintextSize; i < range.size(); i++) + for (auto i = plaintextSize; i < range.size(); i++) plaintext.push_back(range.begin[i].second); // remove those bytes from the range @@ -135,7 +135,7 @@ Data::Data(std::vector ciphertextArg, std::vector pl } // swap bytes between the former contiguous plaintext and the beginning of the range - for (std::size_t i = 0; i < plaintextSize; i++) + for (auto i = std::size_t{}; i < plaintextSize; i++) { range.begin[i].first = offset + i; std::swap(plaintext[i], range.begin[i].second); @@ -147,11 +147,11 @@ Data::Data(std::vector ciphertextArg, std::vector pl // check that there is enough known plaintext if (plaintext.size() < Attack::contiguousSize) - throw Error("not enough contiguous plaintext (" + std::to_string(plaintext.size()) + - " bytes available, minimum is " + std::to_string(Attack::contiguousSize) + ")"); + throw Error{"not enough contiguous plaintext (" + std::to_string(plaintext.size()) + + " bytes available, minimum is " + std::to_string(Attack::contiguousSize) + ")"}; if (plaintext.size() + extraPlaintext.size() < Attack::attackSize) - throw Error("not enough plaintext (" + std::to_string(plaintext.size() + extraPlaintext.size()) + - " bytes available, minimum is " + std::to_string(Attack::attackSize) + ")"); + throw Error{"not enough plaintext (" + std::to_string(plaintext.size() + extraPlaintext.size()) + + " bytes available, minimum is " + std::to_string(Attack::attackSize) + ")"}; // reorder remaining extra plaintext for filtering { diff --git a/src/Keys.cpp b/src/Keys.cpp index 64a8602..f2ad1b4 100644 --- a/src/Keys.cpp +++ b/src/Keys.cpp @@ -1,15 +1,15 @@ #include "Keys.hpp" Keys::Keys(std::uint32_t x, std::uint32_t y, std::uint32_t z) -: x(x) -, y(y) -, z(z) +: x{x} +, y{y} +, z{z} { } Keys::Keys(const std::string& password) { - for (const char p : password) + for (const auto p : password) update(p); } diff --git a/src/KeystreamTab.cpp b/src/KeystreamTab.cpp index c3a7dc1..25c84a3 100644 --- a/src/KeystreamTab.cpp +++ b/src/KeystreamTab.cpp @@ -4,9 +4,10 @@ const KeystreamTab KeystreamTab::instance; KeystreamTab::KeystreamTab() { - for (std::uint32_t z_2_16 = 0; z_2_16 < 1 << 16; z_2_16 += 4) + for (auto z_2_16 = std::uint32_t{}; z_2_16 < 1 << 16; z_2_16 += 4) { - const std::uint8_t k = lsb((z_2_16 | 2) * (z_2_16 | 3) >> 8); + const auto k = lsb((z_2_16 | 2) * (z_2_16 | 3) >> 8); + keystreamtab[z_2_16 >> 2] = k; keystreaminvfiltertab[k][z_2_16 >> 10].push_back(z_2_16); keystreaminvexists[k].set(z_2_16 >> 10); diff --git a/src/MultTab.cpp b/src/MultTab.cpp index f18a6d2..1f5ee34 100644 --- a/src/MultTab.cpp +++ b/src/MultTab.cpp @@ -4,9 +4,9 @@ const MultTab MultTab::instance; MultTab::MultTab() { - std::uint32_t prod = 0; // x * mult - std::uint32_t prodinv = 0; // x * mult^-1 - for (int x = 0; x < 256; x++, prod += mult, prodinv += multInv) + auto prod = std::uint32_t{}; // x * mult + auto prodinv = std::uint32_t{}; // x * mult^-1 + for (auto x = 0; x < 256; x++, prod += mult, prodinv += multInv) { multtab[x] = prod; multinvtab[x] = prodinv; diff --git a/src/VirtualTerminalSupport.cpp b/src/VirtualTerminalSupport.cpp index 49400ac..74c709a 100644 --- a/src/VirtualTerminalSupport.cpp +++ b/src/VirtualTerminalSupport.cpp @@ -12,7 +12,7 @@ class VirtualTerminalSupport::Impl : hStdOut{GetStdHandle(STD_OUTPUT_HANDLE)} , originalMode{[this] { - DWORD mode; + auto mode = DWORD{}; return GetConsoleMode(hStdOut, &mode) ? std::optional{mode} : std::nullopt; }()} { diff --git a/src/Zip.cpp b/src/Zip.cpp index 7772589..37f2d9f 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -16,8 +16,8 @@ auto read(std::istream& is, T& x) -> std::istream& static_assert(N <= sizeof(T), "read requires output type to have at least N bytes"); // We make no assumption about platform endianness. - x = T(); - for (std::size_t index = 0; index < N; index++) + x = T{}; + for (auto index = std::size_t{}; index < N; index++) x |= static_cast(is.get()) << (8 * index); return is; @@ -35,7 +35,7 @@ auto write(std::ostream& os, const T& x) -> std::ostream& static_assert(N <= sizeof(T), "write requires input type to have at least N bytes"); // We make no assumption about platform endianness. - for (std::size_t index = 0; index < N; index++) + for (auto index = std::size_t{}; index < N; index++) os.put(lsb(x >> (8 * index))); return os; @@ -52,18 +52,18 @@ enum class Signature : std::uint32_t auto checkSignature(std::istream& is, const Signature& signature) -> bool { - std::uint32_t sig; + auto sig = std::uint32_t{}; return read(is, sig) && sig == static_cast(signature); } auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t { - std::uint64_t centralDirectoryOffset; + auto centralDirectoryOffset = std::uint64_t{}; // find end of central directory signature { - std::uint32_t signature; - std::uint16_t commentLength = 0; + auto signature = std::uint32_t{}; + auto commentLength = std::uint16_t{}; do { is.seekg(-22 - commentLength, std::ios::end); @@ -71,40 +71,40 @@ auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t commentLength++ < mask<0, 16>); if (!is || signature != static_cast(Signature::Eocd)) - throw Zip::Error("could not find end of central directory signature"); + throw Zip::Error{"could not find end of central directory signature"}; } // read end of central directory record { - std::uint16_t disk; + auto disk = std::uint16_t{}; read(is, disk); is.seekg(10, std::ios::cur); read(is, centralDirectoryOffset); if (!is) - throw Zip::Error("could not read end of central directory record"); + throw Zip::Error{"could not read end of central directory record"}; if (disk != 0) - throw Zip::Error("split zip archives are not supported"); + throw Zip::Error{"split zip archives are not supported"}; } // look for Zip64 end of central directory locator is.seekg(-40, std::ios::cur); if (checkSignature(is, Signature::Zip64EocdLocator)) { - std::uint64_t zip64EndOfCentralDirectoryOffset; + auto zip64EndOfCentralDirectoryOffset = std::uint64_t{}; is.seekg(4, std::ios::cur); read(is, zip64EndOfCentralDirectoryOffset); if (!is) - throw Zip::Error("could not read Zip64 end of central directory locator record"); + throw Zip::Error{"could not read Zip64 end of central directory locator record"}; // read Zip64 end of central directory record is.seekg(zip64EndOfCentralDirectoryOffset, std::ios::beg); if (checkSignature(is, Signature::Zip64Eocd)) { - std::uint16_t versionNeededToExtract; + auto versionNeededToExtract = std::uint16_t{}; is.seekg(10, std::ios::cur); read(is, versionNeededToExtract); @@ -112,12 +112,12 @@ auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t read(is, centralDirectoryOffset); if (!is) - throw Zip::Error("could not read Zip64 end of central directory record"); + throw Zip::Error{"could not read Zip64 end of central directory record"}; if (versionNeededToExtract >= 62) // Version 6.2 introduces central directory encryption. - throw Zip::Error("central directory encryption is not supported"); + throw Zip::Error{"central directory encryption is not supported"}; } else - throw Zip::Error("could not find Zip64 end of central directory record"); + throw Zip::Error{"could not find Zip64 end of central directory record"}; } return centralDirectoryOffset; @@ -126,7 +126,7 @@ auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t } // namespace Zip::Error::Error(const std::string& description) -: BaseError("Zip error", description) +: BaseError{"Zip error", description} { } @@ -142,14 +142,14 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& if (!checkSignature(*m_is, Signature::CentralDirectoryHeader)) return *this = Iterator{}; - std::uint16_t flags; - std::uint16_t method; - std::uint16_t lastModTime; - std::uint16_t lastModDate; + auto flags = std::uint16_t{}; + auto method = std::uint16_t{}; + auto lastModTime = std::uint16_t{}; + auto lastModDate = std::uint16_t{}; - std::uint16_t filenameLength; - std::uint16_t extraFieldLength; - std::uint16_t fileCommentLength; + auto filenameLength = std::uint16_t{}; + auto extraFieldLength = std::uint16_t{}; + auto fileCommentLength = std::uint16_t{}; m_is->seekg(4, std::ios::cur); read(*m_is, flags); @@ -174,11 +174,11 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& m_entry->checkByte = (flags >> 3) & 1 ? static_cast(lastModTime >> 8) : msb(m_entry->crc32); - for (int remaining = extraFieldLength; remaining > 0;) + for (auto remaining = extraFieldLength; remaining > 0;) { // read extra field header - std::uint16_t id; - std::uint16_t size; + auto id = std::uint16_t{}; + auto size = std::uint16_t{}; read(*m_is, id); read(*m_is, size); remaining -= 4 + size; @@ -210,7 +210,7 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& std::accumulate(m_entry->name.begin(), m_entry->name.end(), mask<0, 32>, Crc32Tab::crc32) ^ mask<0, 32>; - std::uint32_t expectedNameCrc32; + auto expectedNameCrc32 = std::uint32_t{}; m_is->seekg(1, std::ios::cur); read(*m_is, expectedNameCrc32); size -= 5; @@ -226,7 +226,7 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& case 0x9901: // AE-x encryption structure if (7 <= size) { - std::uint16_t actualMethod; + auto actualMethod = std::uint16_t{}; m_is->seekg(5, std::ios::cur); read(*m_is, actualMethod); size -= 7; @@ -246,7 +246,7 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& m_is->seekg(fileCommentLength, std::ios::cur); if (!*m_is) - throw Error("could not read central directory header"); + throw Error{"could not read central directory header"}; return *this; } @@ -277,19 +277,19 @@ auto Zip::operator[](const std::string& name) const -> Zip::Entry const auto it = std::find_if(begin(), end(), [&name](const Entry& entry) { return entry.name == name; }); if (it == end()) - throw Error("found no entry named \"" + name + "\""); + throw Error{"found no entry named \"" + name + "\""}; else return *it; } auto Zip::operator[](std::size_t index) const -> Zip::Entry { - std::size_t nextIndex = 0; - const auto it = std::find_if(begin(), end(), [&nextIndex, index](const Entry&) { return nextIndex++ == index; }); + auto nextIndex = std::size_t{}; + const auto it = std::find_if(begin(), end(), [&nextIndex, index](const Entry&) { return nextIndex++ == index; }); if (it == end()) - throw Error("found no entry at index " + std::to_string(index) + " (maximum index for this archive is " + - std::to_string(nextIndex - 1) + ")"); + throw Error{"found no entry at index " + std::to_string(index) + " (maximum index for this archive is " + + std::to_string(nextIndex - 1) + ")"}; else return *it; } @@ -299,11 +299,11 @@ void Zip::checkEncryption(const Entry& entry, Encryption expected) if (entry.encryption != expected) { if (entry.encryption == Encryption::None) - throw Error("entry \"" + entry.name + "\" is not encrypted"); + throw Error{"entry \"" + entry.name + "\" is not encrypted"}; else if (expected == Encryption::None) - throw Error("entry \"" + entry.name + "\" is encrypted"); + throw Error{"entry \"" + entry.name + "\" is encrypted"}; else - throw Error("entry \"" + entry.name + "\" is encrypted with an unsupported algorithm"); + throw Error{"entry \"" + entry.name + "\" is encrypted with an unsupported algorithm"}; } } @@ -311,11 +311,11 @@ auto Zip::seek(const Entry& entry) const -> std::istream& { m_is.seekg(entry.offset, std::ios::beg); if (!checkSignature(m_is, Signature::LocalFileHeader)) - throw Error("could not find local file header"); + throw Error{"could not find local file header"}; // skip local file header - std::uint16_t nameSize; - std::uint16_t extraSize; + auto nameSize = std::uint16_t{}; + auto extraSize = std::uint16_t{}; m_is.seekg(22, std::ios::cur); read(m_is, nameSize); read(m_is, extraSize); @@ -333,14 +333,14 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, { // Store encrypted entries local file header offset and packed size. // Use std::map to sort them by local file header offset. - std::map packedSizeByLocalOffset; + auto packedSizeByLocalOffset = std::map{}; for (const auto& entry : *this) if (entry.encryption == Encryption::Traditional) packedSizeByLocalOffset.insert({entry.offset, entry.packedSize}); // Rewind input stream and iterate on encrypted entries to change the keys, copy the rest. m_is.seekg(0, std::ios::beg); - std::uint64_t currentOffset = 0; + auto currentOffset = std::uint64_t{}; progress.done = 0; progress.total = packedSizeByLocalOffset.size(); @@ -349,21 +349,21 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, { if (currentOffset < localHeaderOffset) { - std::copy_n(std::istreambuf_iterator(m_is), localHeaderOffset - currentOffset, - std::ostreambuf_iterator(os)); + std::copy_n(std::istreambuf_iterator{m_is}, localHeaderOffset - currentOffset, + std::ostreambuf_iterator{os}); m_is.get(); } if (!checkSignature(m_is, Signature::LocalFileHeader)) - throw Error("could not find local file header"); + throw Error{"could not find local file header"}; write(os, static_cast(Signature::LocalFileHeader)); - std::copy_n(std::istreambuf_iterator(m_is), 22, std::ostreambuf_iterator(os)); + std::copy_n(std::istreambuf_iterator{m_is}, 22, std::ostreambuf_iterator{os}); m_is.get(); - std::uint16_t filenameLength; - std::uint16_t extraSize; + auto filenameLength = std::uint16_t{}; + auto extraSize = std::uint16_t{}; read(m_is, filenameLength); read(m_is, extraSize); write(os, filenameLength); @@ -371,19 +371,18 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, if (0 < filenameLength + extraSize) { - std::copy_n(std::istreambuf_iterator(m_is), filenameLength + extraSize, - std::ostreambuf_iterator(os)); + std::copy_n(std::istreambuf_iterator{m_is}, filenameLength + extraSize, std::ostreambuf_iterator{os}); m_is.get(); } - Keys decrypt = oldKeys; - Keys encrypt = newKeys; - std::istreambuf_iterator in(m_is); - std::generate_n(std::ostreambuf_iterator(os), packedSize, + auto decrypt = oldKeys; + auto encrypt = newKeys; + auto in = std::istreambuf_iterator{m_is}; + std::generate_n(std::ostreambuf_iterator{os}, packedSize, [&in, &decrypt, &encrypt]() -> char { - const std::uint8_t p = *in++ ^ decrypt.getK(); - const std::uint8_t c = p ^ encrypt.getK(); + const auto p = *in++ ^ decrypt.getK(); + const auto c = p ^ encrypt.getK(); decrypt.update(p); encrypt.update(p); return c; @@ -394,6 +393,5 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, progress.done++; } - std::copy(std::istreambuf_iterator(m_is), std::istreambuf_iterator(), - std::ostreambuf_iterator(os)); + std::copy(std::istreambuf_iterator{m_is}, {}, std::ostreambuf_iterator{os}); } diff --git a/src/Zreduction.cpp b/src/Zreduction.cpp index b4ed926..d45058b 100644 --- a/src/Zreduction.cpp +++ b/src/Zreduction.cpp @@ -8,12 +8,12 @@ #include Zreduction::Zreduction(const std::vector& keystream) -: keystream(keystream) +: keystream{keystream} { index = keystream.size() - 1; zi_vector.reserve(1 << 22); - for (std::uint32_t zi_10_32_shifted = 0; zi_10_32_shifted < 1 << 22; zi_10_32_shifted++) + for (auto zi_10_32_shifted = std::uint32_t{}; zi_10_32_shifted < 1 << 22; zi_10_32_shifted++) if (KeystreamTab::hasZi_2_16(keystream[index], zi_10_32_shifted << 10)) zi_vector.push_back(zi_10_32_shifted << 10); } @@ -21,36 +21,38 @@ Zreduction::Zreduction(const std::vector& keystream) void Zreduction::reduce(Progress& progress) { // variables to keep track of the smallest Zi[2,32) vector - constexpr std::size_t trackSizeThreshold = 1 << 16; - bool tracking = false; - std::vector bestCopy; - std::size_t bestIndex = index; - std::size_t bestSize = trackSizeThreshold; + constexpr auto trackSizeThreshold = std::size_t{1 << 16}; + + auto tracking = false; + auto bestCopy = std::vector{}; + auto bestIndex = index; + auto bestSize = trackSizeThreshold; // variables to wait for a limited number of steps when a small enough vector is found - constexpr std::size_t waitSizeThreshold = 1 << 8; - bool waiting = false; - std::size_t wait = 0; + constexpr auto waitSizeThreshold = std::size_t{1 << 8}; + + auto waiting = false; + auto wait = std::size_t{}; - std::vector zim1_10_32_vector; + auto zim1_10_32_vector = std::vector{}; zim1_10_32_vector.reserve(1 << 22); - std::bitset<1 << 22> zim1_10_32_set; + auto zim1_10_32_set = std::bitset<1 << 22>{}; progress.done = 0; progress.total = keystream.size() - Attack::contiguousSize; - for (std::size_t i = index; i >= Attack::contiguousSize; i--) + for (auto i = index; i >= Attack::contiguousSize; i--) { zim1_10_32_vector.clear(); zim1_10_32_set.reset(); - std::size_t number_of_zim1_2_32 = 0; + auto number_of_zim1_2_32 = std::size_t{}; // generate the Z{i-1}[10,32) values - for (const std::uint32_t zi_10_32 : zi_vector) - for (const std::uint32_t zi_2_16 : KeystreamTab::getZi_2_16_vector(keystream[i], zi_10_32)) + for (const auto zi_10_32 : zi_vector) + for (const auto zi_2_16 : KeystreamTab::getZi_2_16_vector(keystream[i], zi_10_32)) { // get Z{i-1}[10,32) from CRC32^-1 - const std::uint32_t zim1_10_32 = Crc32Tab::getZim1_10_32(zi_10_32 | zi_2_16); + const auto zim1_10_32 = Crc32Tab::getZim1_10_32(zi_10_32 | zi_2_16); // collect without duplicates only those that are compatible with keystream{i-1} if (!zim1_10_32_set[zim1_10_32 >> 10] && KeystreamTab::hasZi_2_16(keystream[i - 1], zim1_10_32)) { @@ -106,12 +108,11 @@ void Zreduction::reduce(Progress& progress) void Zreduction::generate() { - const std::size_t number_of_zi_10_32 = zi_vector.size(); - for (std::size_t i = 0; i < number_of_zi_10_32; i++) + const auto number_of_zi_10_32 = zi_vector.size(); + for (auto i = std::size_t{}; i < number_of_zi_10_32; i++) { - const std::vector& zi_2_16_vector = - KeystreamTab::getZi_2_16_vector(keystream[index], zi_vector[i]); - for (std::size_t j = 1; j < zi_2_16_vector.size(); j++) + const auto& zi_2_16_vector = KeystreamTab::getZi_2_16_vector(keystream[index], zi_vector[i]); + for (auto j = std::size_t{1}; j < zi_2_16_vector.size(); j++) zi_vector.push_back(zi_vector[i] | zi_2_16_vector[j]); zi_vector[i] |= zi_2_16_vector[0]; } diff --git a/src/file.cpp b/src/file.cpp index 840dbf9..4b29f8c 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1,23 +1,23 @@ #include "file.hpp" FileError::FileError(const std::string& description) -: BaseError("File error", description) +: BaseError{"File error", description} { } auto openInput(const std::string& filename) -> std::ifstream { - if (std::ifstream is = std::ifstream(filename, std::ios::binary)) + if (auto is = std::ifstream{filename, std::ios::binary}) return is; else - throw FileError("could not open input file " + filename); + throw FileError{"could not open input file " + filename}; } auto loadStream(std::istream& is, std::size_t size) -> std::vector { - std::vector content; - std::istreambuf_iterator it(is); - for (std::size_t i = 0; i < size && it != std::istreambuf_iterator(); i++, ++it) + auto content = std::vector{}; + auto it = std::istreambuf_iterator{is}; + for (auto i = std::size_t{}; i < size && it != std::istreambuf_iterator{}; i++, ++it) content.push_back(*it); return content; @@ -25,14 +25,14 @@ auto loadStream(std::istream& is, std::size_t size) -> std::vector auto loadFile(const std::string& filename, std::size_t size) -> std::vector { - std::ifstream is = openInput(filename); + auto is = openInput(filename); return loadStream(is, size); } auto openOutput(const std::string& filename) -> std::ofstream { - if (std::ofstream os = std::ofstream(filename, std::ios::binary)) + if (auto os = std::ofstream{filename, std::ios::binary}) return os; else - throw FileError("could not open output file " + filename); + throw FileError{"could not open output file " + filename}; } diff --git a/src/log.cpp b/src/log.cpp index 54037ff..bd5596e 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -7,7 +7,7 @@ auto put_time(std::ostream& os) -> std::ostream& { - const std::time_t t = std::time(nullptr); + const auto t = std::time(nullptr); return os << std::put_time(std::localtime(&t), "%T"); } diff --git a/src/main.cpp b/src/main.cpp index 474d564..cb9415c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -106,12 +106,12 @@ auto main(int argc, const char* argv[]) -> int try { // enable virtual terminal support on Windows, no-op on other platforms - VirtualTerminalSupport vtSupport; + const auto vtSupport = VirtualTerminalSupport{}; // version information std::cout << "bkcrack " << bkcrackVersion << " - " << bkcrackVersionDate << std::endl; - const Arguments args(argc, argv); + const auto args = Arguments{argc, argv}; if (args.help) { std::cout << usage << std::endl; @@ -130,7 +130,7 @@ try return 0; } - std::vector keysvec; + auto keysvec = std::vector{}; if (args.keys) keysvec.push_back(*args.keys); else if (args.password) @@ -142,16 +142,16 @@ try else // find keys from known plaintext { - const Data data = args.loadData(); + const auto data = args.loadData(); // generate and reduce Zi[10,32) values - Zreduction zr(data.keystream); + auto zr = Zreduction{data.keystream}; if (data.keystream.size() > Attack::contiguousSize) { std::cout << "[" << put_time << "] Z reduction using " << (data.keystream.size() - Attack::contiguousSize) << " bytes of known plaintext" << std::endl; - ConsoleProgress progress(std::cout); + auto progress = ConsoleProgress{std::cout}; zr.reduce(progress); } @@ -165,9 +165,9 @@ try const auto [state, restart] = [&]() -> std::pair { - int start = args.attackStart; - ConsoleProgress progress(std::cout); - const SigintHandler sigintHandler{progress.state}; + auto start = args.attackStart; + auto progress = ConsoleProgress{std::cout}; + const auto sigintHandler = SigintHandler{progress.state}; keysvec = attack(data, zr.getCandidates(), start, zr.getIndex(), args.jobs, args.exhaustive, progress); return {progress.state, start}; }(); @@ -192,14 +192,14 @@ try else { std::cout << "Keys" << std::endl; - for (const Keys& keys : keysvec) + for (const auto& keys : keysvec) std::cout << keys << std::endl; } } // From there, keysvec is not empty. - const Keys keys = keysvec.front(); + const auto keys = keysvec.front(); if ((args.decipheredFile || args.changePassword || args.changeKeys || args.bruteforce) && keysvec.size() > 1) std::cout << "Continuing with keys " << keys << "\n" << "Use the command line option -k to provide other keys." << std::endl; @@ -213,8 +213,8 @@ try std::cout << std::endl; { - std::ifstream cipherstream = openInput(args.cipherArchive ? *args.cipherArchive : *args.cipherFile); - std::size_t ciphersize = std::numeric_limits::max(); + auto cipherstream = openInput(args.cipherArchive ? *args.cipherArchive : *args.cipherFile); + auto ciphersize = std::numeric_limits::max(); if (args.cipherArchive) { @@ -226,7 +226,7 @@ try ciphersize = entry.packedSize; } - std::ofstream decipheredstream = openOutput(*args.decipheredFile); + auto decipheredstream = openOutput(*args.decipheredFile); decipher(cipherstream, ciphersize, args.keepHeader ? 0 : static_cast(Data::encryptionHeaderSize), decipheredstream, @@ -245,10 +245,10 @@ try << newPassword << "\"" << std::endl; { - const auto archive = Zip{*args.cipherArchive}; - std::ofstream unlocked = openOutput(unlockedArchive); + const auto archive = Zip{*args.cipherArchive}; + auto unlocked = openOutput(unlockedArchive); - ConsoleProgress progress(std::cout); + auto progress = ConsoleProgress{std::cout}; archive.changeKeys(unlocked, keys, Keys{newPassword}, progress); } @@ -263,10 +263,10 @@ try << std::endl; { - const auto archive = Zip{*args.cipherArchive}; - std::ofstream unlocked = openOutput(unlockedArchive); + const auto archive = Zip{*args.cipherArchive}; + auto unlocked = openOutput(unlockedArchive); - ConsoleProgress progress(std::cout); + auto progress = ConsoleProgress{std::cout}; archive.changeKeys(unlocked, keys, newKeys, progress); } @@ -278,16 +278,15 @@ try { std::cout << "[" << put_time << "] Recovering password" << std::endl; - std::vector passwords; + auto passwords = std::vector{}; const auto [state, restart] = [&]() -> std::pair { const auto& charset = *args.bruteforce; const auto& [minLength, maxLength] = args.length.value_or(Arguments::LengthInterval{}); - std::string start = args.recoveryStart; - - ConsoleProgress progress(std::cout); - const SigintHandler sigintHandler(progress.state); + auto start = args.recoveryStart; + auto progress = ConsoleProgress{std::cout}; + const auto sigintHandler = SigintHandler{progress.state}; passwords = recoverPassword(keysvec.front(), charset, minLength, maxLength, start, args.jobs, args.exhaustive, progress); return {progress.state, start}; @@ -306,7 +305,7 @@ try const auto fillBefore = std::cout.fill('0'); std::cout << "You may resume the password recovery with the option: --continue-recovery "; - for (std::uint8_t c : restart) + for (const auto c : restart) std::cout << std::setw(2) << static_cast(c); std::cout << std::endl; @@ -331,7 +330,7 @@ try for (const auto& password : passwords) { std::cout << "as bytes: "; - for (std::uint8_t c : password) + for (const auto c : password) std::cout << std::setw(2) << static_cast(c) << ' '; std::cout << std::endl; std::cout << "as text: " << password << std::endl; @@ -403,7 +402,7 @@ auto getCompressionDescription(Zip::Compression compression) -> std::string void listEntries(const std::string& archiveFilename) { - auto archive = Zip{archiveFilename}; + const auto archive = Zip{archiveFilename}; std::cout << "Archive: " << archiveFilename << "\n" << "Index Encryption Compression CRC32 Uncompressed Packed size Name\n" @@ -413,7 +412,7 @@ void listEntries(const std::string& archiveFilename) std::cout.setf(std::ios::right | std::ios::dec, std::ios::adjustfield | std::ios::basefield); const auto fillBefore = std::cout.fill(' '); - std::size_t index = 0; + auto index = std::size_t{}; for (const auto& entry : archive) { // clang-format off @@ -440,16 +439,16 @@ void listEntries(const std::string& archiveFilename) void decipher(std::istream& is, std::size_t size, std::size_t discard, std::ostream& os, Keys keys) { - std::istreambuf_iterator cipher(is); - std::size_t i; + auto cipher = std::istreambuf_iterator{is}; + auto i = std::size_t{}; - for (i = 0; i < discard && i < size && cipher != std::istreambuf_iterator(); i++, ++cipher) + for (; i < discard && i < size && cipher != std::istreambuf_iterator{}; i++, ++cipher) keys.update(*cipher ^ keys.getK()); - for (std::ostreambuf_iterator plain(os); i < size && cipher != std::istreambuf_iterator(); + for (auto plain = std::ostreambuf_iterator{os}; i < size && cipher != std::istreambuf_iterator{}; i++, ++cipher, ++plain) { - const std::uint8_t p = *cipher ^ keys.getK(); + const auto p = *cipher ^ keys.getK(); keys.update(p); *plain = p; } diff --git a/src/password.cpp b/src/password.cpp index 96380d1..a9dd643 100644 --- a/src/password.cpp +++ b/src/password.cpp @@ -10,11 +10,11 @@ Recovery::Recovery(const Keys& keys, const std::vector& charset, std::vector& solutions, std::mutex& solutionsMutex, bool exhaustive, Progress& progress) -: charset(charset) -, solutions(solutions) -, solutionsMutex(solutionsMutex) -, exhaustive(exhaustive) -, progress(progress) +: charset{charset} +, solutions{solutions} +, solutionsMutex{solutionsMutex} +, exhaustive{exhaustive} +, progress{progress} { // initialize target X, Y and Z values x[6] = keys.getX(); @@ -25,17 +25,17 @@ Recovery::Recovery(const Keys& keys, const std::vector& charset, s y[5] = (y[6] - 1) * MultTab::multInv - lsb(x[6]); // derive more Z bytes - for (int i = 6; 1 < i; i--) + for (auto i = 6; 1 < i; i--) z[i - 1] = Crc32Tab::crc32inv(z[i], msb(y[i])); // precompute possible Z0[16,32) and Z{-1}[24,32) - for (const std::uint8_t p5 : charset) + for (const auto p5 : charset) { x[5] = Crc32Tab::crc32inv(x[6], p5); y[4] = (y[5] - 1) * MultTab::multInv - lsb(x[5]); z[3] = Crc32Tab::crc32inv(z[4], msb(y[4])); - for (const std::uint8_t p4 : charset) + for (const auto p4 : charset) { x[4] = Crc32Tab::crc32inv(x[5], p4); y[3] = (y[4] - 1) * MultTab::multInv - lsb(x[4]); @@ -61,7 +61,7 @@ void Recovery::recoverShortPassword(const Keys& initial) z[0] = initial.getZ(); // complete Z values and derive Y[24,32) values - for (int i = 1; i <= 4; i++) + for (auto i = 1; i <= 4; i++) { y[i] = Crc32Tab::getYi_24_32(z[i], z[i - 1]); z[i] = Crc32Tab::crc32(z[i - 1], msb(y[i])); @@ -82,16 +82,16 @@ void Recovery::recoverLongPassword(const Keys& initial) prefix.push_back(charset[0]); // precompute as much as we can about the next cipher state without knowing the password byte - const std::uint32_t x0_partial = Crc32Tab::crc32(initial.getX(), 0); - const std::uint32_t y0_partial = initial.getY() * MultTab::mult + 1; - const std::uint32_t z0_partial = Crc32Tab::crc32(initial.getZ(), 0); + const auto x0_partial = Crc32Tab::crc32(initial.getX(), 0); + const auto y0_partial = initial.getY() * MultTab::mult + 1; + const auto z0_partial = Crc32Tab::crc32(initial.getZ(), 0); - for (const std::uint8_t pi : charset) + for (const auto pi : charset) { // finish to update the cipher state - const std::uint32_t x0 = x0_partial ^ Crc32Tab::crc32(0, pi); - const std::uint32_t y0 = y0_partial + MultTab::getMult(lsb(x0)); - const std::uint32_t z0 = z0_partial ^ Crc32Tab::crc32(0, msb(y0)); + const auto x0 = x0_partial ^ Crc32Tab::crc32(0, pi); + const auto y0 = y0_partial + MultTab::getMult(lsb(x0)); + const auto z0 = z0_partial ^ Crc32Tab::crc32(0, msb(y0)); // recoverShortPassword is inlined below for performance @@ -126,7 +126,7 @@ void Recovery::recoverLongPassword(const Keys& initial) { prefix.push_back(charset[0]); - for (const std::uint8_t pi : charset) + for (const auto pi : charset) { Keys init = initial; init.update(pi); @@ -144,14 +144,14 @@ void Recovery::recursion(int i) { if (i != 1) // the Y-list is not complete so generate Y{i-1} values { - const std::uint32_t fy = (y[i] - 1) * MultTab::multInv; - const std::uint32_t ffy = (fy - 1) * MultTab::multInv; + const auto fy = (y[i] - 1) * MultTab::multInv; + const auto ffy = (fy - 1) * MultTab::multInv; // get possible LSB(Xi) - for (const std::uint8_t xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (y[i - 2] & mask<24, 32>)))) + for (const auto xi_0_8 : MultTab::getMsbProdFiber2(msb(ffy - (y[i - 2] & mask<24, 32>)))) { // compute corresponding Y{i-1} - const std::uint32_t yim1 = fy - xi_0_8; + const auto yim1 = fy - xi_0_8; // filter values with Y{i-2}[24,32) if (ffy - MultTab::getMultinv(xi_0_8) - (y[i - 2] & mask<24, 32>) <= maxdiff<24> && @@ -175,22 +175,24 @@ void Recovery::recursion(int i) return; // complete X values and derive password - for (int j = 5; 0 <= j; j--) + for (auto j = 5; 0 <= j; j--) { - const std::uint32_t xi_xor_pi = Crc32Tab::crc32inv(x[j + 1], 0); - p[j] = lsb(xi_xor_pi ^ x[j]); - x[j] = xi_xor_pi ^ p[j]; + const auto xi_xor_pi = Crc32Tab::crc32inv(x[j + 1], 0); + p[j] = lsb(xi_xor_pi ^ x[j]); + x[j] = xi_xor_pi ^ p[j]; } if (x[0] == candidateX0) // the password is successfully recovered { - std::string password = std::string(prefix.begin(), prefix.end()); + auto password = prefix; password.append(p.begin(), p.end()); password.erase(password.begin(), password.end() - length); - const bool isInCharset = + const auto isInCharset = std::all_of(password.begin(), password.end(), - [this](unsigned char c) { return std::binary_search(charset.begin(), charset.end(), c); }); + [this](char c) { + return std::binary_search(charset.begin(), charset.end(), static_cast(c)); + }); if (!isInCharset) { @@ -201,7 +203,7 @@ void Recovery::recursion(int i) const auto fillBefore = os.fill('0'); os << "Password: " << password << " (as bytes:"; - for (const std::uint8_t c : password) + for (const auto c : password) os << ' ' << std::setw(2) << static_cast(c); os << ')' << std::endl; @@ -233,9 +235,9 @@ namespace void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, const std::string& start, std::string& restart, Progress& progress) { - const int charsetSize = worker.charset.size(); + const auto charsetSize = static_cast(worker.charset.size()); - int index_start = 0; + auto index_start = 0; if (worker.prefix.size() < start.size()) while (index_start < charsetSize && worker.charset[index_start] < static_cast(start[worker.prefix.size()])) @@ -256,9 +258,9 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c { for (auto i = nextCandidateIndex++; i < charsetSize; i = nextCandidateIndex++) { - const std::uint8_t pm4 = worker.charset[i]; + const auto pm4 = worker.charset[i]; - Keys init = initial; + auto init = initial; init.update(pm4); worker.prefix.back() = pm4; @@ -297,8 +299,8 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c worker.prefix.push_back(worker.charset[0]); worker.prefix.push_back(worker.charset[0]); - const bool reportProgress = worker.prefix.size() == 2; - const bool reportProgressCoarse = worker.prefix.size() == 3; + const auto reportProgress = worker.prefix.size() == 2; + const auto reportProgressCoarse = worker.prefix.size() == 3; if (reportProgress) progress.done += index_start; @@ -315,10 +317,10 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c { for (auto i = nextCandidateIndex++; i < charsetSize * charsetSize; i = nextCandidateIndex++) { - const std::uint8_t pm4 = worker.charset[i / charsetSize]; - const std::uint8_t pm3 = worker.charset[i % charsetSize]; + const auto pm4 = worker.charset[i / charsetSize]; + const auto pm3 = worker.charset[i % charsetSize]; - Keys init = initial; + auto init = initial; init.update(pm4); init.update(pm3); @@ -352,18 +354,18 @@ void recoverPasswordRecursive(Recovery& worker, int jobs, const Keys& initial, c { worker.prefix.push_back(worker.charset[0]); - const bool reportProgress = worker.prefix.size() == 2; + const auto reportProgress = worker.prefix.size() == 2; if (worker.prefix.size() == 1) progress.done += index_start * charsetSize; else if (reportProgress) progress.done += index_start; - for (int i = index_start; i < charsetSize; i++) + for (auto i = index_start; i < charsetSize; i++) { - const std::uint8_t pi = worker.charset[i]; + const auto pi = worker.charset[i]; - Keys init = initial; + auto init = initial; init.update(pi); worker.prefix.back() = pi; @@ -390,13 +392,13 @@ auto recoverPassword(const Keys& keys, const std::vector& charset, std::size_t maxLength, std::string& start, int jobs, bool exhaustive, Progress& progress) -> std::vector { - std::vector solutions; - std::mutex solutionsMutex; - Recovery worker(keys, charset, solutions, solutionsMutex, exhaustive, progress); + auto solutions = std::vector{}; + auto solutionsMutex = std::mutex{}; + auto worker = Recovery{keys, charset, solutions, solutionsMutex, exhaustive, progress}; - std::string restart; - const std::size_t startLength = std::max(minLength, start.empty() ? 0 : start.size() + 6); - for (std::size_t length = startLength; length <= maxLength; length++) + auto restart = std::string{}; + const auto startLength = std::max(minLength, start.empty() ? 0 : start.size() + 6); + for (auto length = startLength; length <= maxLength; length++) { if (progress.state != Progress::State::Normal) break; @@ -405,10 +407,10 @@ auto recoverPassword(const Keys& keys, const std::vector& charset, { progress.log([](std::ostream& os) { os << "length 0-6..." << std::endl; }); - Keys initial; + auto initial = Keys{}; // look for a password of length between 0 and 6 - for (int l = 6; l >= 0; l--) + for (auto l = 6; l >= 0; l--) { worker.length = l; worker.recoverShortPassword(initial); diff --git a/src/types.cpp b/src/types.cpp index d0476f5..6c30b4e 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1,6 +1,6 @@ #include "types.hpp" BaseError::BaseError(const std::string& type, const std::string& description) -: std::runtime_error(type + ": " + description + ".") +: std::runtime_error{type + ": " + description + "."} { } From 76afc4757da3686d442a165060e6f01bf02bb56a Mon Sep 17 00:00:00 2001 From: kimci86 Date: Tue, 27 Feb 2024 23:13:51 +0100 Subject: [PATCH 18/19] Avoid output parameter when reading zip structures It allows more variables to be const. --- src/Zip.cpp | 103 +++++++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 62 deletions(-) diff --git a/src/Zip.cpp b/src/Zip.cpp index 37f2d9f..486ed0b 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -11,22 +11,24 @@ namespace { template -auto read(std::istream& is, T& x) -> std::istream& +auto read(std::istream& is) -> T { static_assert(N <= sizeof(T), "read requires output type to have at least N bytes"); // We make no assumption about platform endianness. - x = T{}; + auto x = T{}; for (auto index = std::size_t{}; index < N; index++) x |= static_cast(is.get()) << (8 * index); - return is; + return x; } -auto read(std::istream& is, std::string& string, std::size_t length) -> std::istream& +auto read(std::istream& is, std::size_t length) -> std::string { + auto string = std::string{}; string.resize(length); - return is.read(string.data(), string.size()); + is.read(string.data(), string.size()); + return string; } template @@ -52,8 +54,8 @@ enum class Signature : std::uint32_t auto checkSignature(std::istream& is, const Signature& signature) -> bool { - auto sig = std::uint32_t{}; - return read(is, sig) && sig == static_cast(signature); + const auto sig = read(is); + return is && sig == static_cast(signature); } auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t @@ -67,8 +69,8 @@ auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t do { is.seekg(-22 - commentLength, std::ios::end); - } while (read(is, signature) && signature != static_cast(Signature::Eocd) && - commentLength++ < mask<0, 16>); + signature = read(is); + } while (is && signature != static_cast(Signature::Eocd) && commentLength++ < mask<0, 16>); if (!is || signature != static_cast(Signature::Eocd)) throw Zip::Error{"could not find end of central directory signature"}; @@ -76,11 +78,9 @@ auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t // read end of central directory record { - auto disk = std::uint16_t{}; - - read(is, disk); + const auto disk = read(is); is.seekg(10, std::ios::cur); - read(is, centralDirectoryOffset); + centralDirectoryOffset = read(is); if (!is) throw Zip::Error{"could not read end of central directory record"}; @@ -92,10 +92,8 @@ auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t is.seekg(-40, std::ios::cur); if (checkSignature(is, Signature::Zip64EocdLocator)) { - auto zip64EndOfCentralDirectoryOffset = std::uint64_t{}; - is.seekg(4, std::ios::cur); - read(is, zip64EndOfCentralDirectoryOffset); + const auto zip64EndOfCentralDirectoryOffset = read(is); if (!is) throw Zip::Error{"could not read Zip64 end of central directory locator record"}; @@ -104,12 +102,10 @@ auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t is.seekg(zip64EndOfCentralDirectoryOffset, std::ios::beg); if (checkSignature(is, Signature::Zip64Eocd)) { - auto versionNeededToExtract = std::uint16_t{}; - is.seekg(10, std::ios::cur); - read(is, versionNeededToExtract); + const auto versionNeededToExtract = read(is); is.seekg(32, std::ios::cur); - read(is, centralDirectoryOffset); + centralDirectoryOffset = read(is); if (!is) throw Zip::Error{"could not read Zip64 end of central directory record"}; @@ -142,29 +138,20 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& if (!checkSignature(*m_is, Signature::CentralDirectoryHeader)) return *this = Iterator{}; - auto flags = std::uint16_t{}; - auto method = std::uint16_t{}; - auto lastModTime = std::uint16_t{}; - auto lastModDate = std::uint16_t{}; - - auto filenameLength = std::uint16_t{}; - auto extraFieldLength = std::uint16_t{}; - auto fileCommentLength = std::uint16_t{}; - m_is->seekg(4, std::ios::cur); - read(*m_is, flags); - read(*m_is, method); - read(*m_is, lastModTime); - read(*m_is, lastModDate); - read(*m_is, m_entry->crc32); - read(*m_is, m_entry->packedSize); - read(*m_is, m_entry->uncompressedSize); - read(*m_is, filenameLength); - read(*m_is, extraFieldLength); - read(*m_is, fileCommentLength); + const auto flags = read(*m_is); + const auto method = read(*m_is); + const auto lastModTime = read(*m_is); + m_is->seekg(2, std::ios::cur); + m_entry->crc32 = read(*m_is); + m_entry->packedSize = read(*m_is); + m_entry->uncompressedSize = read(*m_is); + const auto filenameLength = read(*m_is); + const auto extraFieldLength = read(*m_is); + const auto fileCommentLength = read(*m_is); m_is->seekg(8, std::ios::cur); - read(*m_is, m_entry->offset); - read(*m_is, m_entry->name, filenameLength); + m_entry->offset = read(*m_is); + m_entry->name = read(*m_is, filenameLength); m_entry->encryption = flags & 1 ? method == 99 || (flags >> 6) & 1 ? Encryption::Unsupported : Encryption::Traditional @@ -177,10 +164,8 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& for (auto remaining = extraFieldLength; remaining > 0;) { // read extra field header - auto id = std::uint16_t{}; - auto size = std::uint16_t{}; - read(*m_is, id); - read(*m_is, size); + const auto id = read(*m_is); + auto size = read(*m_is); remaining -= 4 + size; switch (id) @@ -188,17 +173,17 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& case 0x0001: // Zip64 extended information if (8 <= size && m_entry->uncompressedSize == mask<0, 32>) { - read(*m_is, m_entry->uncompressedSize); + m_entry->uncompressedSize = read(*m_is); size -= 8; } if (8 <= size && m_entry->packedSize == mask<0, 32>) { - read(*m_is, m_entry->packedSize); + m_entry->packedSize = read(*m_is); size -= 8; } if (8 <= size && m_entry->offset == mask<0, 32>) { - read(*m_is, m_entry->offset); + m_entry->offset = read(*m_is); size -= 8; } break; @@ -210,15 +195,14 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& std::accumulate(m_entry->name.begin(), m_entry->name.end(), mask<0, 32>, Crc32Tab::crc32) ^ mask<0, 32>; - auto expectedNameCrc32 = std::uint32_t{}; m_is->seekg(1, std::ios::cur); - read(*m_is, expectedNameCrc32); + const auto expectedNameCrc32 = read(*m_is); size -= 5; if (nameCrc32 == expectedNameCrc32) { - read(*m_is, m_entry->name, size); - size = 0; + m_entry->name = read(*m_is, size); + size = 0; } } break; @@ -226,9 +210,8 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& case 0x9901: // AE-x encryption structure if (7 <= size) { - auto actualMethod = std::uint16_t{}; m_is->seekg(5, std::ios::cur); - read(*m_is, actualMethod); + const auto actualMethod = read(*m_is); size -= 7; m_entry->compression = static_cast(actualMethod); @@ -314,11 +297,9 @@ auto Zip::seek(const Entry& entry) const -> std::istream& throw Error{"could not find local file header"}; // skip local file header - auto nameSize = std::uint16_t{}; - auto extraSize = std::uint16_t{}; m_is.seekg(22, std::ios::cur); - read(m_is, nameSize); - read(m_is, extraSize); + const auto nameSize = read(m_is); + const auto extraSize = read(m_is); m_is.seekg(nameSize + extraSize, std::ios::cur); return m_is; @@ -362,10 +343,8 @@ void Zip::changeKeys(std::ostream& os, const Keys& oldKeys, const Keys& newKeys, std::copy_n(std::istreambuf_iterator{m_is}, 22, std::ostreambuf_iterator{os}); m_is.get(); - auto filenameLength = std::uint16_t{}; - auto extraSize = std::uint16_t{}; - read(m_is, filenameLength); - read(m_is, extraSize); + const auto filenameLength = read(m_is); + const auto extraSize = read(m_is); write(os, filenameLength); write(os, extraSize); From a82d1c6136d3a0b7c57f6e8bc0df8b389b565fb8 Mon Sep 17 00:00:00 2001 From: kimci86 Date: Tue, 27 Feb 2024 23:15:33 +0100 Subject: [PATCH 19/19] Remove superfluous template parameter from read and write functions --- src/Zip.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/Zip.cpp b/src/Zip.cpp index 486ed0b..09ab9d8 100644 --- a/src/Zip.cpp +++ b/src/Zip.cpp @@ -10,14 +10,12 @@ namespace { -template +template auto read(std::istream& is) -> T { - static_assert(N <= sizeof(T), "read requires output type to have at least N bytes"); - // We make no assumption about platform endianness. auto x = T{}; - for (auto index = std::size_t{}; index < N; index++) + for (auto index = std::size_t{}; index < sizeof(T); index++) x |= static_cast(is.get()) << (8 * index); return x; @@ -31,13 +29,11 @@ auto read(std::istream& is, std::size_t length) -> std::string return string; } -template +template auto write(std::ostream& os, const T& x) -> std::ostream& { - static_assert(N <= sizeof(T), "write requires input type to have at least N bytes"); - // We make no assumption about platform endianness. - for (auto index = std::size_t{}; index < N; index++) + for (auto index = std::size_t{}; index < sizeof(T); index++) os.put(lsb(x >> (8 * index))); return os; @@ -80,7 +76,7 @@ auto findCentralDirectoryOffset(std::istream& is) -> std::uint64_t { const auto disk = read(is); is.seekg(10, std::ios::cur); - centralDirectoryOffset = read(is); + centralDirectoryOffset = read(is); if (!is) throw Zip::Error{"could not read end of central directory record"}; @@ -144,13 +140,13 @@ auto Zip::Iterator::operator++() -> Zip::Iterator& const auto lastModTime = read(*m_is); m_is->seekg(2, std::ios::cur); m_entry->crc32 = read(*m_is); - m_entry->packedSize = read(*m_is); - m_entry->uncompressedSize = read(*m_is); + m_entry->packedSize = read(*m_is); + m_entry->uncompressedSize = read(*m_is); const auto filenameLength = read(*m_is); const auto extraFieldLength = read(*m_is); const auto fileCommentLength = read(*m_is); m_is->seekg(8, std::ios::cur); - m_entry->offset = read(*m_is); + m_entry->offset = read(*m_is); m_entry->name = read(*m_is, filenameLength); m_entry->encryption = flags & 1