0

I have this Python Code (hexdigest is a SHA1):

d = long(hexdigest, 16)
if d >> 159:
    return "-%x" % ((-d) & (2**160-1))
return "%x" % d

and I need this code translated into D. I tried several things:

  • to!long(hexdigest, 16) – failed with Overflow (too big for ulong)
  • std.BigInt doesn't support binary &

How would you do that in D? I tagged this question als as C related, because a C solution will also work in D.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
dav1d
  • 5,917
  • 1
  • 33
  • 52

2 Answers2

1

This code looks like a NOP. You're parsing an SHA1 hexdigest which is a 20 byte number. It's never going to exceed 160 bits, so d>>160 is always 0. So you then just reformat the hexdigest in the same format. I guess you're dropping leading zeros, if there are any.

I'm surprised D's std.BigInt doesn't provide bit operations (&,|,^). Write it yourself? Can't be that hard.

Keith Randall
  • 22,985
  • 2
  • 35
  • 54
  • Sorry, my bad it is actually `d >> 159`, I fixed that. Problem is, I don't have an idea how to implement the binary operations and I am not firm with the structure of BigInt, this would require a bit of time, which I don't have. – dav1d Jul 31 '12 at 16:33
  • Well, that condition is equivalent to `hexdigest[0]` being one of `89ABCDEFabcdef`. You could get the `&` by doing `d - ((d >> 160) << 160)` (after negating it?). – Keith Randall Jul 31 '12 at 16:40
  • In any case, this is silly. Fix the downstream code to accept unsigned numbers and forget this code. – Keith Randall Jul 31 '12 at 16:41
  • This is for a client, the server just accepts this silly format of the hash. I'll try your solution above. thanks so far. – dav1d Jul 31 '12 at 16:44
0

So you want a hex-to-hex conversion from unsigned to signed 2's complement. Did you realize you can just go digit by digit? Every digit in the input string plus its counterpart in the output string equals 0xf, except the last, where it's 0x10. Any kind of bigint arithmetic is overkill for this problem.

Demo in C (note: this doesn't strip leading zeros)

#include <stdio.h>
#include <string.h>

static int fromhex(char dig)
{
  return dig >= '0' && dig <= '9' ? dig - '0'      :
         dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 :
         dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
         -1;
}

int main(int argc, char **argv)
{
  if(argc!=2 ||
     strlen(argv[1])!=40 ||
     strspn(argv[1], "0123456789abcdefABCDEF")!=40)
  {
    fprintf(stderr, "Usage: %s sha1hex\n", argv[0]);
    return 1;
  }
  if(strchr("01234567", argv[1][0])) {
    puts(argv[1]);
  } else {
    int i;
    putchar('-');
    for(i=0;i<39;++i)
      printf("%x", 15 - fromhex(argv[1][i]));
    printf("%x\n", 16 - fromhex(argv[1][i]));
  }
  return 0;
}