tags:

views:

232

answers:

2
typedef union
{
    uint ui[4];
} md5hash;

void main(void)
{
    int opt;

    while ((opt = getopt(argc, argv, "c:t:s:h:")) != -1) {
        switch (opt) {
        case 'h':
            hash = optarg;
            break;
        default: /* '?' */
            exit(EXIT_FAILURE);
        }
    }

    md5hash hash;

    sscanf(hash, "%x%x%x%x", &hash.ui);
}

./program -h ffffffffffffffffffffffffffffffff

I want to do the above, but sscanf does not accept the md5sum properly...

+5  A: 
  1. You seem to have two variables called hash, except one is implicit in your code.
  2. The sscanf statement attempts to read hash back into itself, but obviously it will not find any hexadecimal digits.
  3. %x may load a different sized integer in hexadecimal on different platforms because you have not specified any specific length to read for each field.
  4. You are not taking into account machine endianness.

If you do have a hexadecimal string, let's say in hashString then you can probably try

int fieldsScanned = sscanf (hashString, "%8x%8x%8x%8x", &hash.ui[0], &hash.ui[1], &hash.ui[2], &hash.ui[3]);

if (fieldsScanned == 4)
{
    // MD5 sum is in hash variable.
}
dreamlax
There are other problems with the code too. Such as a union with one member is pretty pointless.
Jonathan Leffler
Separately, your sscanf() code would match a mistyped MD5 checksum with just 25 hex digits. You probably should do a more thorough scrutiny of the string before accepting it - all hex digits and length is 32 - though a non-hex digit before the last conversion starts would fail anyway.
Jonathan Leffler
A: 
int
parse_hex(char *s, unsigned char *hex, int len)
{
  int i, r = 0;

  len *= 2;
  for (i = 0; ; i++, s++)
    {
      if (*s == 0 && !(i & 1))
        return i / 2;
      if (i == len)
        {
          fprintf(stderr, "parsehex: string too long\n");
          //exit(1);
        }
      if (*s >= '0' && *s <= '9')
        r = (r << 4) | (*s - '0');
      else if (*s >= 'a' && *s <= 'f')
        r = (r << 4) | (*s - ('a' - 10));
      else if (*s >= 'A' && *s <= 'F')
        r = (r << 4) | (*s - ('a' - 10));
      else
        {
          fprintf(stderr, "parsehex: bad string\n");
          //exit(1);
        }
      if ((i & 1) != 0)
        {
          hex[i / 2] = r;
          r = 0;
        }
    }
}

void
parse_md5(char *s, unsigned char *md5)
{
  if (!*s)
    {
      memset(md5, 0, 16);
      return;
    }
  if (parse_hex(s, md5, 16) != 16)
    {
      fprintf(stderr, "parsemd5: bad md5\n");
      //exit(1);
    }
}

actually, the sscanf() method above does not work, it reads the bytes in reverse order within the doublewords.