Skip to main content
Arduino

Return to Answer

Answer second question.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

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
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

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.

lang-cpp

AltStyle によって変換されたページ (->オリジナル) /