Get SHA256 hash of UTF-16le String

Viewed 124

I'm trying to get the SHA256 sum of a UTF-16le string. Pythonically what I'm trying to do would look like this:

import hashlib
username = "Administrator"
username = username.decode('utf-8').encode('utf-16le')
hash = hashlib.sha256(username).digest()
print(hash)

The C code below gives me the SHA256 hash as though I had NOT called the decode('utf-8').encode('utf-16le') in the Python section above.

The output of the below is e7d3e769f3f593dadcb8634cc5b09fc90dd3a61c4a06a79cb0923662fe6fae6b. The output that I want would be 5264c63204c56c0df9f8f4a030ea19d93a0fa402be6b00b4d7464e61641021f7

This is my first time coding in C, so if I'm missing something blatantly obvious or doing something wrong, that's why.

#include <openssl/sha.h>
#include <stdio.h>
#include <string.h>

int main()
{
    unsigned const char ibuf[] = "Administrator";
    unsigned char obuf[32];

    SHA256(ibuf, strlen((const char * )ibuf), obuf);

    unsigned char hash[32];
    int i;
    for(i = 0; i < 32; i++)
    {
        printf("%02x",obuf[i]);
    }

    printf("\n");
    return 0;
}
1 Answers

Looking at your code, the only thing that's left to do is the character set conversion. A way to do that conversion is to use the iconv family of functions.

Adapting this question and combining it with your code, that could look something like:

#include <stdio.h>
#include <string.h>
#include <iconv.h>
#include <openssl/sha.h>

int main()
{
    unsigned char ibuf[] = "Administrator";
    unsigned char obuf[32];

    char dest_str[100];
    char *in = ibuf;
    char *out = dest_str;
    size_t inbytes = strlen(in);
    size_t outbytes = sizeof dest_str;
    iconv_t conv = iconv_open("UTF-16LE", "UTF-8");

    if (conv == (iconv_t)-1) {
        perror("iconv_open");
        return 1;
    }

    if (iconv(conv, &in, &inbytes, &out, &outbytes) == (size_t)-1) {
        perror("iconv");
        return 1;
    }

    iconv_close(conv);

    SHA256(dest_str, sizeof dest_str - outbytes, obuf);

    unsigned char hash[32];
    int i;
    for(i = 0; i < 32; i++)
    {
        printf("%02x",obuf[i]);
    }

    printf("\n");
    return 0;
}

...which should indeed give:

5264c63204c56c0df9f8f4a030ea19d93a0fa402be6b00b4d7464e61641021f7

A few things to note:

  • The iconv_open function takes the "to" character set first, and the "from" character set second.
  • The iconv function changes the things it gets passed: in, out, inbytes, outbytes are all modified (increased or decreased) as iconv converts characters.
  • iconv does not allocate memory for the result - in the example program, it uses a fixed-size 100-byte buffer to store its output. If you're going to be converting longer strings as well, you may need a bigger buffer.
Related