Skip to content

Commit

Permalink
Allow to continue a partial attack
Browse files Browse the repository at this point in the history
  • Loading branch information
kimci86 committed Dec 27, 2023
1 parent ea8f1e6 commit e4234e7
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 12 deletions.
4 changes: 4 additions & 0 deletions include/Arguments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ class Arguments
/// Tell not to use the check byte derived from ciphertext entry metadata as known plaintext
bool ignoreCheckByte = false;

/// Staring point of the attack on Z values remaining after reduction
int attackStart = 0;

/// Password from which to derive the internal password representation
std::optional<std::string> password;

Expand Down Expand Up @@ -137,6 +140,7 @@ class Arguments
offset,
extraPlaintext,
ignoreCheckByte,
attackStart,
password,
keys,
decipheredFile,
Expand Down
4 changes: 3 additions & 1 deletion include/Attack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ class Attack
/// \brief Iterate on Zi[2,32) candidates to try and find complete internal keys
/// \param data Data used to carry out the attack
/// \param zi_2_32_vector Zi[2,32) candidates
/// \param start Starting index of Zi[2,32) candidates in zi_2_32_vector to try.
/// Also used as an output parameter to tell where to restart.
/// \param index Index of the Zi[2,32) values relative to keystream
/// \param jobs Number of threads to use
/// \param exhaustive True to try and find all valid keys,
/// false to stop searching after the first one is found
/// \param progress Object to report progress
std::vector<Keys> attack(const Data& data, const u32vec& zi_2_32_vector, std::size_t index, int jobs, bool exhaustive, Progress& progress);
std::vector<Keys> attack(const Data& data, const u32vec& zi_2_32_vector, int& start, std::size_t index, int jobs, bool exhaustive, Progress& progress);

#endif // BKCRACK_ATTACK_HPP
4 changes: 4 additions & 0 deletions src/Arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ void Arguments::parseArgument()
case Option::ignoreCheckByte:
ignoreCheckByte = true;
break;
case Option::attackStart:
attackStart = readInt("checkpoint");
break;
case Option::password:
password = readString("password");
break;
Expand Down Expand Up @@ -317,6 +320,7 @@ Arguments::Option Arguments::readOption(const std::string& description)
PAIRS(-o, --offset, offset),
PAIRS(-x, --extra, extraPlaintext),
PAIR ( --ignore-check-byte, ignoreCheckByte),
PAIR ( --continue-attack, attackStart),
PAIR ( --password, password),
PAIRS(-k, --keys, keys),
PAIRS(-d, --decipher, decipheredFile),
Expand Down
13 changes: 9 additions & 4 deletions src/Attack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ void Attack::testXlist()
progress.state = Progress::State::EarlyExit;
}

std::vector<Keys> attack(const Data& data, const u32vec& zi_2_32_vector, std::size_t index, int jobs, const bool exhaustive, Progress& progress)
std::vector<Keys> attack(const Data& data, const u32vec& 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<int>(zi_2_32_vector.size());
Expand All @@ -186,23 +186,28 @@ std::vector<Keys> attack(const Data& data, const u32vec& zi_2_32_vector, std::si
std::mutex solutionsMutex;
Attack worker(data, index, solutions, solutionsMutex, exhaustive, progress);

progress.done = 0;
progress.done = start;
progress.total = size;

const auto threadCount = std::clamp(jobs, 1, size);
auto threads = std::vector<std::thread>{};
auto nextCandidateIndex = std::atomic<int>{0};
auto nextCandidateIndex = std::atomic<int>{start};
for(auto i = 0; i < threadCount; ++i)
threads.emplace_back(
[&nextCandidateIndex, size, &progress, candidates, worker]() mutable {
for(auto i = nextCandidateIndex++; i < size && progress.state == Progress::State::Normal; i = nextCandidateIndex++)
for(auto i = nextCandidateIndex++; i < size; i = nextCandidateIndex++)
{
worker.carryout(candidates[i]);
progress.done++;

if(progress.state != Progress::State::Normal)
break;
}
});
for(auto& thread : threads)
thread.join();

start = nextCandidateIndex;

return solutions;
}
21 changes: 14 additions & 7 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,14 @@ Options to get the internal password representation:
--ignore-check-byte Do not automatically use ciphertext's check byte
as known plaintext
--password <password> Password from which to derive the internal password
representation. Useful for testing purposes and
advanced scenarios such as reverting the effect of
the --change-password command.
--continue-attack <checkpoint>
Starting point of the attack. Useful to continue a previous
non-exhaustive or interrupted attack.
--password <password>
Password from which to derive the internal password representation.
Useful for testing purposes and advanced scenarios such as reverting
the effect of the --change-password command.
Options to use the internal password representation:
-k, --keys <X> <Y> <Z> Internal password representation as three 32-bits
Expand Down Expand Up @@ -144,12 +148,13 @@ try
std::cout << "[" << put_time << "] Attack on " << zr.getCandidates().size() << " Z values at index "
<< (static_cast<int>(data.offset + zr.getIndex()) - static_cast<int>(Data::ENCRYPTION_HEADER_SIZE)) << std::endl;

const auto state = [&]() -> Progress::State
const auto [state, restart] = [&]() -> std::pair<Progress::State, int>
{
int start = args.attackStart;
ConsoleProgress progress(std::cout);
SigintHandler sigintHandler{progress.state};
keysvec = attack(data, zr.getCandidates(), zr.getIndex(), args.jobs, args.exhaustive, progress);
return progress.state;
keysvec = attack(data, zr.getCandidates(), start, zr.getIndex(), args.jobs, args.exhaustive, progress);
return {progress.state, start};
}();

if(state == Progress::State::Canceled)
Expand All @@ -162,6 +167,8 @@ try
if(keysvec.empty())
{
std::cout << "Could not find the keys." << std::endl;
if(state == Progress::State::Canceled)
std::cout << "You may resume the attack with the option: --continue-attack " << restart << std::endl;
return 1;
}
else
Expand Down

0 comments on commit e4234e7

Please sign in to comment.