Skip to content

Commit

Permalink
Finished xor ciphers
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyclic3 committed Aug 5, 2020
1 parent f1ee4b5 commit 4056d16
Show file tree
Hide file tree
Showing 11 changed files with 228 additions and 280 deletions.
15 changes: 9 additions & 6 deletions include/ciphey/ciphers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,25 @@ namespace ciphey {
}

namespace xor_single {
void crypt(bytes_ref_t str, key_t const& key);
void crypt(bytes_ref_t str, key_t key);
inline void encrypt(bytes_ref_t str, key_t const& key) { crypt(str, key); }
inline void decrypt(bytes_ref_t str, key_t const& key) { crypt(str, key); }

std::vector<crack_result<key_t>> crack(prob_table observed, prob_table const& expected,
freq_t ptext_length, prob_t p_value = default_p_value);
prob_t detect(const prob_table& observed, prob_table const& expected, freq_t count);
}

namespace xorcrypt {
void crypt(bytes_ref_t& str, key_t const& key);
inline void encrypt(bytes_ref_t& str, key_t const& key) { crypt(str, key); }
inline void decrypt(bytes_ref_t& str, key_t const& key) { crypt(str, key); }
void crypt(bytes_ref_t str, bytes_const_ref_t key);
inline void encrypt(bytes_ref_t str, bytes_const_ref_t key) { crypt(str, key); }
inline void decrypt(bytes_ref_t str, bytes_const_ref_t key) { crypt(str, key); }

// A result of 1 means that it is not likely to be xorcrypt
size_t guess_len(bytes_const_ref_t input);

std::vector<crack_result<key_t>> crack(windowed_prob_table observed, prob_table const& expected,
freq_t ptext_length, prob_t p_value = default_p_value);
std::vector<crack_result<bytes_t>> crack(windowed_prob_table const& observed, prob_table const& expected,
freq_t ptext_length, prob_t p_value = default_p_value);
prob_t detect(windowed_prob_table const& observed, prob_table const& expected, freq_t count);
}
}
61 changes: 53 additions & 8 deletions include/ciphey/swig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace ciphey {
domain_t domain;
freq_t len;
};
inline std::shared_ptr<simple_analysis_res> analyse_string(string_t str, domain_t domain = {}) {
inline std::shared_ptr<simple_analysis_res> analyse_string(string_ref_t str, domain_t domain = {}) {
auto ret = std::make_shared<simple_analysis_res>();
ret->domain = std::move(domain);
if (ret->domain.size())
Expand All @@ -27,20 +27,30 @@ namespace ciphey {
}
return ret;
}
inline std::shared_ptr<simple_analysis_res> analyse_bytes(bytes_const_ref_t str) {
auto ret = std::make_shared<simple_analysis_res>();
freq_analysis(ret->freqs, string_const_ref_t{reinterpret_cast<char_t const*>(str.data()), str.size()});
ret->len = str.size();
return ret;
}
inline std::shared_ptr<simple_analysis_res> start_analysis(domain_t domain = {}) {
auto ret = std::make_shared<simple_analysis_res>();
ret->domain = std::move(domain);
ret->len = 0;
return ret;
}
inline void continue_analysis(std::shared_ptr<simple_analysis_res> target, string_t str) {
inline void continue_analysis(std::shared_ptr<simple_analysis_res> target, string_const_ref_t str) {
if (target->domain.size())
target->len += freq_analysis(target->freqs, str, target->domain);
else {
freq_analysis(target->freqs, str);
target->len += str.size();
}
}
inline void continue_analysis(std::shared_ptr<simple_analysis_res> target, bytes_const_ref_t str) {
freq_analysis(target->freqs, string_const_ref_t{reinterpret_cast<char_t const*>(str.data()), str.size()});
target->len += str.size();
}

// +-------------------------------------------------------------------------+
// | WINDOWED ANALYSIS |
Expand All @@ -65,13 +75,21 @@ namespace ciphey {
// ret->probs = freq_conv(ret->freqs, ret->len);
return ret;
}
inline std::shared_ptr<windowed_analysis_res> analyse_bytes(bytes_const_ref_t str, size_t window_size,
domain_t domain = {}) {
auto ret = std::make_shared<windowed_analysis_res>();
ret->freqs.resize(window_size);
ret->len = str.size();
freq_analysis(ret->freqs, string_const_ref_t{reinterpret_cast<char_t const*>(str.data()), str.size()});
return ret;
}
inline std::shared_ptr<windowed_analysis_res> start_analysis(size_t window_size, domain_t domain = {}) {
auto ret = std::make_shared<windowed_analysis_res>();
ret->domain = std::move(domain);
ret->len = 0;
return ret;
}
inline void continue_analysis(std::shared_ptr<windowed_analysis_res> target, string_t str) {
inline void continue_analysis(std::shared_ptr<windowed_analysis_res> target, string_const_ref_t str) {
if (target->domain.size()) {
freq_analysis(target->freqs, str);
target->len += str.size();
Expand Down Expand Up @@ -141,7 +159,7 @@ namespace ciphey {
size_t len;
std::shared_ptr<windowed_analysis_res> tab;
};
inline std::vector<vigenere_key_len_candidate> vigenere_likely_key_lens(string_t in, prob_table expected,
inline std::vector<vigenere_key_len_candidate> vigenere_likely_key_lens(string_const_ref_t in, prob_table expected,
domain_t const& domain,
prob_t p_value = default_p_value) {
auto res = vigenere::likely_key_lens(in, expected, domain, p_value);
Expand All @@ -159,6 +177,37 @@ namespace ciphey {
return ret;
}

inline std::vector<ciphey::crack_result<ciphey::xor_single::key_t>> xor_single_crack(std::shared_ptr<simple_analysis_res> in,
prob_table const& expected,
prob_t p_value = default_p_value) {
return xor_single::crack(freq_conv(in->freqs, in->len), expected, in->len, p_value);
}

inline void xor_single_decrypt(bytes_ref_t str, ciphey::caesar::key_t key) {
xor_single::decrypt(str, key);
}
inline void xor_single_encrypt(bytes_ref_t str, ciphey::caesar::key_t key) {
xor_single::encrypt(str, key);
}
inline prob_t xor_single_detect(std::shared_ptr<simple_analysis_res> in, prob_table const& expected) {
return xor_single::detect(freq_conv(in->freqs, in->len), expected, in->len);
}

inline std::vector<ciphey::crack_result<ciphey::xorcrypt::key_t>> xorcrypt_crack(std::shared_ptr<windowed_analysis_res> in,
prob_table expected,
prob_t p_value = default_p_value) {
return xorcrypt::crack(freq_conv(in->freqs, in->len), expected, in->len, p_value);
}
inline void xorcrypt_decrypt(bytes_ref_t str, bytes_const_ref_t key) {
xorcrypt::decrypt(str, key);
}
inline void xorcrypt_encrypt(bytes_ref_t str, bytes_const_ref_t key) {
xorcrypt::encrypt(str, key);
}
inline prob_t xorcrypt_detect(std::shared_ptr<windowed_analysis_res> in, prob_table expected) {
auto prob_tab = freq_conv(in->freqs, in->len);
return xorcrypt::detect(prob_tab, expected, in->len);
}
inline size_t xorcrypt_guess_len(bytes_const_ref_t in) {
return xorcrypt::guess_len(in);
}
Expand All @@ -179,8 +228,4 @@ namespace ciphey {
ret.index = (size_t)(edges.front() - input.data()) / sizeof(ausearch_edge const*);
return ret;
}

inline void xor_single_crypt(bytes_ref_t str, ciphey::xor_single::key_t key) {
xor_single::crypt(str, key);
}
}
3 changes: 2 additions & 1 deletion include/ciphey/typedefs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ namespace ciphey {

using string_t = std::basic_string<char_t>;
using string_ref_t = nonstd::span<char_t>;
using string_const_ref_t = std::basic_string_view<char_t>;
// Not using string_view because casting is painful
using string_const_ref_t = nonstd::span<const char>;

using bytes_t = std::vector<uint8_t>;
using bytes_ref_t = nonstd::span<uint8_t>;
Expand Down
26 changes: 22 additions & 4 deletions src/ciphers/xor_single.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ namespace ciphey::xor_single {
// We need to swap the XOR pairs, but we also need to avoid swapping back
//
// HACK: There must be a better way than this
std::array<bool, 256> is_on = {false};
std::array<bool, 256> is_on;
std::fill(is_on.begin(), is_on.end(), false);
for (size_t i = 0; i < 256; ++i) {
if (!std::exchange(is_on[i], true)) {
auto i_xor = i ^ key;
Expand All @@ -22,7 +23,7 @@ namespace ciphey::xor_single {
}
}

void crypt(bytes_ref_t& str, key_t const& key) {
void crypt(bytes_ref_t str, key_t key) {
for (auto& i : str)
i ^= key;
}
Expand All @@ -32,13 +33,30 @@ namespace ciphey::xor_single {

for (uint8_t key = 1; key != 0; ++key) {
// Undo last one, and add our one (the -1'th term is 0, so no effect!)
xor_prob_table(observed, key ^ (key - 1));
if (auto key_p_value = gof_test(create_assoc_table(observed, expected), 256); key_p_value > p_value)
//
// TODO: actually do this with a rotation
// xor_prob_table(observed, key ^ (key - 1));
prob_table new_observed;
for (auto& i : observed)
new_observed[i.first^key] = i.second;
if (key == 'c')
::printf("");

if (auto key_p_value = gof_test(create_assoc_table(new_observed, expected), count); key_p_value > p_value)
ret.push_back({.key = key, .p_value = key_p_value });
else {
::printf("");
}
}

sort_crack_result(ret);

return ret;
}

prob_t detect(prob_table const& observed, prob_table const& expected, freq_t count) {
if (count == 0)
return 0.;
return closeness_test(observed, expected, count);
}
}
6 changes: 3 additions & 3 deletions src/ciphers/xorcrypt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ namespace ciphey::xorcrypt {
return best_candidate.first;
}

std::vector<crack_result<key_t>> crack(windowed_prob_table observed, prob_table const& expected,
freq_t count, prob_t p_value) {
std::vector<crack_result<bytes_t>> crack(const windowed_prob_table& observed, prob_table const& expected,
freq_t count, prob_t p_value) {
return detail::reducer<key_t, xor_single::key_t, xor_single::crack>::crack(observed, expected, count, p_value);
}

void crypt(bytes_t& str, key_t const& key) {
void crypt(bytes_ref_t str, bytes_const_ref_t key) {
for (size_t i = 0; i < str.size(); ++i)
str[i] ^= key[i % key.size()];
}
Expand Down
2 changes: 1 addition & 1 deletion src/freq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ namespace ciphey {
};

std::map<char_t, key_elem> keys;
// We can use index notation for this, as that gets default constructed
for (auto& i : expected)
keys[i.first].exp_val = i.second;
// We can use index notation for this, as that gets default constructed
for (auto& i : observed)
keys[i.first].obs_val = i.second;

Expand Down
2 changes: 1 addition & 1 deletion test/caesar.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ struct test_elem {
ciphey::caesar::key_t key;
};

std::vector<test_elem> caesar_tests {
static std::vector<test_elem> caesar_tests {
{
"xubbe, fbqduj",
"hello, planet",
Expand Down
2 changes: 1 addition & 1 deletion test/vigenere.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ struct vigenere_test_elem {
ciphey::vigenere::key_t key;
};

std::vector<vigenere_test_elem> vigenere_tests {
static std::vector<vigenere_test_elem> vigenere_tests {
{
"odxo yh uvtpmhx. vapq bqddv mja",
"call me ishmael. some years ago",
Expand Down
Loading

0 comments on commit 4056d16

Please sign in to comment.