add keystroke analyzer
This commit is contained in:
parent
3e70825234
commit
0a1db4e1ae
@ -58,7 +58,9 @@ include_directories(password-analyzer PRIVATE ${CMAKE_BINARY_DIR}/external)
|
|||||||
set(COMMON_SOURCES
|
set(COMMON_SOURCES
|
||||||
defs.hpp
|
defs.hpp
|
||||||
utils.cpp
|
utils.cpp
|
||||||
|
stat_keystroke.cpp
|
||||||
stat_length.cpp
|
stat_length.cpp
|
||||||
|
stat_struct.cpp
|
||||||
)
|
)
|
||||||
set(COMMON_LIBRARIES
|
set(COMMON_LIBRARIES
|
||||||
magic_enum::magic_enum
|
magic_enum::magic_enum
|
||||||
|
8
defs.hpp
8
defs.hpp
@ -16,10 +16,18 @@ using std::operator""sv;
|
|||||||
|
|
||||||
enum class DataSource { CSDN, YAHOO };
|
enum class DataSource { CSDN, YAHOO };
|
||||||
|
|
||||||
|
struct Cord {
|
||||||
|
int x, y;
|
||||||
|
bool operator==(const Cord &rhs) const { return x == rhs.x && y == rhs.y; }
|
||||||
|
};
|
||||||
|
|
||||||
bool is_num(char c);
|
bool is_num(char c);
|
||||||
bool is_alpha(char c);
|
bool is_alpha(char c);
|
||||||
|
|
||||||
std::generator<std::string> passwords(const DataSource &source);
|
std::generator<std::string> passwords(const DataSource &source);
|
||||||
|
|
||||||
|
void stat_keystroke(const DataSource &source);
|
||||||
void stat_length(const DataSource &source);
|
void stat_length(const DataSource &source);
|
||||||
|
void stat_struct(const DataSource &source);
|
||||||
|
|
||||||
#endif // DEFS_HPP
|
#endif // DEFS_HPP
|
||||||
|
79
stat_keystroke.cpp
Normal file
79
stat_keystroke.cpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
|
const char keyboard[2][4][15] = {{"`1234567890-=", "\0qwertyuiop[]\\", "\0asdfghjkl;'", "\0zxcvbnm,./"},
|
||||||
|
{"~!@#$%^&*()_+", "\0QWERTYUIOP{}|", "\0ASDFGHJKL:\"", "\0ZXCVBNM<>?"}};
|
||||||
|
|
||||||
|
auto string_to_cord(const std::string &password) -> std::vector<Cord> {
|
||||||
|
std::vector<Cord> ret;
|
||||||
|
for (auto ch : password) {
|
||||||
|
for (const auto &kbd : keyboard) {
|
||||||
|
for (int j = 0; j < 4; ++j) {
|
||||||
|
auto bgn = kbd[j][0] == '\0' ? 1 : 0;
|
||||||
|
auto pos = std::strchr(kbd[j] + bgn, ch);
|
||||||
|
if (pos) {
|
||||||
|
ret.push_back({j, static_cast<int>(pos - kbd[j])});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cord_to_string(const std::vector<Cord> &cords) -> std::string {
|
||||||
|
std::ostringstream ret;
|
||||||
|
for (auto cord : cords) {
|
||||||
|
auto ch = keyboard[0][cord.x][cord.y]; // only consider not shifted keyboard
|
||||||
|
if (ch != '\0')
|
||||||
|
ret << ch;
|
||||||
|
else
|
||||||
|
spdlog::warn("cord_to_string: invalid cord: ({}, {})", cord.x, cord.y);
|
||||||
|
}
|
||||||
|
return ret.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto is_neighbour(const Cord &a, const Cord &b) -> bool {
|
||||||
|
auto [x1, y1] = a;
|
||||||
|
auto [x2, y2] = b;
|
||||||
|
|
||||||
|
auto same = x1 == x2 && y1 == y2; // NOTE: consider the case of `same` is true
|
||||||
|
return !same && std::abs(x1 - x2) <= 1 && std::abs(y1 - y2) <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stat_keystroke(const DataSource &source) {
|
||||||
|
spdlog::info("stat_keystroke({})", magic_enum::enum_name(source));
|
||||||
|
|
||||||
|
std::map<std::string, size_t> stat;
|
||||||
|
for (auto const &password : passwords(source)) {
|
||||||
|
if (password.size() <= 1) continue;
|
||||||
|
|
||||||
|
auto cords = string_to_cord(password);
|
||||||
|
if (cords.size() <= 1) continue;
|
||||||
|
|
||||||
|
std::string longest;
|
||||||
|
size_t max_len = 0, cur_len = 1;
|
||||||
|
for (int i = 0; i < cords.size() - 1; i++) {
|
||||||
|
auto ok = is_neighbour(cords[i], cords[i + 1]);
|
||||||
|
if (ok) {
|
||||||
|
cur_len++;
|
||||||
|
} else {
|
||||||
|
if (cur_len > max_len) {
|
||||||
|
max_len = cur_len;
|
||||||
|
longest = cord_to_string(
|
||||||
|
std::vector<Cord>(cords.begin() + (int)(i - cur_len + 1), cords.begin() + i + 1));
|
||||||
|
}
|
||||||
|
cur_len = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_len >= 4) stat[longest]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, size_t>> vec(stat.begin(), stat.end());
|
||||||
|
std::sort(vec.begin(), vec.end(), [](auto const &lhs, auto const &rhs) { return lhs.second > rhs.second; });
|
||||||
|
|
||||||
|
for (auto const &[length, count] : vec | std::views::take(10)) spdlog::info("{}: {}", length, count);
|
||||||
|
}
|
42
stat_struct.cpp
Normal file
42
stat_struct.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
|
std::string get_struct(const std::string &password) {
|
||||||
|
auto mapper = [](char c) {
|
||||||
|
if (is_num(c))
|
||||||
|
return 'D';
|
||||||
|
else if (is_alpha(c))
|
||||||
|
return 'L';
|
||||||
|
else
|
||||||
|
return 'S';
|
||||||
|
};
|
||||||
|
|
||||||
|
auto v = password | std::views::transform(mapper);
|
||||||
|
|
||||||
|
std::ostringstream ret;
|
||||||
|
|
||||||
|
for (auto cur = v.begin(); cur != v.end();) {
|
||||||
|
auto ch = *cur;
|
||||||
|
auto nxt = std::adjacent_find(cur, v.end(), std::not_equal_to<>());
|
||||||
|
auto end = nxt == v.end();
|
||||||
|
ret << ch << std::distance(cur, nxt) + !end;
|
||||||
|
cur = end ? nxt : std::next(nxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void stat_struct(const DataSource &source) {
|
||||||
|
spdlog::info("stat_struct({})", magic_enum::enum_name(source));
|
||||||
|
|
||||||
|
std::map<std::string, size_t> stat;
|
||||||
|
for (auto const &password : passwords(source)) ++stat[get_struct(password)];
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, size_t>> vec(stat.begin(), stat.end());
|
||||||
|
std::sort(vec.begin(), vec.end(), [](auto const &lhs, auto const &rhs) { return lhs.second > rhs.second; });
|
||||||
|
|
||||||
|
for (auto const &[struct_, count] : vec | std::views::take(10)) spdlog::info("{}: {}", struct_, count);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user