尝试算法:这个算法有相反的吗?
Experimenting with algorithms: Is there an inverse to this algorithm?
本文关键字:算法 更新时间:2023-10-16
EDIT-我重命名了这个标题并改变了问题的措辞,因为有些人指出这似乎更像是一种哈希算法,而不是加密 - 解密算法。但是,我将保留函数的名称。我还将在末尾附加我的完整代码以及一个链接,您可以在其中找到我正在使用的字典文件,因为有些人不确定我在哪里或如何生成要在算法中使用的数字。
我正在研究一种自定义算法,到目前为止,第一部分的结果似乎很好。但是,我用于反向的计算我不确定是否有。
伪代码如下:
for each character in string:
new character in return string = (a|b) & c + 'a';
where:
a is a large value based on the occurrence of that character
based on an alpha text dictionary file
b is a small value based on the occurrence of that character
found in the analyzed string to be encrypted.
c is the current string converted to lowercase.
我的加密功能:
std::string encrypt(const std::string& sentence, std::map<char, std::pair<unsigned, unsigned>>& dist) {
std::string encrypted = "";
// take each character from our original sentence
// find it in the map and perform the calculation.
// if the character is non alphabetical just add it.
for (auto& s : sentence)
if (std::isalpha(s)) {
char c = std::tolower(s);
char a = dist[std::remove_const_t<char>(c)].first; // large value
char b = dist[std::remove_const_t<char>(c)].second; // small value
char res = (a | b) % c + 'a';
encrypted.push_back(res);
}
else
encrypted.push_back(s);
return encrypted;
}
解密功能:
std::string decrypt(const std::string& encrypted, std::map<char, std::pair<unsigned, unsigned>>& dist) {
std::string decrpyted = "";
for (auto& s : encrypted) {
// ? Is there an inverse to the above?
// Also how would I handle the non alpha characters that
// were unchanged?
}
return decrpyted;
}
我将函数的结果更改为:
char res = (a % b) % c + 'a';
文本似乎被打乱了。有没有办法扭转这种情况?
编辑- -完整的源代码和字典文件的链接-
Github:字典文件
完整来源
#include <cctype>
#include <climits>
#include <iostream>
#include <iterator>
#include <fstream>
#include <map>
#include <sstream>
void generateCryptoBaseMapFromFile(std::string filename, std::map<char, unsigned>& weights);
void printWeights(std::string filename, std::map<char, unsigned> weights);
void analyzeTextAndGenerateDistributionMap(std::string contents, std::map<char,unsigned>& weights, std::map<char, std::pair<unsigned, unsigned>>& dist);
void printDistributionMap(std::string filename, std::map<char, std::pair<unsigned, unsigned>>& dist);
std::string encrypt(const std::string& sentence, std::map<char, std::pair<unsigned, unsigned>>& dist);
std::string decrypt(const std::string& encrypted, std::map<char, std::pair<unsigned, unsigned>>& dist);
int main() {
std::string filenameIn( "words_alpha.txt" );
std::map<char, unsigned> weights;
generateCryptoBaseMapFromFile(filenameIn, weights);
std::string filenameOut("character_distribution.txt");
printWeights(filenameOut, weights);
std::cout << 'n';
std::string sentence("I enjoyed myself when I went to the shore. I had a blast swimming in the cool ocean on a hot summer day with a mild breeze.");
std::map<char, std::pair<unsigned, unsigned>> distMap;
analyzeTextAndGenerateDistributionMap(sentence, weights, distMap);
printDistributionMap(filenameOut, distMap);
std::cout << 'n';
std::string encrypted = encrypt(sentence, distMap);
std::cout << encrypted << 'n';
// std::string decrypted = decrypt(encrypted, dist);
// std::cout << decrypted << 'n'; // should match original sentence.
return EXIT_SUCCESS;
}
void generateCryptoBaseMapFromFile(std::string filename, std::map<char, unsigned>& weights) {
unsigned int count[1U << CHAR_BIT]{};
std::ifstream in;
in.open(filename);
if (!in.is_open()) {
std::cout << "Could not open " << filename << " for reading.";
return;
}
for (std::istream_iterator<char> it(in), it_eof; it != it_eof; ++it)
++count[std::tolower(static_cast<unsigned char>(*it))];
for (unsigned i = 0; i < (1U << CHAR_BIT); ++i)
if (std::isalpha(i) && count[i])
weights[static_cast<char>(i)] = count[i];
in.close();
}
void printWeights(std::string filename, std::map<char, unsigned> weights) {
std::ostringstream ostream;
for (auto& u : weights)
ostream << u.first << ' ' << u.second << 'n';
// print to file & cout
std::ofstream out;
out.open(filename, std::ios::trunc);
out << ostream.str();
std::cout << ostream.str();
}
void analyzeTextAndGenerateDistributionMap(std::string contents, std::map<char,unsigned>& weights, std::map<char, std::pair<unsigned, unsigned>>& dist) {
std::cout << "nAnalyzing the following sentence:n" << contents << 'n';
unsigned int count[1U << CHAR_BIT]{};
std::istringstream istream( contents );
for (std::istream_iterator<char> it(istream), it_eof; it != it_eof; ++it)
++count[std::tolower(static_cast<unsigned char>(*it))];
for (unsigned i = 0; i < (1U << CHAR_BIT); ++i) {
if (std::isalpha(i) && count[i]) {
unsigned weight = weights.at(static_cast<unsigned char>(i));
dist[static_cast<unsigned char>(i)] = std::make_pair(weight, count[i]);
}
}
}
void printDistributionMap(std::string filename, std::map<char, std::pair<unsigned, unsigned>>& dist) {
std::ofstream out;
out.open(filename, std::ios::app);
std::ostringstream os;
os << "nn";
out << os.str();
std::cout << os.str();
os.str(std::string());
os.clear();
for (auto& m : dist) {
os << m.first << " (" << m.second.first << "," << m.second.second << ")n";
}
out << os.str();
std::cout << os.str();
}
std::string encrypt(const std::string& sentence, std::map<char, std::pair<unsigned, unsigned>>& dist) {
std::string encrypted = "";
// take each character from original string find it in the map
// and perform the calculations. If the character is non
// alpahbetical we just add it to the string.
for (auto& s : sentence)
if (std::isalpha(s)) {
char c = std::tolower(s);
char a = dist[c].first;
char b = dist[c].second;
// the following formula must have an inverse!
unsigned char res = (a % (b * c)) /*+ 'a'*/;
std::cout << +res << ' ';
encrypted.push_back(res);
}
else
encrypted.push_back(s);
std::cout << "nn";
return encrypted;
}
std::string decrypt(const std::string& encrypted, std::map<char, std::pair<unsigned, unsigned>>& dist) {
std::string decrpyted = "";
for (auto& s : encrypted) {
// ???
}
return decrpyted;
}
如果不查看dist
是如何生成的,则无法确定执行的操作是否可还原。但是,有一种相当简单的方法可以找出答案。您的算法所做的本质上是将任何字母字符映射到特定的固定值,该值可以简单地预先计算:
for(char c = 'a'; c <= 'z'; c++)
std::cout << c << ': ' << (int) ((dist[c].first | dist[c].second) % c + 'a') << 'n';
根据我从代码中可以看出的猜测是,它不是可逆的,因为在大多数情况下映射不会是双射的。由于c
的大小,除非在计算dist
时发生神奇的事情,否则至少一些字母字符会被映射到非字母字符所采用的代码,从而产生碰撞。
如果要将加密限制为字母字符,则应确保只有这些字符是有效的输出代码。最后但并非最不重要的一点是,大多数逻辑运算符以及模运算符都会修剪数据,这很可能无助于使整个事情可逆。
还有一个重要的注意事项(你可能已经听说过,但仍然):
永远不要将自己开发的算法用于任何实际的事情,除非你是布鲁斯施奈尔。
相关文章:
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 为什么我的排序算法会更改数组值
- 求最大元素位置的分治算法
- 具有非整数边容量的最大流量的Dinic算法
- 到连接组件算法的问题(递归)
- STL算法函数在多个一维容器上的使用
- 读取最后一行代码算法 - c++ 时出现问题
- 括号更改 O(n) 算法
- std::unordered_map 搜索算法是如何实现的?
- 如何实现高效的算法来计算大型数据集的多个不同值?
- 如何在 Mac 上使用 c++17 并行标准库算法?