You have to convert the string "<challenge>-<password>" to UTF-16LE. If the whole string is plain ASCII, the conversion is trivial: you just have to add a zero byte after each ASCII byte.
// ASCII string to be hashed.
const char* text = "1234567z-abc"; // umlaut removed
// Convert to UTF-16LE.
const size_t length = strlen(text);
char buffer[2*length];
for (size_t i = 0; i < length; i++) {
buffer[2*i] = text[i];
buffer[2*i+1] = 0;
}
// Compute and print the hash.
unsigned char* hash2 = MD5::make_hash(buffer, 2*length);
char *md5str2 = MD5::make_digest(hash2, 16);
free(hash2);
Serial.print("MD5: ");
Serial.println(md5str2);
Note that I use the two-parameter version of MD5::make_hash()
in order
to pass the length of the buffer. The one parameter version of this
method would stop at the first zero byte.
Edit: Regarding your extended question (the new section "Working Example"), this is a problem completely unrelated to the previous one. It is about string termination.
In C and C++, strings are arrays of characters terminated with a NUL ASCII character (numeric value zero). The terminating NUL is not part of the string per se, but it should be stored in the array holding the string. String literals are interpreted by the compiler as NUL-terminated arrays of characters. Every function that expects a string as an input expects it to be NUL-terminated.
In this particular instance, you failed to NUL-terminate
challengePass
. When this array is given to strelen()
, this function
scans the memory until it finds a zero byte. If that zero byte happens
to be right after the end of the array, your code will work as expected.
Otherwise, any non-zero byte coming after challengePass
in memory will
be interpreted as being part of the string. The program behavior is
unpredictable, because you do not know what will be stored in memory
right after challengePass
.
The solution is to NUL-terminate the string. Start by allocating one more byte:
char challengePass[8 + 1 + passLength + 1]; // challenge-password
Then, right after copying the password, add a zero byte to terminate the string:
challengePass[8 + 1 + passLength] = '0円'; // terminate the string
Note that '0円'
means "the character with numeric value zero".
Alternatively, you can terminate the string right after adding the dash,
then use strcat()
to concatenate the password. strcat()
will take
care of terminating the string:
challengePass[8] = '-';
challengePass[9] = '0円'; // temporarily terminate the string
strcat(challengePass, pass); // append password
You have to convert the string "<challenge>-<password>" to UTF-16LE. If the whole string is plain ASCII, the conversion is trivial: you just have to add a zero byte after each ASCII byte.
// ASCII string to be hashed.
const char* text = "1234567z-abc"; // umlaut removed
// Convert to UTF-16LE.
const size_t length = strlen(text);
char buffer[2*length];
for (size_t i = 0; i < length; i++) {
buffer[2*i] = text[i];
buffer[2*i+1] = 0;
}
// Compute and print the hash.
unsigned char* hash2 = MD5::make_hash(buffer, 2*length);
char *md5str2 = MD5::make_digest(hash2, 16);
free(hash2);
Serial.print("MD5: ");
Serial.println(md5str2);
Note that I use the two-parameter version of MD5::make_hash()
in order
to pass the length of the buffer. The one parameter version of this
method would stop at the first zero byte.
You have to convert the string "<challenge>-<password>" to UTF-16LE. If the whole string is plain ASCII, the conversion is trivial: you just have to add a zero byte after each ASCII byte.
// ASCII string to be hashed.
const char* text = "1234567z-abc"; // umlaut removed
// Convert to UTF-16LE.
const size_t length = strlen(text);
char buffer[2*length];
for (size_t i = 0; i < length; i++) {
buffer[2*i] = text[i];
buffer[2*i+1] = 0;
}
// Compute and print the hash.
unsigned char* hash2 = MD5::make_hash(buffer, 2*length);
char *md5str2 = MD5::make_digest(hash2, 16);
free(hash2);
Serial.print("MD5: ");
Serial.println(md5str2);
Note that I use the two-parameter version of MD5::make_hash()
in order
to pass the length of the buffer. The one parameter version of this
method would stop at the first zero byte.
Edit: Regarding your extended question (the new section "Working Example"), this is a problem completely unrelated to the previous one. It is about string termination.
In C and C++, strings are arrays of characters terminated with a NUL ASCII character (numeric value zero). The terminating NUL is not part of the string per se, but it should be stored in the array holding the string. String literals are interpreted by the compiler as NUL-terminated arrays of characters. Every function that expects a string as an input expects it to be NUL-terminated.
In this particular instance, you failed to NUL-terminate
challengePass
. When this array is given to strelen()
, this function
scans the memory until it finds a zero byte. If that zero byte happens
to be right after the end of the array, your code will work as expected.
Otherwise, any non-zero byte coming after challengePass
in memory will
be interpreted as being part of the string. The program behavior is
unpredictable, because you do not know what will be stored in memory
right after challengePass
.
The solution is to NUL-terminate the string. Start by allocating one more byte:
char challengePass[8 + 1 + passLength + 1]; // challenge-password
Then, right after copying the password, add a zero byte to terminate the string:
challengePass[8 + 1 + passLength] = '0円'; // terminate the string
Note that '0円'
means "the character with numeric value zero".
Alternatively, you can terminate the string right after adding the dash,
then use strcat()
to concatenate the password. strcat()
will take
care of terminating the string:
challengePass[8] = '-';
challengePass[9] = '0円'; // temporarily terminate the string
strcat(challengePass, pass); // append password
You have to convert the string "<challenge>-<password>" to UTF-16LE. If the whole string is plain ASCII, the conversion is trivial: you just have to add a zero byte after each ASCII byte.
// ASCII string to be hashed.
const char* text = "1234567z-abc"; // umlaut removed
// Convert to UTF-16LE.
const size_t length = strlen(text);
char buffer[2*length];
for (size_t i = 0; i < length; i++) {
buffer[2*i] = text[i];
buffer[2*i+1] = 0;
}
// Compute and print the hash.
unsigned char* hash2 = MD5::make_hash(buffer, 2*length);
char *md5str2 = MD5::make_digest(hash2, 16);
free(hash2);
Serial.print("MD5: ");
Serial.println(md5str2);
Note that I use the two-parameter version of MD5::make_hash()
in order
to pass the length of the buffer. The one parameter version of this
method would stop at the first zero byte.