2

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 Answer 1

1

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.
Sign up to request clarification or add additional context in comments.

1 Comment

One small thing I changed, if anyone else is reading over this. I got a compile error unless *in was defined as a constant, e.g. const char *in = ibuf;. Everything else worked. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.