problems encrypting char* - c++

i have been working on this project for a week and i cant find the solution to my problems.
i'm making an encryptor which can encrypt/decrypt binary file(like .exe, .jpg etc).
i am able to correctly get the data from the binary file using vector.
but i cannot correctly encrypt/decrypt the data from the vector.
some code:
if (encryptFile)
{
Crypt crypt;
//TOencryptfile.open(writeFile, ios::binary | ios::out);
vector<char> buffer((istreambuf_iterator<char>(encryptFile)),(istreambuf_iterator<char>()));
cout << buffer.size() << endl;
_getch();
for (std::vector<char>::iterator i = buffer.begin(); i != buffer.end(); ++i) {
// encryption that fails
temp = crypt.getKeyFromString(&*i , key, strlen(&*i));
}
TOencryptfile.close();
encryptFile.close();
}
and the function getKeyFromString:
KEYCRYPT Crypt::getKeyFromString(KEYCRYPT text, KEYCHAR charkey, keylength length) {
int string_size = std::strlen(text);
KEYCRYPT textcrypt = new char[string_size + 1];
std::strcpy(textcrypt, text);
int key = strlen(charkey);
for (int i = 0; i < length; i++) {
if (strlen(text) != 0) {
textcrypt[i] = text[i] ^ charkey[i % (sizeof(charkey) / sizeof(char))];
//keylvl += text[i] ^ (int(charkey) + i) % key;
//keyfnl += keylvl[i] ^ (int(charkey) - i) * key;
}
}
return textcrypt;
}
and at last the types:
typedef char* KEYCRYPT;
typedef int KEY;
typedef char* KEYCHAR;
typedef int keylength;
does anybody know a good way to encrypt *i?
because my way does not work, it does not return the same when calling the function again with getKeyFromString(temp, key, strlen(temp))

well, according to the response of #Barmar:
#waterlight Put the file contents into a string and pass that to the crypto API.
i managed to fix the problem.
all i had to do was:
stringstream result;
std::copy(buffer.begin(), buffer.end(), std::ostream_iterator<char>(result, " "));
string now = result.str();
and everything worked.
thanks to everybody who replied!!

Related

I need to write a c++ program with these objectives

A C++ program which read data from a text file. Suppose text file contains a
paragraph about any topic. Your program asks user to enter file name without extension. Now, a
user defined function (name: ReadWordByWord()) reads all data word by word and store in a
character type array with dynamically grows according to the data.
Finally, declare a user-defined function (name: SaveInReverse()) which stores this text into a
text file (name is entered by user) in reverse order of words e.g. last words will be stored at start,
then 2nd last word, 3rd last word etc. of the original document.
And here is what I've done so far... Here I am not using the delete command, that if I use will cause an error- a heap error. How can I accomplish that first? And then what are any tips to improve this program.
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
char* readWordByWord(char * old)
{
int coun = 0;
for (int i = 0; old[i] != '\0'; i++) // to find the length of word
{
coun++;
}
char *newArr = new char[coun + 1];
strcpy(newArr, old);
//delete[]old; // this is where i am putting delete command to delete the previous i.e old array and then return the new one
return newArr;
}
int size = 100;
int main()
{
fstream fin;
string forCopy[1000];
int index = 0;
fin.open("file.txt");
char *p = new char[size];
while (fin >> p)
{
p = readWordByWord(p);
//cout << p<<endl;
forCopy[index++] = p;
/*for (int i = 0; p[i] != '\0'; i++)
{
}*/
}
for (int i = index - 1; i > 0; i--)
cout << forCopy[i] << " ";
delete[]p;
p = NULL;
fin.close();
return 0;
}
I've made it from start again (must not include newlines since only a paragraph required):
#include <iostream>
#include <fstream>
#include <string>
void reverse(char *begin, char *end) { // reverses a word
char temp;
while (begin < end) {
temp = *begin;
*begin++ = *end;
*end-- = temp;
}
}
void reverseParagraph(char *arg) { // reverses each word of the paragraph
char *word_begin = arg;
char *temp = arg;
while (*temp) {
temp++;
if (*temp == '\0')
reverse(word_begin, temp - 1);
else if (*temp == ' ') {
reverse(word_begin, temp - 1);
word_begin = temp + 1;
}
}
reverse(arg, temp - 1);
}
int main() {
std::ifstream file("file.txt");
std::string fileData = "";
while(getline(file, fileData)); // counting the number of letters for memory allocation
size_t len = fileData.length();
char *str = new char[len + 1];
strcpy(str, fileData.c_str());
reverseParagraph(str); // reverse the entire character pointer
std::cout << str << std::endl; // displays for testing
std::ofstream fileOut("out.txt");
fileOut << str << std::endl; // saving the output into another file
fileOut.close();
delete[] str;
file.close();
return 0;
}
This program firstly gets the containing data of a file and then assigns into a variable. The variable is then converted into character (pointer) after getting the string length.
After that, it recursively reverses the position each word of the fileData and finally it displays. The modified data is thereafter printed into another file.

Making a Caesar Cypher, and it does not want to decipher the message

For a project, we have to make a Caesar Cipher using classes and save the encrypted message inside of a file so a user can decipher it with the program.
I input the message and it has no problem encrypting the message according to the displacement/key I input (since I gave an option for the user to place the displacement they please).
However, the problem lies in decripting the message. It seems to only decript the penultimate or last letter of what I inputted and it doesnt even bother to show the remaining characters of the message.
I have currently no idea why its acting the way it is, I figured I would have to change the message to take char variables instead of string, but that would mean rewriting a large chunk of the code, and at the moment, I would like to avoid having to rewrite the code from scratch. If there are no other options, then I guess I will have to rewrite the code.
Here is the code, (hope that helps and sorry if my message may seem messy, this is the first time I post anything here):
#include<iostream>
#include<string>
#include<fstream>
#include<ctime>
#include<cstdlib>
/* This is a program that will grab a message from the user and encrypt it, then decrypt it
It will also generate a random 8-digit character password used to access the encrypted file
It will also have the ability to allow the user to choose how many spaces the cipher will take into account */
using namespace std;
//Implement a set displacement and get displacement
class Cipherer
{
private:
int displacement;
string message;
//string decryptMessage;
public:
void setDisplacer(int key);
int getDisplacer()const;
void msgEncripter(string, int);
string getMessage()const;
void msgDecripter(string);
string getDecription()const;
};
void Cipherer::setDisplacer(int key)
{
displacement = key;
}
int Cipherer::getDisplacer()const
{
return displacement;
}
void Cipherer::msgEncripter(string msg, int key)
{
string encriptedMsg = msg;
//.size returns the number of elements
for (unsigned int i = 0; i < msg.size(); i++)
{
if (msg[i] == 32) //32 is the value in ASCII of the space character
{
continue;
}
else
{
if ((msg[i] + key) > 122)
{
int temp = (msg[i] + key) - 122;
encriptedMsg[i] = 96 + temp;
}
else if (msg[i] + key > 90 && msg[i] <= 96)
{
int temp = (msg[i] + key) - 90;
encriptedMsg[i] = 64 + temp;
}
else
{
encriptedMsg[i] += key;
}
}
}
message = encriptedMsg;
}
string Cipherer::getMessage()const
{
return message;
}
void Cipherer::msgDecripter(string msg)
{
string decriptedMsg;
for (unsigned int i = 0; i < msg.size(); i++)
{
if (msg[i] == 32)
{
continue;
}
else
{
if ((msg[i] - displacement) < 97 && (msg[i] - displacement) > 90)
{
decriptedMsg[i] = (msg[i] - displacement) + 26;
}
else if ((msg[i] - displacement) < 65)
{
decriptedMsg[i] = (msg[i] - displacement) + 26;
}
else
{
decriptedMsg = msg[i] - displacement;
}
}
}
message = decriptedMsg;
}
string Cipherer::getDecription()const
{
return message;
}
static const char PASSWORD_POOL[] =
"0123456789";
int poolSize = sizeof(PASSWORD_POOL) - 1;
char getRandChar()
{
return PASSWORD_POOL[rand() % poolSize];
}
int main()
{
srand(time(0));
string pass, input, msg;
int key;
Cipherer message;
ofstream outputFile;
ifstream inputFile;
outputFile.open("SecretMSG.txt");
cout << "Write a message: \n";
getline(cin, msg);
cout << "Choose the displacement of the message (0-25): ";
cin >> key;
message.setDisplacer(key);
message.msgEncripter(msg, key);
outputFile << msg;
outputFile.close();
for (int count = 0; count < 1; count++)
{
for (int i = 0; i <= 7; i++)
{
pass += getRandChar();
}
cout << pass << endl;
}
cout << "Input password " << pass << " ";
cin >> input;
if (input == pass)
{
//Make a local variable to read file
string encryptedMessage;
inputFile.open("SecretMSG.txt");
inputFile >> encryptedMessage;
inputFile.close();
cout << message.getMessage() << endl;
cout << "If you wish to decrypt the message, type in the password once again " << pass << ": ";
cin >> input;
if (input == pass)
{
message.msgDecripter(encryptedMessage);
cout << message.getDecription() << endl;
}
else
{
exit(EXIT_FAILURE);
}
}
else
{
exit(EXIT_FAILURE);
}
system("pause");
return 0;
}
In msgDecripter your string decriptedMsg creates a string with the size 0, so any decriptedMsg[i] = is undefined behavior.
In your msgEncripter you write string encriptedMsg = msg;, and because you create a copy of mgs the encriptedMsg has the same size.
So either you do string decriptedMsg = msg or string decriptedMsg = std::string(msg.size(), ' ');
But a more c++ like approach would be to use transform.
string encriptedMsg = msg;
std::transform(encriptedMsg.begin(), encriptedMsg.end(), encriptedMsg.begin(),
[](unsigned char c) -> unsigned char {
if( c == ' ') {
return c;
} else {
// ... your other encrypting logic ...
}
});
Or using msg as source and an empty string as target and utilize std::back_inserter.

How to get string from xml in COM

I have one array like this:
static WCHAR FilesToShow[][100] = { { L"start.cmd" },{ L"image.xml" }, { L"xyz" }};
as you see that there is "xyz" which I have to replace with some unique name. For this I have to read image.xml file.
Please can you tell me how can I do this.
I wrote a method like this:
PRIVATE WCHAR GetSystemName(WCHAR *pName)
{
WCHAR line;
wfstream in("image.xml");
WCHAR tmp;
bool begin_tag = false;
while (getline(in,line))
{
// strip whitespaces from the beginning
for (int i = 0; i < line.length(); i++)
{
if (line[i] == ' ' && tmp.size() == 0)
{
}
else
{
tmp += line[i];
}
}
if (wcswcs(tmp,"<SystemPath>") != NULL)
{
???????? how to get "vikash" from here <SystemPath>C:\Users\rs_user\Documents\RobotStudio\Systems\vikash</SystemPath>
}
else
{
continue;
}
}
return tmp;
}
I'm getting exception for wfstream, getline and line.length() method.
I have included fstream.h header file but I think It's not supported in COM.
Please help me how to solve this issue without parsing xml file.
If your xml-file is simple enough so that there is only a single tag with given name, you could do it like this:
#include <string>
#include <sstream>
#include <iostream>
std::wstring get_value(std::wistream & in, std::wstring const & tagname)
{
std::wstring text = std::wstring(std::istreambuf_iterator<std::wstring::value_type>(in),
std::istreambuf_iterator<std::wstring::value_type>());
std::wstring start_tag = L"<" + tagname + L">";
std::wstring end_tag = L"</" + tagname + L">";
std::wstring::size_type start = text.find(start_tag);
if (start == std::wstring::npos)
{
throw 123;
}
start += start_tag.length();
std::wstring::size_type end = text.find(end_tag);
if (end == std::wstring::npos)
{
throw 123;
}
return text.substr(start, end - start);
}
std::wstring get_substr_after(std::wstring const & str, wchar_t delim)
{
std::wstring::size_type pos = str.rfind(delim);
if (pos == std::wstring::npos)
{
throw 123;
}
return str.substr(pos + 1);
}
void stackoverflow()
{
std::wstring text(L"<foo>\n<bar>abc/def/ghi</bar>\n<baz>123/456/789</baz>\n</foo>\n");
std::wistringstream wiss(text);
std::wcout << text << std::endl;
std::wcout << get_substr_after(get_value(wiss, std::wstring(L"bar")), L'/') << std::endl;
}
The output of this program is:
<foo>
<bar>abc/def/ghi</bar>
<baz>123/456/789</baz>
</foo>
ghi
I hope that answered your question.
you have several issues here.
what you are getting are compiler errors and not exceptions
the header file to include is 'fstream' not 'fstream.h'.
make sure you have a line saying using namespace std;
You are declaring line as a variable of type WCHAR, so it is a single wide character, which surely is not a wstring object. Therefore line.length() is incorrect.
Why are you mixing C (wcswcs()) and C++ (STL) ? maybe you should re-design your function signature.
However, try the below function. I have modified the signature to return a pointer to WCHAR, and place the requested string in the buffer space provided by pName. I added a check to verify that the buffer is large enough to fit the name and the terminating NULL character.
WCHAR* GetSystemName(WCHAR *pName, size_t buflen)
{
wstring line;
wifstream in("image.xml");
WCHAR* tmp = NULL;
while (getline(in,line))
{
// strip whitespaces from the beginning
size_t beg_non_whitespace = line.find_first_not_of(L" \t");
if (beg_non_whitespace != wstring::npos)
{
line = line.substr( beg_non_whitespace );
}
size_t beg_system_path = line.find( L"<SystemPath>" );
if ( beg_system_path != wstring::npos )
{
// strip the tags (assuming closing tag is present)
size_t beg_data = beg_system_path + wstring( L"<SystemPath>" ).length();
size_t range = line.find( L"</SystemPath>" ) - beg_data;
line = line.substr( beg_data, range );
// get file name
size_t pos_last_backslash = line.find_last_of( L'\\' );
if ( pos_last_backslash != wstring::npos )
{
line = line.substr( pos_last_backslash + 1 );
if ( buflen <= line.length() )
{
// ERROR: pName buffer is not large enough to fit the string + terminating NULL character.
return NULL;
}
wcscpy( pName, line.c_str() );
tmp = pName;
break;
}
}
}
return tmp;
}
EDIT: Moreover, if you are using and/or parsing XML in other areas of your program, I strongly suggest using an XML parsing library such as Xerces-C or libXml2.
Thank you all for your answer. Here I got solution of my question.
PRIVATE WCHAR* GetNewSystemName()
{
WCHAR line[756];
WCHAR tempBuffer[100];
CComBSTR path = CurrentFolder.Path();
CComBSTR imagePath1 = L"rimageinfo.xml";
path.AppendBSTR(imagePath1);
std::wfstream in(path);
WCHAR tmp[756];
in.getline(line, 756);
WCHAR* buffer;
buffer = wcswcs(line, L"<SystemPath>");
WCHAR *dest = wcsstr(buffer, L"</SystemPath>");
int pos;
pos = dest - buffer;
unsigned int i = 0;
if (wcswcs(buffer,L"<SystemPath>") != NULL && wcswcs(buffer,L"</SystemPath>") != NULL)
{
for (; i < pos; i++)
{
if (buffer[i] == ' ' && sizeof(tmp) == 0)
{
}
else
{
tmp[i] = buffer[i];
}
}
tmp[i] = NULL;
//break;
}
int j = i;
for (; j > 0; j--)
{
if (tmp[j] == '\\')
{
break;
}
}
j++;
int k = 0;
for (; j < i ; j++)
{
System_Name[k] = tmp[j];
k++;
}
System_Name[k] = NULL;
return System_Name;

Simple read from text file algorithm doesn't work

I have a text file that contains keys and values like this:
keyOne=1
keyTwo=734
keyThree=22.3
keyFour=5
The keys are just lower-case and upper-case letters like in my example. The values are either integers or floats. Each key and value is separated by an equals sign (=). Now I want to read the values into variables I have in my program.
This is the code I have tried to read the values:
(I omitted the part where I store the values in my program's variables, and just print them out now for demonstration.)
std::fstream file(optionsFile, std::fstream::in);
if (file.good()) {
int begin;
int end;
std::string line;
while(std::getline(file, line)) {
// find the position of the value in the line
for (unsigned int i = 0; i < line.length(); i++) {
if (line.at(i) == '=') {
begin = i + 1;
end = line.length();
break;
}
}
// build the string... it starts at <begin> and ends at <end>
const char *string = "";
for (int i = begin; i < end; i++) {
string += line.at(i);
}
// only gibberish is printed in the following line :(
std::cout << "string=" << string << std::endl;
}
}
I don't understand why it won't print the value.. instead only weird stuff or even nothing is printed
Please help this broke my spirit so hard :(
You are using C-style strings (char arrays) without properly allocated memory, and you are just manipulating with the pointer, so you are not appending characters into your string:
// build the string... it starts at <begin> and ends at <end>
const char *string = "";
for (int i = begin; i < end; i++) {
string += line.at(i);
}
Use std::string instead:
/// build the string... it starts at <begin> and ends at <end>
std::string str;
for (int i = begin; i < end; i++) {
str += line.at(i);
}
Or allocate memory by hand, use the proper indexing, terminate the string with '\0' character and don't forget to delete the string after you don't need it anymore:
char *string = new char[end - begin + 1];
int j = 0;
for (int i = begin; i < end; i++) {
string[j++] = line.at(i);
}
// Don't forget to end the string!
string[j] = '\0';
// Don't forget to delete string afterwards!
delete [] string;
So, just use std::string.
Edit Why did you mix C strings and std::string in the first place?
As was already mentioned, native string types in c/c++ do not support straightforward concatenation since they are essentially pointers to some preallocated memory. You should always use std::string when a string is supposed to be mutable.
Btw, think about the following refactoring:
void process_option (const std::string& a_key, const std::string& a_value)
{
std::cout << a_key << " <-- " << a_value << std::endl;
}
void read_options (std::istream& a_in, const char* a_source)
{
int line_n = 0;
std::string line;
while (std::getline(a_in, line))
{
++ line_n;
std::string::size_type p = line. find('=');
if (p == line. npos)
{
// invalid_entry(a_source, line_n);
continue;
}
process_option(
line. substr(0, p), // key
line. substr(p + 1, line. find_first_of("\t\r\n", p + 1)) // value
);
}
}
void read_options (const char* a_filename)
{
std::ifstream file(a_filename);
if (! file)
{
// read_error(a_filename);
return;
}
read_options(file, a_filename);
file. close();
}
void read_options (const std::string& a_filename)
{
read_options(a_filename. c_str());
}

Output wrong. Possible strncpy issue?

So, I'm trying to get this code to parse each line inputted from the file into individual tokens, then add each one in turn to tklist array. Then the main just prints out each token. It's printing blanks though, and when I step into the code it looks like the strncpy isn't working. Any ideas what the issue is? I get no errors.
Here's the main function:
#include <iostream>
#include <fstream>
using namespace std;
#include "definitions.h"
#include "system_utilities.h"
int main()
{
ifstream inFile;
char line[MAX_CMD_LINE_LENGTH];
char* token[MAX_TOKENS_ON_A_LINE];
int numtokens;
system("pwd");
inFile.open("p4input.txt", ios::in);
if(inFile.fail()) {
cout << "Could not open input file. Program terminating.\n\n";
return 0;
}
while (!inFile.eof())
{
inFile.getline(line, 255);
line[strlen(line)+1] = '\0';
numtokens = parseCommandLine(line, token);
int t;
for (t=1; t <= numtokens; t++) {
cout << "Token "<< t << ": " << token[t-1] << "\n";
}
}
return 0;
}
And here's the parseCommandLine function:
int parseCommandLine(char cline[], char *tklist[]){
int i;
int length; //length of line
int count = 0; //counts number of tokens
int toklength = 0; //counts the length of each token
length = strlen(cline);
for (i=0; i < length; i++) { //go to first character of each token
if (((cline[i] != ' ' && cline[i-1]==' ') || i == 0)&& cline[i]!= '"') {
while ((cline[i]!=' ')&& (cline[i] != '\0') && (cline[i] != '\r')){
toklength++;
i++;
}
//---------------
tklist[count] = (char *) malloc( toklength +1);
strncpy(tklist[count], &cline[i-toklength], toklength);
//--------------
count ++;
toklength = 0;
}
if (cline[i] == '"') {
do {
toklength++;
i++;
if (cline[i] == ' ') {
toklength--;
}
} while (cline[i]!='"');
//--------------
tklist[count] = (char *) malloc( toklength +1);
strncpy(tklist[count], &cline[i-toklength], toklength);
//--------------
count ++;
toklength = 0;
}
}
int j;
for (j = 0; j < count; j++) {
free( (void *)tklist[j] );
}
return count;
}
Like I said, when I debug it looks like a problem with copying, but I'm a beginner so I suspect I'm doing something wrong.
Thanks for any help you can give!!
Try something like
tklist[count][toklength]='\0';
after
strncpy(tklist[count], &cline[i-toklength], toklength);
strncpy() does not necessarily add a null terminator for you. strncpy needs some care to use safely.
No null-character is implicitly appended at the end of destination if
source is longer than num..
Just for starters... there are other deeper issues as mentioned in comments.
To start with the generic equivalent of malloc/free is new/delete (heap memory allocation).
Second you seem to be confusing strings and c_strings (good old char*). getline uses strings, your parsing function uses c_strings they are not the same things and there is .c_str() a member function of string to do the conversion.
So, I'm trying to get this code to parse each line inputted from the
file into individual tokens, then add each one in turn to tklist
array.
For
each line inputted from the file
use
std::ifstream ifs;
std::string s;
/**/
std::getline(ifs, s);
adopted to your loop.
To
parse [..] into individual tokens
look how
std::string
can help you on that task (or use boost::tokenizer).
And this
then add each [token] in turn to tklist array.
almost cries for std::list or std::vector instead of a plain C array, the choice, which container to use depends e.g. on what you intend to do with the tokens found.