I want to print MD5 for some string. For this I have done the the function
std::string generateHashMD5(std::string text)
{
unsigned char * resultHash;
resultHash = MD5((const unsigned char*)text.c_str(), text.size(), NULL);
std::string result;
result += (char *) resultHash;
return result;
}
Mow I want to print the result of this function. I try to version of such function.
void printHash(std::string hash)
{
for (unsigned i = 0; i < str.size(); i++)
{
int val = (short) hash[i];
std::cout<<std::hex<<val<<':';
}
std::cout<<std::endl;
}
std::string printHash(std::string hash)
{
char arrayResult[200];
for(int i = 0; i < 16; i++)
sprintf(&arrayResult[i*2], "%02x", (unsigned short int)hash[i]);
std::string result;
result += arrayResult;
return result;
}
The problem is that unfortunately none of it does not show correct result. What should be changed in this function or where is the mistakes?
You improperly use std::string as a buffer:
result += (char *) resultHash;
treats resultHash as a c-string, so if there is \0 byte in middle it would not get enough data. If there is no \0 byte you would copy too much and get UB. You should use constructor with size:
std::string result( static_cast<const char *>( resultHash ), blocksize );
where block size probably is 16. But I would recommend to use std::array<uint8_t,blocksize> or std::vector<uint8_t> instead os std::string, as std::string for buffer is very confusing.
in case if MD5 returns byte array
result += (char *) resultHash;
return result;
conversion to string will lose numbers after 0 because string constructor interprets input as null-terminated string
so vector can be used or string construction with explicit number of characters.
Still, there are not enough information to say exactly
Related
int computeHMACSHA1Hash(const char * unhashedcstr, char * hashedcstr, const char * key, int returncode)
{
string hashed;
size_t unhashlength = strlen(unhashedcstr);
char * nonconstunhashcstr = new char[unhashlength];
strcpy_s(nonconstunhashcstr, unhashlength + 1, unhashedcstr);
unsigned char* pixels = reinterpret_cast<unsigned char*>(nonconstunhashcstr);
returncode = 0;
HMAC_CTX* context = HMAC_CTX_new();
size_t unhashedstrlength = sizeof(unhashedcstr);
if (context != NULL)
{
if (HMAC_Init_ex(context, key, strlen(key), EVP_sha1(), NULL))
{
if (HMAC_Update(context, pixels, unhashedstrlength))
{
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int lengthOfHash = 0;
if (HMAC_Final(context, hash, &lengthOfHash))
{
std::stringstream ss;
for (unsigned int i = 0; i < lengthOfHash; ++i)
{
ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
}
hashed = ss.str();
size_t outputSize = hashed.length() + 1; // +1 for null terminator
strcpy_s(hashedcstr, outputSize, hashed.c_str());
returncode = 0;
}
else
{
returncode = 7;
}
}
else
{
returncode = 6;
}
}
else
{
returncode = 5;
}
HMAC_CTX_free(context);
}
else
{
returncode = 4;
}
return returncode;
}
int main()
{
const char * unhashedcstr = "a=services&l=v1&p=open&k=SD58292829&i=20200918125249803&n=2124&t=1600404769&f={\"invoiceCode\": \"11111\",\"invoiceNo\": \"2222\",\"inTaxAmount\": \"\",\"exTaxAmount\": \"\"}";
char * hashedcstr = new char[100];
int returncode = 0;
const char * key = "SD886A11B0EE428F";
int result = computeHMACSHA1Hash(unhashedcstr, hashedcstr, key, returncode);
return 0;
}
I tried the code above to calculating the HMAC SHA1 hash value for a content, but compared the results on https://www.freeformatter.com/hmac-generator.html#before-output
it looks like I didn't do it right. I'm not sure what I have done wrong though. Any help would be appreciated.
It turned out the result was "d916b4c2d277319bbf18076c158f0cbcf6c3bc57", while on the website https://www.freeformatter.com/hmac-generator.html#before-output, the result was "71482b292f2b2a47b3eca6dad5e7350566d60963". Even when I tried using the string "a=services&l=v1&p=open&k=SD58292829&i=20200918125249803&n=2124&t=1600404769&f={"invoiceCode": "11111","invoiceNo": "2222","inTaxAmount": "","exTaxAmount": ""}" which removed the escape characters, the result was "09be98b6129c149e685ed57a1d19651a602cda0d". It didn't match the correct one.
Is there anything wrong with my code?
Your hash is calculated over the bytes a=se, which are the first four bytes of the whole input string. Thus, you get d916b4c2d277319bbf18076c158f0cbcf6c3bc57 instead of the 09be98b6129c149e685ed57a1d19651a602cda0d that would correspond to the whole string.
The reason is this:
size_t unhashedstrlength = sizeof(unhashedcstr);
Here, sizeof(unhashedcstr) is the size of the unhashedcstr pointer itself (which is of type const char*), not the size of the null-terminated C-style string this unhashedcstr pointer is pointing to. You are compiling a 32-bit program, so the size of a pointer is 4 bytes. Thus, unhashedstrlength is 4.
To get the length of the C-style string, you can do this instead:
size_t unhashedstrlength = strlen(unhashedcstr);
But just as a comment, in modern C++, you should avoid using raw pointers (such as const char*, char*, unsigned char*), C functions (like strlen(), strcpy_s()) and manual memory management (new / delete and new[] / delete[]). You should prefer to use std::string and/or std::vector<unsigned char> instead, wherever possible. When you need to pass a buffer's address to an API function, you can use std::string::data(), std::vector::data(), or more generally, std::data().
By the way, you currently leak memory: you dynamically allocate buffers using new[], but you never deallocate those (using delete[]). So that memory is released by the OS only after the program exits. This is called a memory leak.
I have input strings that contain only digits (just the plain Latin ones, 0-9, so for example "0123"), stored as std::wstring, and I need each as a char*. What's the best way for me to do this? This is my initial approach:
void type::convertWStringToCharPtr(_In_ std::wstring input, _Out_ char * outputString)
{
outputString = new char[outputSize];
size_t charsConverted = 0;
const wchar_t * inputW = input.c_str();
wcstombs_s(&charsConverted, outputString, sizeof(outputString), inputW, input.length());
}
EDIT: The code below works. Thanks all!
void type::convertWStringToCharPtr(_In_ std::wstring input, _Out_ char * outputString)
{
size_t outputSize = input.length() + 1; // +1 for null terminator
outputString = new char[outputSize];
size_t charsConverted = 0;
const wchar_t * inputW = input.c_str();
wcstombs_s(&charsConverted, outputString, outputSize, inputW, input.length());
}
You are not allocating enough memory for your buffer:
char * outputString = new char[input.length()];
Should be
char * outputString = new char[input.length() + 1];
because of terminating NUL-character.
Oh, and also, as per pm100's comment: sizeof(outputString) is giving you the size of the pointer. You should use input.length() + 1, as that is the size of the buffer.
There are a couple of errors in your code. First, you're not allocating enough space in your destination buffer for the NULL character. You must allocate at least input.length() + 1 chars for the function to succeed.
Second, you're not passing in the correct size of the output buffer to the function. sizeof(outputString) returns the size of outputString itself, a char *, and not the number of bytes pointed to by that pointer.
So your function should look like this:
void CoverageTileManager::convertWStringToCharPtr(_In_ std::wstring input, _Out_ char * outputString)
{
size_t outputSize = input.length() + 1;
outputString = new char[outputSize];
size_t charsConverted = 0;
wcstombs_s(&charsConverted, outputString, outputSize, input.c_str(), input.length());
// TODO verify charsConverted = outputSize
}
In C++ I would never use pure pointers: use vector if a char array needed in heap! Do you want to copy the source string? If not, const reference should be used for input. wcstombs_s is used only in Windows, so why doesn't use simply WideCharToMultiByte? Was the conversion success? Return value.
bool CoverageTileManager::convertWStringToCharPtr(const std::wstring& input, std::vector<char>& outputString )
{
if ( input.empty() ) {
return false;
}
int size = WideCharToMultiByte(CP_ACP,0,input.c_str(),input.size(),NULL,0,NULL,NULL);
if ( size <= 0 ) {
return false;
}
outputString.resize(size+1);
if ( WideCharToMultiByte(CP_ACP,0,input.c_str(),input.size(),&outputString[0],size,NULL,NULL) <= 0 ) {
outputString.clear();
return false;
}
outputString[size] = '\0';
return true;
}
Use vector to external C++ lib:
extern void call( const char*, size_t);
std::vector<char> buffer;
std::wstring input;
...
if ( convertWStringToCharPtr(input,buffer) ) {
call(&buffer[0],buffer.size());
}
So I am working on a tool that dereferences the values of some addresses, it is in both C and C++, and although I am not familiar with C++ I figured out I can maybe take advantage of the string type offered by C++.
What I have is this:
unsigned char contents_address = 0;
unsigned char * address = (unsigned char *) add.addr;
int i;
for(i = 0; i < bytesize; i++){ //bytesize can be anything from 1 to whatever
if(add.num == 3){
contents_address = *(address + i);
//printf("%02x ", contents_address);
}
}
As you can see what I am trying to do is dereference the unsigned char pointer. What I want to do is have a string variable and concatenate all of the dereferenced values into it and by the end instead of having to go through a for case for getting each one of the elements (by having an array of characters or by just going through the pointers) to have a string variable with everything inside.
NOTE: I need to do this because the string variable is going to a MySQL database and it would be a pain to insert an array into a table...
Try this that I borrowed from this link:
http://www.corsix.org/content/algorithmic-stdstring-creation
#include <sstream>
#include <iomanip>
std::string hexifyChar(int c)
{
std::stringstream ss;
ss << std::hex << std::setw(2) << std::setfill('0') << c;
return ss.str();
}
std::string hexify(const char* base, size_t len)
{
std::stringstream ss;
for(size_t i = 0; i < len; ++i)
ss << hexifyChar(base[i]);
return ss.str();
}
I didn't quite understand what you want to do here (why do you assign a dereferenced value to a variable called ..._address)?.
But maybe what you're looking for is a stringstream.
Here's a relatively efficient version that performs only one allocation and no additional function calls:
#include <string>
std::string hexify(unsigned char buf, unsigned int len)
{
std::string result;
result.reserve(2 * len);
static char const alphabet[] = "0123456789ABCDEF";
for (unsigned int i = 0; i != len)
{
result.push_back(alphabet[buf[i] / 16]);
result.push_back(alphabet[buf[i] % 16]);
{
return result;
}
This should be rather more efficient than using iostreams. You can also modify this trivially to write into a given output buffer, if you prefer a C version which leaves allocation to the consumer.
I have this code that show me correctly, the md5 of a string.
I prefer to return a string to the function, but I have some problem converting the values of md5 into my string.
This is the code:
string calculatemd5(string msg)
{
string result;
const char* test = msg.c_str();
int i;
MD5_CTX md5;
MD5_Init (&md5);
MD5_Update (&md5, (const unsigned char *) test, msg.length());
unsigned char buffer_md5[16];
MD5_Final ( buffer_md5, &md5);
printf("Input: %s", test);
printf("\nMD5: ");
for (i=0;i<16;i++){
printf ("%02x", buffer_md5[i]);
result[i]=buffer_md5[i];
}
std::cout <<"\nResult:"<< result[i]<<endl;
return result;
}
For example result[i] is a strange ascii char like this: .
How can is possible solve this problem?
A cleaner way (and faster) might be like this:
std::string result;
result.reserve(32); // C++11 only, otherwise ignore
for (std::size_t i = 0; i != 16; ++i)
{
result += "0123456789ABCDEF"[hash[i] / 16];
result += "0123456789ABCDEF"[hash[i] % 16];
}
return result;
replace
for (i=0;i<16;i++){
printf ("%02x", buffer_md5[i]);
result[i]=buffer_md5[i];
}
with
char buf[32];
for (i=0;i<16;i++){
sprintf(buf, "%02x", buffer_md5[i]);
result.append( buf );
}
notice that when you print out result, print result, not result[i] to get whole string.
if you put the buffer_md5[i] value directly in result then you may get problems since a string may not have an embedded 0 (if there is one).
Seems that you are using openssl.
Use constant MD5_DIGEST_LENGTH.
You can also use MD5 function instead of MD5_Init, MD5_Update and MD5_Final.
MD5() may take most of the time, but if you want to reduce time of sprintf, then do hex string manually.
Like this way:
{
static const char hexDigits[16] = "0123456789ABCDEF";
unsigned char digest[MD5_DIGEST_LENGTH];
char digest_str[2*MD5_DIGEST_LENGTH+1];
int i;
// Count digest
MD5( (const unsigned char*)msg.c_str(), msg.length(), digest );
// Convert the hash into a hex string form
for( i = 0; i < MD5_DIGEST_LENGTH; i++ )
{
digest_str[i*2] = hexDigits[(digest[i] >> 4) & 0xF];
digest_str[i*2+1] = hexDigits[digest[i] & 0xF];
}
digest_str[MD5_DIGEST_LENGTH*2] = '\0';
std::cout <<"\nResult:"<< digest_str <<endl;
}
not tested, so there may be bugs.
#include <sstream>
...
std::stringstream ss;
for (i=0;i<16;i++){
printf ("%02x", buffer_md5[i]);
ss << std::hex << buffer_md5[i];
}
result = ss.str();
std::hex might not do exactly what you want. Perhaps, this will be better:
for (i=0;i<16;i++){
printf ("%02x", buffer_md5[i]);
if (buffer_md5[i] < 10)
ss << buffer_md5[i];
else
ss << 97 + buffer_md5[i] - 15;
}
How would I manually concatenate two char arrays without using the strncpy function?
Can I just say char1 + char2?
Or would I have to write a for loop to get individual elements and add them like this:
addchar[0] = char1[0];
addchar[1] = char1[1];
etc
etc
addchar[n] = char2[0];
addchar[n+1] = char2[1];
etc
etc
To clarify, if
char1 = "happy"
char2 = "birthday"
I want addchar to = happybirthday
For a C-only solution use strncat:
char destination[80] = "";
char string1[] = "Hello";
char string2[] = " World!";
/* Copy string1 to destination */
strncat(destination, string1, sizeof(destination));
/* Append string2 to destination */
strncat(destination, string2, sizeof(destination) - sizeof(string1));
Note that the strn* family of string functions are safer than the ones without n, because they avoid the possibility of buffer overruns.
For a C++ solution, simply use std::string and operator+ or operator+=:
std::string destination("Hello ");
destination += "World";
destination += '!';
If you consider two trivial loops to be "manual", then yes, without using the standard library this is the only way.
char *append(const char *a, const char *b) {
int i = 0;
size_t na = strlen(a);
size_t nb = strlen(b);
char *r = (char*)calloc(na + nb + 1, 1);
for (i = 0; i < na; i++) {
r[i] = a[i];
}
for (i = 0; i < nb; i++) {
r[na + i] = b[i];
}
return r;
}
Remember to call free.
If you're using c++ just use an std::string. With std::strings, the + operator is supported, so you can do string1+string2.
Without using library functions, here is the procedure:
1. Point to the first character in string1.
2. While the current character at the pointer is not null, increment the pointer.
3. Create a "source" pointer pointing to string2.
4. While the character at the "source" location is not null:
4.1. Copy the character from the "source" location to the location pointed to by the String1 pointer.
4.2. Increment both pointers.
Unless this is homework, use C++ std::string for your text.
If you must use C style strings, use the library functions.
Library functions are optimized and validated, reducing your development time.
Alright, you want something like this:
char1 + char2
First, let's see the insane solution:
C:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length_left = strlen(a_Left);
unsigned int length_right = strlen(a_Right);
unsigned int length = length_left + length_right;
char* result = (char*)malloc(length);
// clear the string
memset(result, 0, length);
// copy the left part to the final string
memcpy(result, a_Left, length_left);
// append the right part the to the final string
memcpy(&result[length_left], a_Right, length_right);
// make sure the string actually ends
result[length] = 0;
return result;
}
C++:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length_left = strlen(a_Left);
unsigned int length_right = strlen(a_Right);
unsigned int length = length_left + length_right;
char* result = new char[length];
// clear the string
memset(result, 0, length);
// copy the left part to the final string
memcpy(result, a_Left, length_left);
// append the right part the to the final string
memcpy(&result[length_left], a_Right, length_right);
// make sure the string actually ends
result[length] = 0;
return result;
}
Now, let's see the sane solution:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length = strlen(a_Left) + strlen(a_Right);
char* result = new char[length];
strcpy(result, a_Left);
strcat(result, a_Right);
return result;
}
So, was this homework? I don't really care.
If it was, ask yourself: what did you learn?