Here's my code
#include <cryptopp/hex.h>
#include <string>
#include <iostream>
void hexlify(CryptoPP::byte* bytes, std::string &hex_string, size_t size)
{
CryptoPP::StringSource ss(bytes, size, true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(hex_string)));
}
void unhexlify(std::string hex_string, CryptoPP::byte* &bytes)
{
std::string decoded;
CryptoPP::StringSource ss(hex_string, true, new CryptoPP::HexDecoder(new CryptoPP::StringSink(decoded)));
std::cout << decoded + "\n"; // For testing
bytes = (CryptoPP::byte*)decoded.data();
}
int main()
{
std::string seed = "BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60";
std::cout << "\n" + seed + "\n";
CryptoPP::byte* b;
unhexlify(seed, b);
std::string s;
hexlify(b, s, 32);
std::cout << s;
std::cout << "\n\n";
}
It should take the 32-byte, 64-character hex string seed, print it, convert it into bytes, then convert it back into a hex string (s) and print it. I also have it print the decoded string in the unhexlify function.
My expectation is for the output to look like this:
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
The first line (seed) and the third line (s, the seed converted into bytes and back) should be the same. And very rarely, that's exactly what happens. However, most of the time the first and third lines are completely different.
What's weird is that I made zero changes to the code, and I didn't even recompile it. But every time I run the executable, it says something different. What's even weirder is that the third line is different every time I run it. Again, it happens even though I'm running the same executable without changing the code or recompiling. Here are the outputs from 5 runs:
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205BC0AE8B7F0000AB7615AD06EA16A2889A960301000000189C960301000000
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205B40C2B87F0000AB7615AD06EA16A288FA9B060100000018FC9B0601000000
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205BC07DA67F0000AB7615AD06EA16A2885A6C0B01000000185C6C0B01000000
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205BC06EB47F0000AB7615AD06EA16A288DAAE090100000018DCAE0901000000
BF0F3123B21A60E5AB7615AD06EA16A2BD44D84CED4DCC10AA0413127F87DC60
?1#?`?v????D?L?M????`
205BC0F9EB7F0000AB7615AD06EA16A288DAF5010100000018DCF50101000000
The second line is the same every time, so I know the problem is with the hexlify function and/or the Crypto++ HexEncoder. Also, the section AB7615AD06EA16A2 always matches in both seed and s. The section that does match goes from the 17th character to the 32nd character. That always happens for every seed I try. But everything else is usually different.
I don't understand why it's not encoding the bytes into a hex string properly. And I don't understand why it rarely does work even if I made no changes to the code. And I especially don't understand how the output can be different every time I run the same compiled code. What is going on here?
void unhexlify(std::string hex_string, CryptoPP::byte* &bytes)
{
std::string decoded;
CryptoPP::StringSource ss(hex_string, true, new CryptoPP::HexDecoder(new CryptoPP::StringSink(decoded)));
std::cout << decoded + "\n"; // For testing
bytes = (CryptoPP::byte*)decoded.data(); // <--
}
You return the pointer to the buffer owned by the local variable decoded that dies after function exit. You get the undefined behavior with following passing the dangling pointer to hexlify. To fix the issue return string from std::string unhexlify(std::string hex_string) and call hexlify(bytes.data(), s. bytes.size()).
This function looks suspicious:
void unhexlify(std::string hex_string, CryptoPP::byte* &bytes)
{
std::string decoded;
// stuff added to decoded, maybe...
bytes = (CryptoPP::byte*)decoded.data();
}
decoded is a local variable that is destroyed as the function exits, but you're making bytes point to the internal data of it, causing a dangling pointer (which is undefined behavior, and differing output is explained by that.)
You should just return decoded as the return value (by value), and store it on the caller's stack. Then set bytes to its data after this function returns in the calling code.
Related
I have created a program that randomly assigns roles(jobs) to members of a certain house using file input / output.. It builds successfully, but when using cout and I actually see the results, I can see why the program is not working.
Here is the snippet of code I believe something is wrong with :
std::string foo = std::string("Preferences/") + std::to_string(members[random]) + "-Preferences";
cout << foo << endl;
And here is the members[random] array, it is randomly selecting members from this array and reviewing their available times and assigning them jobs based on their Preference input file.
unsigned const char members[22] =
{ 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v' };
I have created a random number picker that goes through 0-21 and assigns the value it creates to variable random. So, in essence, it is members[random] and completely random.
Here is the output I get in my terminal.
Preferences/116-Preferences
But I set the output to do Preferences/ member[random] -Preferences.
It is accessing a number and not my array chars.
I created a cout << members[random]; right below it, and every time I run the program, I get
Preferences/107-Preferences <---- A random number every time
k <---- random letter every time.
So I know it must be accessing my random functions, but assigned it to numbers! How do I fix this so my proper output can be :
Preferences/t-Preferences
Please help me, and thanks!
"The more you overthink the plumbing, the easier it is to stop up
the drain" - Scotty, Star Trek III
Declaring members to be unsigned chars does not accomplish anything useful. A simple char will suffice. std::string already implements an overloaded + operator that takes a char parameter, so it's much easier than you thought it would be:
const char members[22] = {
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v' };
// ...
std::string foo = std::string("Preferences/") + members[random]
+ "-Preferences";
There is no ::std::to_string(char), only (among less close) ::std::to_string(int). So your character is actually converted to its numerical representation and you get your unwanted result.
Try instead
std::string foo("Preferences/");
foo = foo.append(1, members[random]).append("-Preferences");
Variant using string streams:
ostringstream oss;
oss << "Preferences/" << members[random] << "-Preferences";
// get your string via:
oss.str();
Here is what I should do
making a program that reads a text file that contains encrypted message and crack it it is kind of close to substitution cipher where I should swap swap each letter back with another meaning like shifting B back to A if its being shifted by one, and try comparing shifted words by some common used words to find if 2 of the common words have been found on the shifted ones
ex: shift the word by one
check when you shifted it is there 2 common words found?
no keep going
yes means thats it stop shifting
Now this issue here which makes the program hard for me is that I do not have a key to be entered it would've been awesome if I had it.
3 issues I am having now, is in my void function it will not print anything,
the second issue is, even if I fix my issue (I know this because in my function I have added something to convert string to c_string) and the issue is it will not shift until it finds the words I am looking which I have declared in string "Common[]"
3rd issue is whenever I compile I get an error invalid conversion from const char** to char comparison between signed and unsigned integer expressions
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <ctype.h>
using namespace std;
void makeshift (string encrypt, int key)
{
for (int i = 0 ; i<encrypt.size();i++)
{
cout<<encrypt<<endl; // to see what is in file way to debug
const char *encryptedc; // this is to convert string to cstring
encryptedc = encrypt.c_str();
encryptedc-=key;
cout<<"decrypted message is "<<encryptedc<<endl;
}
}
int main (int argc, char* argv[])
{
// this will make me compare between encrypted message to check if it
// contains this words or not!
const char* common[]{"the","and","in","he","with","that","as","at","do"};
string encrypted; // The encrypted message gotten from file
ifstream message(argv[1]); // get file name typed by user
if(message.is_open()) // check if file is open
{
while (!message.eof()) // check if we reached end of file
{
// get the whole line in file
getline(message,encrypted);
///loop throgh it to store numbers in declared varibles
for (int i = 0 ; i < encrypted.size();i++)
{
makeshift(encrypted,i);
// here is where the error occurs which is "invalid conversion
// from const char to char
if(encrypted.find(common) != -1)
{
cout<<"found common"<<endl;
cout<<encrypted<<endl;
break;
}
}
}
}
}
Compile error
First, you say you're getting a compile error on this line:
if(encrypted.find(common) != -1)
The reason for that is because find() expects its argument to be a string, but common is an array of strings. In other words, find() can only search for one word at a time. It can't search for a whole list of words.
To fix that, you'll want to write a loop and check one word each iteration.
Shift function
Next up is the makeshift function. A couple of suggestions there.
There's no real need to call c_str(). You can change encrypted directly by modifying each encrypted[i] in the loop.
It needs to return the result. If you modify encrypted but do not return it then the caller won't see the result.
The printouts ought to be outside the loop. Presumably you just want to see the before and after results after you've decrypted the entire string.
Here's what it looks like with those issues addressed:
string makeshift (string encrypt, int key)
{
cout << encrypt << endl; // to see what is in file way to debug
for (int i = 0 ; i<encrypt.size();i++)
{
encrypted[i] -= key;
}
cout << "decrypted message is " << encryptedc << endl;
return encrypted;
}
And then you would call it as:
string decrypted = makeshift(encrypted, i);
By the way, I'm not sure if the encrypted[i] -= key; line is completely correct. My guess is you'll need to handle wraparound. Like if you subtract 3 from the letter "A" you should probably wrap around to "X", correct? If so, I'll leave that as a TODO for you.
I/O error checking
Lastly, let's talk about I/O. Specifically, this bit of code:
ifstream message(argv[1]); // get file name typed by user
if(message.is_open()) // check if file is open
{
while (!message.eof()) // check if we reached end of file
{
// get the whole line in file
getline(message,encrypted);
...
}
}
A good practice in C++ is to check the results of I/O operations (e.g. getline). After you read a line you need to check that the read actually worked. You don't want to continue on if getline() failed (say, because it hit end-of-file).
Conveniently, if you write while (getline(...)) then that'll do a whole bunch of things all at once--it'll check if the file is open, if it's at EOF, and it'll read lines and tell you if the reads were successful. That means you can replace the stuff above with a single loop:
ifstream message(argv[1]); // get file name typed by user
while (getline(message, encrypted))
{
...
}
You are passing the value of encrypted to makeshift, so whatever you do in makeshift function will not change the encrypted in main function
you have 2 solutions here:
you can either pass the pointer of encrypted to the makeshift function
void makeshift (string* encrypt, int key){
for (int i = 0 ; i<encrypt.size();i++)
{ cout<<encrypt->c_str()<<endl; // to see what is in file way to debug
const char *encryptedc; // this is to convert string to cstring
encryptedc = encrypt->c_str();
encryptedc-=key;
cout<<"decrypted message is "<<encryptedc<<endl;
}
}
int main (int argc, char* argv[]){
...
makeshift(&encrypted, i);
...
}
Or you can return the value of encryptedc and assign it back to encrypted in main function
string makeshift (string encrypt, int key){
for (int i = 0 ; i<encrypt.size();i++)
{ cout<<encrypt.c_str()<<endl; // to see what is in file way to debug
const char *encryptedc; // this is to convert string to cstring
encryptedc = encrypt.c_str();
encryptedc-=key;
cout<<"decrypted message is "<<encryptedc<<endl;
return encryptedc; //you can assign const char* to string
}
}
int main (int argc, char* argv[]){
...
encrypted = makeshift(encrypted, i);
...
}
I met a strange problem when trying to get the result of a string’s function c_str() whose result is inconsistent with g++.
There is a function called Test to return a string instance. And I want to use a char* type to store the result (it’s needed). As you can see the function is simple return a string “resultstring”. But when I try to get the result something strange happened.
The result I got is “” in part two. The part one and part three both return the “resultstring”. While that’s in Visual Studio. The three part of the same code compiled with g++ both return the “result string. Let’s just as well see the result first:
result of vs:
address:16841988
resultstring
address:16842096
"here is a empty line"
address:16842060
address:16842144
address:16842396
address:16842396
resultstring
result of g++
address:5705156
resultstring
address:5705156
resultstring
address:5705156
address:5705196
address:5705156
address:5705156
resultstring
The code is very simple list below:
#include <iostream>
#include <string>
using namespace std;
string Test()
{
char a[64] = "resultstring";
return string(a);
}
int main(void)
{
//part one
cout << "address:"<< (unsigned)Test().c_str() << endl;
cout << Test().c_str() << endl;
//part two
char *j = const_cast<char*>(Test().c_str());
cout << "address:"<< (unsigned)Test().c_str() << endl;
cout << j << endl;
cout << "address:" << (unsigned)j <<endl;
//part three
string h3 = Test();
char* j2 = const_cast<char*>(h3.c_str());
cout << "address:"<< (unsigned)Test().c_str() << endl;
cout << "address:"<< (unsigned)h3.c_str() << endl;
cout << "address:" << (unsigned)j2 <<endl;
cout << j2 <<endl;
getchar();
return 0;
}
Now I have three questions.
1st, why the result complied by g++ returns all resultstring while the result of Visual Studio returns all resultstring except for variable j? If you debug into this you’ll find that VC++ only set the address of j2 like 00 65 73 75 … which is esultstring with a 00 begin address. And it is not strange that we’ll get “”. It’s just like char* str = "\0something else" you’ll always get "". But the question is why does this happen only with j?
2nd, why does one of the addresses of the (unsigned) Test ().c_str() is different with others? If we remove the line string h3 = Test () the address will be all the same.
3rd, Is it the “correct” behavior of Visual Studio returning “” value of variable j? why it is different with g++?
Looking forward to your replies.
Regards,
Kevin
This is totally flawed. You create and destroy a temporary string every time you call Test(). Any attempt to access memory using pointer returned by Test().c_str() after temporary was destroyed makes no sense - memory was freed already. It MIGHT have the old values (if nothing is written there before the access), but it might have anything as well (if it is reused before the access). It's Undefined Behavior.
In case of VC++ it is overwritten once and is not in other cases. With GCC - it's never overwritten. But this is pure chance. Once again - it's UB.
You have undefined behavior. The std::string returned by Test() is a temporary and the pointer returned by c_str() (stored in j) is no longer valid after the lifetime of the temporary ends. This means that anything can happen. The array the pointer points to may contain garbage, it may be the original string or the implementation may have null terminated the beginning of it. Accessing it may cause a segmentation fault or it may allow you to access the original string data. This can and usually does vary between different compilers and implementations of the standard library.
char *j = const_cast<char*>(Test().c_str());
// The contents pointed to by j are no longer valid and access that content
// is undefined behavior
cout << "address:"<< (unsigned)Test().c_str() << endl;
The address is different between calls to Test() because it returns a temporary each time you call it. Some compilers may optimize this and/or the allocation of data may get the same block of memory but it is not guaranteed to be the same.
I have a problem that I don't understand in C++:
I got a unsigned char* as a result from a method call. if I iterate the char* to display the datas everything is fine, but when I just print the datas there are not the same values displayed.
Here is my code sample:
unsigned char returning[32];
for(int i=0;i<32;i++){
returning[i] = result[i];
std::cout << returning[i];//return the good values
}
std::cout << "\n";
std::cout << returning << "\n";
//the first one are the good values, and then there are wrong
Someone could explain me this strange behavior?
tl;dr:
unsigned char returning[33];
returning[32] = '\0';
fixed.
Explanation:
The first loop will print every value in "returning". The second piece of code will only return the values until it hits a value which is zero. And then it stops, because a zero in a char array is interpreted as an end of line character.
Alternatively, if the there is no zero in "returning" anywhere, the second piece of code will continue to write random values until it does hit a zero.
First of all in returning array, you are just assigning values till 31st index which is wrong. Last byte of that should be null terminated \0.
std::cout << returning[i] This statement will read the ASCII value from that particular and it will print the corresponding character.
std::cout << returning But this statement will keep on reading bytes till it reaches \0. In your case returning array is not NULL terminated. So in this buffer overflow will happen and it will print first 32 byte proper characters and then it will start printing some other characters(may be not readable formal also). If \0 never comes in the further bytes then it will surely tries to go beyond that segment at that time application will crash.
Sorry noob question couldn't figure out which functions to use here.
http://www.cplusplus.com/reference/string/string/
Was gonna convert to c-string and write a whole mess of code but I bet there's a good way to do this.
Just trying to append A, B, and C to the end of a string and add it to queue, keep getting segmentation fault tho that terminates in a ??() function after string::assign() (according to debugger)
string a, b, c;
a = s.append("A");
b = s.append("B");
c = s.append("C");
q.add(a);
q.add(b);
q.add(c);
this too ends with segmentation fault.
q.add(s + "A");
q.add(s + "B");
q.add(s + "C");
Also problem with this is it uses the old, so I'll get:
teststringA
teststringAB
teststringABC
instead of expected
teststringA
teststringB
teststringC
What is a segmentation fault?
When your program runs, it has access to certain portions of memory. First, you have local variables in each of your functions; these are stored in the stack. Second, you may have some memory, allocated during runtime (using either malloc, in C, or new, in C++), stored on the heap (you may also hear it called the "free store"). Your program is only allowed to touch memory that belongs to it -- the memory previously mentioned. Any access outside that area will cause a segmentation fault. Segmentation faults are commonly referred to as segfaults.
your second problem is
q.add(s + "A"); // appends A to s hence teststringA
q.add(s + "B"); // teststringA + B hence teststringAB
q.add(s + "C"); //teststringAB + C hence teststringABC
refer document at http://www.cplusplus.com/reference/string/string/append/
Append to string
The current string content is extended by adding an additional appending string at its end.
The arguments passed to the function determine this appending string:
string& append ( const string& str );
Appends a copy of str.
example
// appending to string
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str;
string str2="Writing ";
string str3="print 10 and then 5 more";
// used in the same order as described above:
str.append(str2); // "Writing "
str.append(str3,6,3); // "10 "
str.append("dots are cool",5); // "dots "
str.append("here: "); // "here: "
str.append(10,'.'); // ".........."
str.append(str3.begin()+8,str3.end()); // " and then 5 more"
str.append<int>(5,0x2E); // "....."
cout << str << endl;
return 0;
}
Output:
Writing 10 dots here: .......... and then 5 more.....