- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在移植我的“加密器/解密器”程序,该程序使用 key ( like this one ) 来触发文本。加密部分已完成,现在我正在研究解密器:
chars[index_of_long_string]
获取字符pass
vector<string> arrayAllReplaceDecryptVector(std::begin(arrayAllReplaceDecrypt), end(arrayAllReplaceDecrypt));
chars[index]
连接起来,然后删除 key_string 的前 128 个字符:
size_t index = std::distance(arrayAllReplaceDecryptVector.begin(), find(arrayAllReplaceDecryptVector.begin(), arrayAllReplaceDecryptVector.end(), pass.substr(0,128)));
output = output + chars[index];
pass = pass.substr(128, pass.length());
cin >> pass
传递给函数时被切断。这似乎发生在输入中第一次出现空格字符时。这从上面的索引代码中产生了 95。显示的输入是加密后的“Hello”,索引号应该是14、9、22、22,然后是28。最终的输出应该是“Hello”。
#include <iostream>
#include <fstream>
#include <vector>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
void fillChars(char(&chars)[95]);
string decrypt(char(chars)[95], string pass, string& lastJob);
char chars[95];
int runs = 0, lastJobID = 0;
bool keyCreated = false;
bool charsFilled = false;
int main()
{
string pass, lastJob;
//One time fills the character array
if (charsFilled == false)
{
fillChars(chars);
}
cout << "\nEnter a message to decrypt:\n";
cin >> pass;
lastJob = decrypt(chars, pass, lastJob);
lastJobID = 2;
}
void fillChars(char(&chars)[95])
{
//Opens chars.txt
ifstream characters("chars.txt");
for (int i = 0; i <= 94; i++)
{
if (i == 94)
{
chars[i] = ' ';
}
else
{
//Puts characters into array
characters >> chars[i];
}
}
characters.close();
}
string arrayAllReplaceDecrypt[95];
string decrypt(char(chars)[95], string pass, string& lastJob)
{
cout << "\n" << pass << "\n";
//Encrypted string
string output;
//Opens key
ifstream ifs("Key.txt");
//Reads entire key to string
string content((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()));
//Loops to add chars to
for (int i = 0; i < 94; i++)
{
//Adds 128 chars to replace array
arrayAllReplaceDecrypt[i] = content.substr(1, 128);
try
{
//Deletes old chars
content = content.substr(130, content.size());
}
catch (const exception& e)
{
//content.clear();
}
}
ifs.close();
vector<string> arrayAllReplaceDecryptVector(std::begin(arrayAllReplaceDecrypt), end(arrayAllReplaceDecrypt));
while (pass.length() > 0)
{
size_t index = std::distance(arrayAllReplaceDecryptVector.begin(), find(arrayAllReplaceDecryptVector.begin(), arrayAllReplaceDecryptVector.end(), pass.substr(0, 128)));
cout << "\n" << index << "\n";
output = output + chars[index];
pass = pass.substr(129, (pass.length() - 128));
}
return(output);
}
最佳答案
很有意思。你的程序随着时间的推移而发展,你发现了一些问题并逐步修补它们。有时通过两次犯同样的错误来消除错误。
尽管如此,仍有一些必须修复的严重错误。这些大多是越界错误。然后是样式错误,例如全局变量和错误数据类型的使用。
所以,软件设计的一个大问题,必须重构
最后但并非最不重要的一点是,您如何加密的想法是行不通的,因为您将第一个字母和 key 一起存储在 Key.txt”中。
sb = sb + (chars[(sb.length()) / 128]);
chars[rand() % 95 + 1]
rand
可以产生介于 0 和非常大的数字。如果这么大的数字的余数是 94,那么你在索引上加 1,得到无效的 95。因为,在变量定义中
char chars[95];
int runs = 0;
runs
.你可以测试一下。在第一次创建 key 文件时,您会看到许多 0 字符。在第二次运行时,您将创建 '\001' 字符。
substr(1,128)
然后
content = content.substr(130, content.size());
.这样,您消除了第一个清除字符,然后读取了 128 个字节。然后您跳过附加到 key 文件的“\n”。所有这些都应该重构。
get
或
getline
来克服这个问题。
for (int i = 0; i < 94; i++)
pass = pass.substr(129, pass.length());
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <random>
#include <algorithm>
#include <iterator>
#include <numeric>
// Definitions ---------------------------------------------------------------------------------------------------------------------
// Filenames that we want to use in our software
const std::string fileNamePrintableCharacters{ "chars.txt" };
const std::string fileNameKey{ "Key.txt" };
// That many printable characters we will use. We will use the ASCII and hence have characters in the range 32-126, and that are 95
constexpr size_t NumberOfUsedPrintableCharacters = 95U;
// One character will be encrypted with this number of bytes
constexpr size_t NumberOfEncryptionCharacters = 128U;
// This is datatype for our key. For each printable character we use NumberOfEncryptionCharacters.
using KeyData = std::vector<std::string>;
// ----------------------------------------------------------------------------------------------------------------------------------
// Read the printable characters from the definition file
std::string getPrintableCharacters() {
// Here we sill store the result. Initialize all values with 0
std::string printableCharacters{};
// Open the file with the printable characters and check, if the file could be opened
if (std::ifstream printableCharactersFileStream{ fileNamePrintableCharacters }; printableCharactersFileStream) {
// Read the printable characters and check, if that worked
if (!std::getline(printableCharactersFileStream, printableCharacters) || (printableCharacters.size() != NumberOfUsedPrintableCharacters)) {
std::cerr << "\n\n*** Error: Could not read the expected data from ('" << fileNamePrintableCharacters << "')\n";
printableCharacters = {};
}
}
else { // In case that we could not open the file, show error message
std::cerr << "\n\n*** Error: File with printable characters ('" << fileNamePrintableCharacters << "') could not be opened\n";
}
// Return the array with printable characters to the caller using Return Value Optimization / Copy Elision
return printableCharacters;
}
// ----------------------------------------------------------------------------------------------------------------------------------
std::string generateNewPrintableCharactersFile() {
// Here we will stor the resulting printabl characters string
std::string printableCharacters(NumberOfUsedPrintableCharacters, '\0');
// Open output file and chcke, if it could be opened
if (std::ofstream printableCharactersFileStream{ fileNamePrintableCharacters }; printableCharactersFileStream) {
// Create all printable characters
std::iota(printableCharacters.begin(), printableCharacters.end(), ' ');
if (!(printableCharactersFileStream << printableCharacters)) {
std::cerr << "\n\n*** Error: Could not create printable character file\n";
printableCharacters.clear();
}
}
return printableCharacters;
}
// ----------------------------------------------------------------------------------------------------------------------------------
KeyData getKeyData() {
// Here we will store all key data
KeyData keyData{};
// indicator for error. In case of error, we delete all key data
bool thereWasAnError = false;
// Open the file with the key data and check, if the file could be opened
if (std::ifstream keyDataFileStream{ fileNameKey }; keyDataFileStream) {
// Read NumberOfUsedPrintableCharacters lines from the key data file
for (size_t i{}; (i < NumberOfUsedPrintableCharacters) && keyDataFileStream && !thereWasAnError; ++i) {
// Read a line, and check, if that worked
if (std::string line{}; std::getline(keyDataFileStream, line)) {
// Sanity check. Check, if there were the expected number of characters in the key file
if (line.size() != NumberOfEncryptionCharacters) {
std::cerr << "\n\n*** Error: Invalid data in keyfile line " << i + 1 << "\n";
thereWasAnError = true;
}
else { // Save new read line with encryption characters
keyData.push_back(line);
}
}
}
// Next sanity check. Check, if we have read enough lines
if (keyData.size() != NumberOfUsedPrintableCharacters) {
std::cerr << "\n\n*** Error: Not enough data in key file\n";
thereWasAnError = true;
}
}
else { // In case that we could not open the file, show error message
std::cerr << "\n\n*** Error: File with key data ('" << fileNameKey << "') could not be opened\n";
thereWasAnError = true;
}
// In case of any error, reset the key data
if (thereWasAnError) keyData.clear();
// Return the array with printable characters to the caller using Return Value Optimization / Copy Elision
return keyData;
}
// ----------------------------------------------------------------------------------------------------------------------------------
KeyData generateNewKeyFile(const std::string& printableCharacters) {
// Here we will store all key data
KeyData keyData{};
// Sanity Check. Do we have the expected number of printable characters
if (NumberOfUsedPrintableCharacters == printableCharacters.size()) {
// Open already now the output file, and check, if it could be opened.
if (std::ofstream keyDataFileStream{ fileNameKey }; keyDataFileStream) {
// Initialize random number generation. Lambda for generating randim values
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<size_t> distribution(0U, NumberOfUsedPrintableCharacters - 1);
auto randomCharacter = [&]() { return printableCharacters[distribution(gen)]; };
// We want to create a key string for all printable characters
for (size_t i{}; i < NumberOfUsedPrintableCharacters && keyDataFileStream; ++i) {
// Temporary for string with random chars
std::string key(NumberOfEncryptionCharacters, '\0');
// Genrate string with random content
std::generate_n(key.begin(), NumberOfEncryptionCharacters, randomCharacter);
// Write data to file and check for possible error
if (!(keyDataFileStream << key << "\n")) {
std::cerr << "\n\n*** Error: Could not write line to key file\n";
keyData = {}; break;
}
else {
// Store the next line in the file in in the internal vector
keyData.push_back(std::move(key));
}
}
if (keyData.size() != NumberOfUsedPrintableCharacters) std::cerr << "\n*** Geeneral error during creation of key file\n";
}
else {
// In case that we could not open the file, show error message
std::cerr << "\n\n*** Error: File with key data ('" << fileNameKey << "') could not be opened for writing\n";
}
}
return keyData;
}
// ----------------------------------------------------------------------------------------------------------------------------------
std::string encrypt(const std::string& toBeEncrypted, const KeyData& keyData, const std::string& printableCharacters, const std::string& outputFileName) {
// Here we will store the encrypted result
std::string encryptedString{};
// First open output file, if this does not work, no need to do something else
if (std::ofstream outFileStream{ outputFileName }; outFileStream) {
// Then make some sanity checks
if (((keyData.size() != NumberOfUsedPrintableCharacters)) || (printableCharacters.size() != NumberOfUsedPrintableCharacters)) {
std::cerr << "\n\n*** Error: Preconditions for encryption not met\n";
}
else {
// Go through all data in source string that shall be encrypter
for (const char c : toBeEncrypted) {
// Search for the character in our printable character string and check, if it is available and if it is in the key data
if (size_t index{ printableCharacters.find(c) }; (index != std::string::npos) && (index < NumberOfUsedPrintableCharacters)) {
// Prepare output
encryptedString += keyData[index] + "\n";
outFileStream << keyData[index] << "\n";
}
else {
std::cerr << "\n\n*** Error: Invalid character '" << c << "' in input string\n";
}
}
}
}
else {
// In case that we could not open the file, show error message
std::cerr << "\n\n*** Error: output file ('" << outputFileName << "') for encrypted data could not be opened\n";
}
return encryptedString;
}
// ----------------------------------------------------------------------------------------------------------------------------------
std::string decrypt(const KeyData& keyData, const std::string& printableCharacters, const std::string& inputFileName) {
// Here we will store the decrypted result
std::string decryptedString{};
// First open input file, if this does not work, no need to do something else
if (std::ifstream inFileStream{ inputFileName }; inFileStream) {
// Then make some sanity checks
if (((keyData.size() != NumberOfUsedPrintableCharacters)) || (printableCharacters.size() != NumberOfUsedPrintableCharacters)) {
std::cerr << "\n\n*** Error: Preconditions for encryption not met\n";
}
else {
// Read all lines of the file
for (std::string line{}; std::getline(inFileStream, line); ) {
// Search this line in the keydata
if (KeyData::const_iterator searchResult = std::find(keyData.begin(), keyData.end(), line); searchResult != keyData.cend()) {
// Calculate the distance
if (const int index{ std::distance(keyData.begin() , searchResult) }; index < printableCharacters.size()) {
decryptedString += printableCharacters[index];
}
else { // With all the checks, this error should not occur
std::cerr << "\n\n*** Unexpected error while decrypting data\n";
}
}
else {
std::cerr << "\n\n*** Error: Could not decrypt data\n";
}
}
}
}
else {
// In case that we could not open the file, show error message
std::cerr << "\n\n*** Error: input file ('" << inputFileName << "') with encrypted data could not be opened\n";
}
// Last sanity check
if (decryptedString.empty()) std::cerr << "\nGeneral Error during decryption\n";
return decryptedString;
}
int main() {
// First read the printable character string. Check, if that was successfull
if (std::string printableCharacters{ getPrintableCharacters() }; printableCharacters.length() == NumberOfUsedPrintableCharacters ||
(printableCharacters = generateNewPrintableCharactersFile()).size() == NumberOfUsedPrintableCharacters) {
// Next, try to read a KeyData file
if (KeyData keyData{ getKeyData() }; keyData.size() == NumberOfUsedPrintableCharacters ||
(keyData = generateNewKeyFile(printableCharacters)).size() == NumberOfUsedPrintableCharacters) {
// main programm loop
for (bool doRunMainLoop{ true }; doRunMainLoop; ) {
// Show menu to the user
std::cout << "\n\n\nPlease select, what to do. Press\n\n\t1\tfor encryption\n\t2\tfor decryption\n\t3\tto generate new key file\n\t4\tto exit\n\nSelection: ";
// Get input from user and check, if that worked
if (unsigned int selection{}; std::cin >> selection) {
switch (selection) {
case 1U:
// Encryption
std::cout << "\nEncryption\n\nEnter first a filename and then the word that you want to encrypt:\n";
if (std::string filename{}, word{}; std::cin >> filename >> word) {
std::cout << "\nEncrypted Data:\n\n" << encrypt(word, keyData, printableCharacters, filename) << "\n";
}
else std::cout << "\n\nError while reading your data. Please try again\n";
break;
case 2U:
// Decryption
std::cout << "\nDecryption\n\nEnter first a filename with the ecrypted information:\n";
if (std::string filename{}; std::cin >> filename) {
std::cout << "\nDecrypted Data:\n\n" << decrypt(keyData, printableCharacters, filename) << "\n";
}
else std::cout << "\n\nError while reading your data. Please try again\n";
break;
case 3U:
// Generate new keyfile
if ((keyData = generateNewKeyFile(printableCharacters)).size() != NumberOfUsedPrintableCharacters) {
std::cerr << "\n\n*** Error: New keyfile could not be generated. Exit\n";
doRunMainLoop = false;
}
break;
case 4U:
doRunMainLoop = false;
break;
default:
std::cout << "\nInvalid selection. Pleas try again\n";
} // End select
}
else std::cerr << "\n\n\nError: Unexpected error while reading from console\n";
} // End for
}
else std::cerr << "\n\n*** Error: Problem with key data generation\n";
}
else std::cerr << "\n\n*** Error: No printable character data present\n";
return 0;
}
关于c++ - 在 vector 中查找字符串的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61167570/
如何使用 SPListCollection.Add(String, String, String, String, Int32, String, SPListTemplate.QuickLaunchO
我刚刚开始使用 C++ 并且对 C# 有一些经验,所以我有一些一般的编程经验。然而,似乎我马上就被击落了。我试过在谷歌上寻找,以免浪费任何人的时间,但没有结果。 int main(int argc,
这个问题已经有答案了: In Java 8 how do I transform a Map to another Map using a lambda? (8 个回答) Convert a Map>
我正在使用 node + typescript 和集成的 swagger 进行 API 调用。我 Swagger 提出以下要求 http://localhost:3033/employees/sear
我是 C++ 容器模板的新手。我收集了一些记录。每条记录都有一个唯一的名称,以及一个字段/值对列表。将按名称访问记录。字段/值对的顺序很重要。因此我设计如下: typedef string
我需要这两种方法,但j2me没有,我找到了一个replaceall();但这是 replaceall(string,string,string); 第二个方法是SringBuffer但在j2me中它没
If string is an alias of String in the .net framework为什么会发生这种情况,我应该如何解释它: type JustAString = string
我有两个列表(或字符串):一个大,另一个小。 我想检查较大的(A)是否包含小的(B)。 我的期望如下: 案例 1. B 是 A 的子集 A = [1,2,3] B = [1,2] contains(A
我有一个似乎无法解决的小问题。 这里...我有一个像这样创建的输入... var input = $(''); 如果我这样做......一切都很好 $(this).append(input); 如果我
我有以下代码片段 string[] lines = objects.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.No
这可能真的很简单,但我已经坚持了一段时间了。 我正在尝试输出一个字符串,然后输出一个带有两位小数的 double ,后跟另一个字符串,这是我的代码。 System.out.printf("成本:%.2
以下是 Cloud Firestore 列表查询中的示例之一 citiesRef.where("state", ">=", "CA").where("state", "= 字符串,我们在Stack O
我正在尝试检查一个字符串是否包含在另一个字符串中。后面的代码非常简单。我怎样才能在 jquery 中做到这一点? function deleteRow(locName, locID) { if
这个问题在这里已经有了答案: How to implement big int in C++ (14 个答案) 关闭 9 年前。 我有 2 个字符串,都只包含数字。这些数字大于 uint64_t 的
我有一个带有自定义转换器的 Dozer 映射: com.xyz.Customer com.xyz.CustomerDAO customerName
这个问题在这里已经有了答案: How do I compare strings in Java? (23 个回答) 关闭 6 年前。 我想了解字符串池的工作原理以及一个字符串等于另一个字符串的规则是
我已阅读 this问题和其他一些问题。但它们与我的问题有些无关 对于 UILabel 如果你不指定 ? 或 ! 你会得到这样的错误: @IBOutlet property has non-option
这两种方法中哪一种在理论上更快,为什么? (指向字符串的指针必须是常量。) destination[count] 和 *destination++ 之间的确切区别是什么? destination[co
This question already has answers here: Closed 11 years ago. Possible Duplicates: Is String.Format a
我有一个Stream一个文件的,现在我想将相同的单词组合成 Map这很重要,这个词在 Stream 中出现的频率. 我知道我必须使用 collect(Collectors.groupingBy(..)
我是一名优秀的程序员,十分优秀!