Convert hex string to unsigned char in C++ - c++

How can I convert it? And I want the converted result to 1.
#include <iostream>
#include <string>
int main(int argc, const char * argv[]) {
std::string s = "0x00";
// insert code here...
unsigned char* str_hex = (unsigned char*)s.c_str();
unsigned char target = 0x00;
std::cout << "result: " << (*str_hex == target) << "\n";
return 0;
}

Like this: // #include <string>
std::string s = "0x4A";
unsigned char ch = std::stoul(s, nullptr, 16); // 'J' (Since C++11)
Or like this: // #include <cstdio>
std::string s = "0x4B";
unsigned char ch = '\0';
sscanf(s.c_str(), "%x", &ch); // 'K' (C library function)

Related

OpenSsl + gost engine decryption fail (or encryption)

I am trying to write an encryption - decryption programm, which uses gost89 to encrypt and decrypt data. Everything works fine, but when I try to cast QString to unsigned char and use it as a key, the programm fails to decrypt.
The code:
#include <cstdio>
#include <iostream>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <fstream>
#include <QString>
#include <QDebug>
#include <QFile>
using std::cerr;
using std::endl;
void encryptdata(QString pass, QString data){
OPENSSL_add_all_algorithms_conf();
ENGINE *engine_gost = ENGINE_by_id("gost");
const EVP_CIPHER * cipher_gost = EVP_get_cipherbyname("gost89");
unsigned char *key = (unsigned char * )"password";
qDebug() << (char*)key;
unsigned char * iv = (unsigned char * ) "12345678";
unsigned char *text = (unsigned char*)"Hello World";
int text_len = 11;
unsigned char ciph[512];
int ciph_len = 0;
EVP_CIPHER_CTX * ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
int init = EVP_EncryptInit_ex(ctx, cipher_gost, engine_gost, key, iv);
int enc = EVP_EncryptUpdate(ctx, ciph, &ciph_len, text, text_len);
std::ofstream myfile;
myfile.open ("example.bin");
for (int i = 0; i < text_len; i++){
myfile << ciph[i];
}
myfile.close();
EVP_CIPHER_CTX_free(ctx);
}
void decryptdata(){
OPENSSL_add_all_algorithms_conf();
ENGINE *engine_gost1 = ENGINE_by_id("gost");
const EVP_CIPHER * cipher_gost1 = EVP_get_cipherbyname("gost89");
unsigned char * key1 = (unsigned char * ) "password";
qDebug() << (char*)key1;
unsigned char * iv1 = (unsigned char * ) "12345678";
unsigned char text1[512];
int text_len1 = 11;
unsigned char ciph1[512];
int ciph_len1 = 0;
std::ifstream yourfile;
yourfile.open ("example.bin");
yourfile >> text1;
yourfile.close();
qDebug() << text1;
EVP_CIPHER_CTX * ctx1 = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx1);
int init = EVP_DecryptInit_ex(ctx1, cipher_gost1, engine_gost1, key1, iv1);
int enc = EVP_DecryptUpdate(ctx1, ciph1, &ciph_len1, text1, text_len1);
//int enc1 = EVP_DecryptFinal(ctx, ciph, &ciph_len);
for (int i = 0; i < text_len1; i++){
std::cout << ciph1[i];
}
std::cout << std::endl;
EVP_CIPHER_CTX_free(ctx1);
}
int main(){
//unsigned char t[512] = {'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
QString pss = "password";
QString dat = "Hello World";
encryptdata(pss, dat);
decryptdata();
}
I've tried lots of different casting methods, but they did not help
unsigned char* - implies it's a set of bytes that's read/write.
However "password" is const char* - it's a readonly string literal.
It's dangerous to cast "password" to unsigned char*.
You need to spend more effort in understanding memory management and read/writable memory.
Because you want it come from a QString, I would recommend the following steps:
Consider using QString toUtf8() to convert the QString to a QByteArray
Consider either (1) providing unsigned char* raw access to the QByteArray(), e.g. via data() or, (2) to copy it out to a allocated memory buffer.
Finally completed the task. Yeah, the problem was really in my stupid lector, who wrongly casted string to unsigned char.
The key size must be EXACTLY 256 bit(unsigned char key[32]), otherwise it is going to **** up everything.

Identify Memory Corruption

I'm having trouble identifying a possible source of memory corruption in the following code. Is it due to the fact that I don't call the free() function on char *stringToAdd?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <iostream>
using namespace std;
#define MAX 1024
char* add_strings(char *stringOne, char *stringTwo);
int main() {
char s = 'x';
char *stringOne = &s;
char *stringTwo = new char[1025]();
char *final = add_strings(stringOne, stringTwo);
return 0;
}
char* add_strings(char *stringOne, char *stringTwo) {
unsigned int lengthOfStringOne = strlen(stringOne);
unsigned int lengthOfStringTwo = strlen(stringTwo);
cout << lengthOfStringOne << endl;
cout << lengthOfStringTwo << endl;
char *stringToAdd = lengthOfStringOne < lengthOfStringTwo ? stringOne : stringTwo;
unsigned int lengthOfAdd = lengthOfStringOne < lengthOfStringTwo ? lengthOfStringOne : lengthOfStringTwo;
char *final = static_cast<char*>(calloc(MAX, sizeof(char)));
unsigned int avgLengthOfStrings = (lengthOfStringOne + lengthOfStringTwo) / 2;
if (avgLengthOfStrings < MAX) {
strncat(final, stringToAdd, lengthOfAdd);
printf("DONE\n");
} else {
printf("Average length of both input strings exceeds liimit.\n");
free(final);
return NULL;
}
return final;
}

Convert *argv[] (command line parameters) to unsigned char vector

In C++ I'm trying to convert command line *argv[] pointer (3 arguments) to vector of unsigned chars i.e. mytest 148 64 127
I got a vector:
vector<unsigned char> msg;
Vector includes 3 unsigned chars : msg = {0, 0, 0}
When I trying to convert in this way,
unsigned char c1 = *argv[1];
unsigned char c2 = *argv[2];
unsigned char c3 = *argv[3];
msg = {c1, c2, c3}
I get only first character of these chars.
i.e.
In command line I enter : mytest 148 64 127
I get : 1, 6 and 1
I recommend creating a vector of strings:
#include <iostream>
#include <vector>
int
main(int argc, char *argv[]) {
std::vector<std::string> args;
for (int i = 1; i < argc; i++) {
args.push_back({ argv[i] });
}
for (auto a: args) {
std::cout << a << std::endl;
}
return 0;
}
Simplest is convert to using strings.
vector<string> msg;
If you really want unsigned chars, then you will need to do something like:
vector<vector <unsigned char>> msg;
Rather than copy the characters you can save pointers to argv by doing
vector<unsigned char *> msg;
msg.push_back(reinterpret_cast<unsigned char *>(argv[0]));
You are saving only the 1st char of each argument string into your vector.
unsigned char c1 = *argv[1];
Is the same as doing:
const char *str = argv[1];
unsigned char c1 = str[0]; // <-- 1st char only!
For what you are attempting, you need to instead parse each argument string as-is into the numeric value it represents, so that the argument strings "148" "64" "127" yield the integers 148 64 127. You can use std::stoi() or std::stol() for that, eg:
#include <vector>
#include <string>
//#include <cstdlib>
//#include <limits>
/*
static const int min_uc = std::numeric_limits<unsigned char>::min();
static const int max_uc = std::numeric_limits<unsigned char>::max();
*/
int main(int argc, char* argv[])
{
if (argc < 2)
{
// no arguments given, do something...
return 0;
}
std::vector<unsigned char> msg;
msg.reserve(argc-1);
for (int i = 1; i < argc; ++i)
{
int i = std::stoi(argv[i], nullptr, 0);
//int i = std::strtol(argv[i], nullptr, 0);
if ((i < 0) || (i > 255))
//if ((i < min_uc) || (i > max_uc))
{
// bad input, do something...
return 0;
}
msg.push_back(static_cast<unsigned char>(i));
}
// use msg as needed...
...
}

C++ OPENSSL - How to convert OPENSSL output to a readable text and store it to a variable (if possible)

I have the working code below using OPENSSL AES 256 CBC to encrypt/decrypt.
It is working but I am missing something really important that is to CONVERT the Encryption result to readable text and STORE it to a STRING variable if possible (for later use).
For example, I need to see something like this: UkV8ecEWh+b1Dz0ZdwMzFVFieCI5Ps3fxYrfqAoPmOY=
Trying hard to find how to do that and what format OPENSSL is throwing out from Encryption process. (binary format ??) See image attached.
ps. Don't worry about the hashes below. They are not in production.
Thanks in Advance!!
Here is my code so far:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
using namespace std;
// HEX PRINT
static void hex_print(const void* pv, size_t len)
{
const unsigned char* p = (const unsigned char*)pv;
if (NULL == pv)
printf("NULL");
else
{
size_t i = 0;
for (; i < len; ++i)
printf("%02X ", *p++);
}
printf("\n");
}
// Starting MAIN function
int main()
{
int keylength = 256;
unsigned char aes_key[] = "1Tb2lYkqstqbh9lPAbeWpQOs3seHk6cX";
// Message we want to encrypt
unsigned char aes_input[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 abcdefghijklmnopqrstuvwxyz";
size_t inputslength = sizeof(aes_input)-1; // -1 because we don't want to encrypt the \0 character
// initialization vector IV - same for Encryption and Decryption
unsigned char iv_enc[] = "JxebB512Gl3brfx4" ;
unsigned char iv_dec[] = "JxebB512Gl3brfx4" ;
// buffers for encryption and decryption
const size_t encslength = inputslength ;
unsigned char enc_out[257];
unsigned char dec_out[257];
memset(enc_out, 0, sizeof(enc_out));
memset(dec_out, 0, sizeof(dec_out));
//Encryption START
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(aes_key, keylength, &enc_key);
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT);
//Decryption START
AES_set_decrypt_key(aes_key, keylength, &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT);
// Printing Results
printf("original: \t");
hex_print(aes_input, sizeof(aes_input));
cout << aes_input << endl;
printf("encrypted: \t");
hex_print(enc_out, sizeof(enc_out));
cout << enc_out << endl;
printf("decrypt: \t");
hex_print(dec_out, sizeof(dec_out));
cout << dec_out << endl;
return 0;
}
Image of the Process
All Right. Thanks for the tips #RemyLebeau and #PaulSanders !!
I could resolve the issue using another tip from here -->
Base64 C++
Working REALLY fine now!!
Thanks Much!!
Here is the code for "encode" and "decode" Base64, just in case someone wants to do the same. Very usefull!!
typedef unsigned char uchar;
static const string b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static string base64_encode(const string &in) {
string out;
int val=0, valb=-6;
for (uchar c : in) {
val = (val<<8) + c;
valb += 8;
while (valb>=0) {
out.push_back(b[(val>>valb)&0x3F]);
valb-=6;
}
}
if (valb>-6) out.push_back(b[((val<<8)>>(valb+8))&0x3F]);
while (out.size()%4) out.push_back('=');
return out;
}
static string base64_decode(const string &in) {
string out;
vector<int> T(256,-1);
for (int i=0; i<64; i++) T[b[i]] = i;
int val=0, valb=-8;
for (uchar c : in) {
if (T[c] == -1) break;
val = (val<<6) + T[c];
valb += 6;
if (valb>=0) {
out.push_back(char((val>>valb)&0xFF));
valb-=8;
}
}
return out;
}

What's the correct way to add a character array to a constant character array in C++?

What's the correct way to add a character array to a constant character array in C++?
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int pathSize = 0;
char* pathEnd = &argv[0][0];
while(argv[0][pathSize] != '\0') {
if(argv[0][pathSize++] == '/')
pathEnd = &argv[0][0] + pathSize;
}
pathSize = pathEnd - &argv[0][0];
char *path = new char[pathSize];
for(int i = 0; i < pathSize; i++)
path[i] = argv[0][i];
cout << "Documents Path: " << path + "docs/" << endl; // Line Of Interest
delete[] path;
return 0;
}
This code outputs:
Documents Path: �\
Using 'path' instead of '*path' will give me the compile error:
invalid operands of types ‘char*’ and ‘const char [6]’ to binary ‘operator+’
May I suggest using C++ to begin with, and (Boost) Filesystem for maximum benefits:
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;
int main(int argc, const char *argv[])
{
const std::vector<std::string> args { argv, argv+argc };
path program(args.front());
program = canonical(program);
std::cout << (program.parent_path() / "docs").native();
}
This will use the platform's path separator, know how to translate 'funny' paths (e.g. containing ..\..\, or UNC paths).
Something like this should do it (totally untested):
const char* end = strrchr(argv[0], '/');
std::string docpath = end ? std::string(argv[0], end) : std::string(".");
docpath += '/docs/';
Your way:
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int pathSize = 0;
char* pathEnd = &argv[0][0];
while(argv[0][pathSize] != '\0') {
if(argv[0][pathSize++] == '/')
pathEnd = &argv[0][0] + pathSize;
}
pathSize = pathEnd - &argv[0][0];
char *path = new char[pathSize + 5]; //make room for "docs/"
for(int i = 0; i < pathSize; i++)
path[i] = argv[0][i];
char append[] = "docs/";
for(int i = 0; i < 5; i++)
path[pathSize+i] = append[i];
cout << "Documents Path: " << path << endl;
function_expecting_charptr(path);
delete[] path;
return 0;
}
Sane C way:
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
char* pathEnd = strrchr(argv[0], '/');
if (pathEnd == NULL)
pathEnd = argv[0];
int pathSize = (pathEnd-argv[0]) + 5; //room for "docs/"
char *path = new char[pathSize];
if (pathSize)
strncpy(path, argv[0], pathSize+1);
strcat(path, "docs/");
cout << "Documents Path: " << path << endl;
function_expecting_charptr(path);
delete[] path;
return 0;
}
C++ way:
#include <iostream>
#include <string>
int main(int argc, char** argv) {
std::string path = argv[0];
size_t sep = path.find('/');
if (sep != std::string::npos)
path.erase(sep+1);
else
path.clear();
path += "docs/";
std::cout << "Documents Path: " << path << endl;
function_expecting_charptr(path.c_str());
return 0;
}
Note that argv[0] holds an implementation defined value, and especially in *nix environments isn't guaranteed to hold anything useful. The first parameter passed to the program is found in argv[1].
I combined some of your guys' ideas into this compact code:
#include <iostream>
#include <cstring>
using namespace std;
int main(int argc, char** argv) {
const string path_this = argv[0];
const string path = path_this.substr(0, strrchr(argv[0], '/') - argv[0] +1);
const string path_docs = path + "docs/";
cout << "Documents Path: " << path_docs << endl;
return 0;
}
To get the character array from this I can then run 'path_docs.c_str()'.
Credits: #MooingDuck, #MarkB, Google.