9

I did two SHA1 in C code, one is for a string, and another is for a integer, and get different result.

SHA_init(&ctx);
SHA_update(&ctx, "1234", 4);
sha = SHA_final(&ctx);

unsigned n = 1234;
SHA_init(&ctx);
SHA_update(&ctx, &n, sizeof(n));
sha = SHA_final(&ctx);

string  result:  7110eda4d09e62aa5e4a390b0a572acd2c220
integer result:  c7f07b846cc46631c2079cdd7179afdd783d643

In python, it's very easy to get the string SHA1

sha1 = hashlib.sha1()
sha1.update('1234')
sha1.hexdigest()

'7110eda4d09e062aa5e4a390b0a572ac0d2c0220'

We can see the string result is same as C code. But how to get the integer SHA1 in python? because the python sha1 doesn't support integer.

I tried following code, but it can't get the same result as C code.

aint = unpack('>4B', pack('>I', 1234))   
sha1 = hashlib.sha1()
sha1.update(bytearray(aint))
sha1.hexdigest()

'ac9928e78cf6ea117451ecd6654fea2adae73e21'

How to do the integer SHA1 in python?

7
  • Hint: map(ord, "1234") == [49, 50, 51, 52] != [210, 4] == [1234 & 0xff, 1234 >> 8] Commented Jul 2, 2015 at 3:30
  • How about sha1.update(str(1234))? Commented Jul 2, 2015 at 3:38
  • Of course, sha1.update(str(1234)) is same as ` sha1.update('1234')` Commented Jul 2, 2015 at 3:45
  • 1
    Have you verified that the layout of 1234 in C matches what struct.pack produces? Commented Jul 2, 2015 at 3:47
  • 1
    And does size(n) return 4? Commented Jul 2, 2015 at 3:52

3 Answers 3

9
digest = sha1.hexdigest()
digest_int = int(digest,16)
Sign up to request clarification or add additional context in comments.

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.
2

I can't reproduce your results in C, what SHA library are you using? OpenSSL recommends the SHA1_* functions but says that SHA_* are included for compatibility. These two give different results for me, so if you're comparing to Pythons SHA1, you should be using SHA1_*

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

int main(void) {
    unsigned n = 1234;
    unsigned char md[50];
    SHA_CTX c;

    for (int i=0; i<sizeof(n); i++) {
        printf("%02x ", ((unsigned char*)&n)[i]);
    }
    printf("\n");

    SHA1_Init(&c);
    SHA1_Update(&c, &n, 4);
    SHA1_Final(md, &c);

    for (int i=0; i<20; i++) {
        printf("%02x", md[i]);
    }
    printf("\n");
    return 0;
}

Gives:

 d2 04 00 00
 7b08e025e311c3dfcf5179b67c0fdc08e73de261

Which suggests that you're packing bytes in the wrong order in your python implementation. It should be:

>>> import hashlib
>>> hashlib.sha1(b'\xd2\x04\x00\x00').hexdigest()
'7b08e025e311c3dfcf5179b67c0fdc08e73de261'
>>> hashlib.sha1(bytearray(unpack('>4B', pack('I', 1234)))).hexdigest()
'7b08e025e311c3dfcf5179b67c0fdc08e73de261'

(Note no > in front of the I) which matches the shasum above.

For reference, if I use the SHA_* functions I get

int main(void) {
    unsigned n = 1234;
    unsigned char md[50];
    SHA_CTX c;

    SHA_Init(&c);
    SHA_Update(&c, &n, 4);
    SHA_Final(md, &c);

    for (int i=0; i<20; i++) {
        printf("%02x", md[i]);
    }
    printf("\n");
    return 0;
}

3e491ac1d065d6d666e5e216e0cddf60fcb5be86

Which seems to agree with the SHA ("SHA-0") value in Python:

>>> hashlib.new('sha', b'\xd2\x04\x00\x00').hexdigest()
'3e491ac1d065d6d666e5e216e0cddf60fcb5be86'

2 Comments

Thank you for your answer. I used the SHA from android code. github.com/android/platform_system_core/blob/master/libmincrypt/… . But it's strange that the string SHA is matched.
And hashlib.sha1(bytearray(unpack('>4B', pack('I', 1234)))).hexdigest() is the right function to do integrer in python? Thanks.
1

It may be your code that converts to hex for printing. Notice how neither of your hashes is 40 characters long? Try using my to_hex() method below.

    python ==>  '7110eda4d09e062aa5e4a390b0a572ac0d2c0220'
string  result:  7110eda4d09e62aa5e4a390b0a572acd2c220
integer result:  c7f07b846cc46631c2079cdd7179afdd783d643

I also couldn't reproduce your C results. Here's an OSX version:

#include <stdio.h>
#include <CommonCrypto/CommonDigest.h>

char *to_hex(unsigned char *buffer, size_t len) {
  static char out[100];
  char *p = out;
  while (len--)
    p += sprintf(p, "%02x", *buffer++);
  *p = 0;
  return out;
}

int main() {
  unsigned char buffer[21] = { 0 };
  printf("SHA1(\"1234\") =   %s\n", to_hex(CC_SHA1("1234", 4, buffer), 20));

  unsigned n = 1234;
  printf("1234 LE =        %s\n", to_hex(&n, 4));  
  printf("SHA1(1234 LE) =  %s\n", to_hex(CC_SHA1(&n, 4, buffer), 20));

  n = htonl(n);
  printf("1234 BE =        %s\n", to_hex(&n, 4));
  printf("SHA1(1234 BE) =  %s\n", to_hex(CC_SHA1(&n, 4, buffer), 20));

  return 0;
}

and here's the Android version

#include <stdio.h>
#include "mincrypt/sha.h"

char *to_hex(unsigned char *buffer, size_t len) {
  static char out[100];
  char *p = out;
  while (len--)
    p += sprintf(p, "%02x", *buffer++);
  *p = 0;
  return out;
}

int main() {
  unsigned char buffer[21] = { 0 };
  printf("SHA1(\"1234\") =   %s\n", to_hex(SHA1_hash("1234", 4, buffer), 20));

  unsigned n = 1234;
  printf("1234 LE =        %s\n", to_hex(&n, 4));  
  printf("SHA1(1234 LE) =  %s\n", to_hex(SHA1_hash(&n, 4, buffer), 20));

  n = htonl(n);
  printf("1234 BE =        %s\n", to_hex(&n, 4));
  printf("SHA1(1234 BE) =  %s\n", to_hex(SHA1_hash(&n, 4, buffer), 20));

  return 0;
}

that file is in system/core/libmincrypt and compiled with cc -I../include -o sha_test sha_test.c sha.c

both programs yield the same results

SHA1("1234") =   7110eda4d09e062aa5e4a390b0a572ac0d2c0220
1234 LE =        d2040000
SHA1(1234 LE) =  7b08e025e311c3dfcf5179b67c0fdc08e73de261
1234 BE =        000004d2
SHA1(1234 BE) =  ac9928e78cf6ea117451ecd6654fea2adae73e21

1 Comment

Sorry, my test code have some issues, the n is changed. After fix this mistake, the SHA is aligned to C code. Thank all 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.