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.
Related
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;
}
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)
How do I make myself enter data into a string through cin, and not in program code ("message," "pwd")?
I need to make a transformation from string to unsigned char, but I don't know how. The code itself is an attempt to implement RC4
#include <iostream>
#include <string.h>
using namespace std;
void rc4(unsigned char * ByteInput, unsigned char * pwd,
unsigned char * &ByteOutput){
unsigned char * temp;
int i,j=0,t,tmp,tmp2,s[256], k[256];
for (tmp=0;tmp<256;tmp++){
s[tmp]=tmp;
k[tmp]=pwd[(tmp % strlen((char *)pwd))];
}
for (i=0;i<256;i++){
j = (j + s[i] + k[i]) % 256;
tmp=s[i];
s[i]=s[j];
s[j]=tmp;
}
temp = new unsigned char [ (int)strlen((char *)ByteInput) + 1 ] ;
i=j=0;
for (tmp=0;tmp<(int)strlen((char *)ByteInput);tmp++){
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp2=s[i];
s[i]=s[j];
s[j]=tmp2;
t = (s[i] + s[j]) % 256;
if (s[t]==ByteInput[tmp])
temp[tmp]=ByteInput[tmp];
else
temp[tmp]=s[t]^ByteInput[tmp];
}
temp[tmp]='\0';
ByteOutput=temp;
}
int main()
{
unsigned char * message;
unsigned char * pwd;
unsigned char * encrypted;
unsigned char * decrypted;
message=(unsigned char *)"Hello world!";
pwd=(unsigned char *)"abc";
rc4(message,pwd,encrypted);
rc4(encrypted,pwd,decrypted);
cout<<"Test"<<endl<<endl;
cout<<"Message: "<<message<<endl;
cout<<"Password: "<<pwd<<endl;
cout<<"Message encrypted: "<<encrypted<<endl;
cout<<"Message decrypted: "<<decrypted<<endl;
return 0;
}
std::string has a .c_str() member function which returns const char * to the internal string. You can use reinterpret_cast to cast that to const unsigned char*. Example:
#include <string> // string not string.h
std::string message;
std::getline (std::cin, message);
const unsigned char* msg = reinterpret_cast<const unsigned char*>(message.c_str());
there is code
#include <stdio.h>
#include <string.h>
#include <openssl/hmac.h>
int main() {
const char key[] = "012345678";
char data[] = "hello world";
unsigned char* result;
unsigned int len = 20;
result = (unsigned char*)malloc(sizeof(char) * len);
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, key, strlen(key), EVP_sha1(), NULL);
HMAC_Update(&ctx, (unsigned char*)&data, strlen(data));
HMAC_Final(&ctx, result, &len);
HMAC_CTX_cleanup(&ctx);
printf("HMAC digest: ");
for (int i = 0; i != len; i++)
printf("%02x", (unsigned int)result[i]);
printf("\n");
free(result);
}
output HMAC digest: e19e220122b37b708bfb95aca2577905acabf0c0
I can not update this code for openssl 1.1.0.
The new version changed the syntax hmac.
#include <iostream>
#include <string.h>
#include <openssl/hmac.h>
using namespace std;
int main() {
const char key[] = "012345678";
char data[] = "hello world";
int datalen = strlen(data);
int keylen = strlen(key);
unsigned char* result;
unsigned int len = 20;
result = (unsigned char*)malloc(sizeof(char) * len);
cout << datalen << endl;
cout << keylen << endl;
cout << len << endl;
HMAC_CTX *HMAC_CTX_new();
int HMAC_CTX_reset(HMAC_CTX *ctx);
int HMAC_Init_ex(HMAC_CTX *ctx, const char key, int keylen, const EVP_MD EVP_sha1());
int HMAC_Update(HMAC_CTX * ctx, char &data, int datalen);
int HMAC_Final(HMAC_CTX * ctx, char result, int &len);
int HMAC_CTX_cleanup(HMAC_CTX * ctx);
printf("HMAC digest: ");
for (int i = 0; i != len; i++)
printf("%02x", (unsigned int)result[i]);
printf("\n");
free(result);
return 0;
}
output HMAC digest: 0000000000000000000000000000000000000000
I will be glad of any help
I need some help with decrypt a char array in C++ using AES decrypt with Open SSL library. I already done encryption mode and works fine, but decryption is not working.
This is the Encrypt Function:
string Encrypt(char *Key, char *Msg, int size)
{
static char* Res;
static const char* const lut = "0123456789ABCDEF";
string output;
AES_KEY enc_key;
Res = (char *)malloc(size);
AES_set_encrypt_key((unsigned char *)Key, 128, &enc_key);
for(int vuelta = 0; vuelta <= size; vuelta += 16)
{
AES_ecb_encrypt((unsigned char *)Msg + vuelta, (unsigned char *)Res + vuelta, &enc_key, AES_ENCRYPT);
}
output.reserve(2 * size);
for (size_t i = 0; i < size; ++i)
{
const unsigned char c = Res[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
free(Res);
return output;
}
This is the Decrypt Function (not working):
char * Decrypt( char *Key, char *Msg, int size)
{
static char* Res;
AES_KEY dec_key;
Res = ( char * ) malloc( size );
AES_set_decrypt_key(( unsigned char * ) Key, 128, &dec_key);
for(int vuelta= 0; vuelta<=size; vuelta+=16)
{
AES_ecb_encrypt(( unsigned char * ) Msg+vuelta, ( unsigned char * ) Res+vuelta, &dec_key, AES_DECRYPT);
}
return (Res);
}
This is an Example of the Main function that call the methods, the problem is thar no mather how i print the "Res" variable in the Decrypt function, it always show random ASCII values, and i like to show the result in a string like the Encrypt function:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "openSSL/aes.h"
using namespace std;
int main(int argc, char const *argv[])
{
char key[16];
char message[128];
char enc_message[128];
string s_key = "THIS_IS_THE_KEY_";
string s_message = "Hello World !!!";
memset(key, 0, sizeof(key));
strcpy(key, s_key.c_str());
memset(message, 0, sizeof(message));
strcpy(message, s_message.c_str());
string response = Encrypt(key, message, sizeof(message));
cout<<"This is the Encrypted Message: "<<response<<endl;
memset(enc_message, 0, sizeof(enc_message));
strcpy(enc_message, response.c_str());
Decrypt(key, enc_message, sizeof(enc_message));
return 0;
}
Any improve in this methods?
I wanted to put the answer to how I solved it: The problem with my example was that I was trying to use the decrypt function with a HEXADECIMAL STRING and it should be done with an ASCII STRING with the values as delivered by the encryption function.
That is, instead of trying to decrypt a string like this: 461D019896EFA3
It must be decrypted with a string like this: #(%_!#$
After that, the decryption will be delivered in ASCII values. They must be passed to Hexadecimal and finally to a String.
Here is the example that worked for me:
string Decrypt_string(char *Key, string HEX_Message, int size)
{
static const char* const lut = "0123456789ABCDEF";
int i = 0;
char* Res;
AES_KEY dec_key;
string auxString, output, newString;
for(i = 0; i < size; i += 2)
{
string byte = HEX_Message.substr(i, 2);
char chr = (char) (int)strtol(byte.c_str(), NULL, 16);
auxString.push_back(chr);
}
const char *Msg = auxString.c_str();
Res = (char *)malloc(size);
AES_set_decrypt_key((unsigned char *)Key, 128, &dec_key);
for(i = 0; i <= size; i += 16)
{
AES_ecb_encrypt((unsigned char *)Msg + i, (unsigned char *)Res + i, &dec_key, AES_DECRYPT);
}
output.reserve(2 * size);
for (size_t i = 0; i < size; ++i)
{
const unsigned char c = Res[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
int len = output.length();
for(int i = 0; i < len; i += 2)
{
string byte = output.substr(i, 2);
char chr = (char) (int)strtol(byte.c_str(), NULL, 16);
newString.push_back(chr);
}
free(Res);
return newString;
}