【问题标题】:How to store the hex value generated by MD5 as an integer?如何将 MD5 生成的十六进制值存储为整数?
【发布时间】:2012-03-08 20:35:27
【问题描述】:

我正在使用以下代码为字符串生成 MD5 哈希。以十六进制打印的值似乎是正确的(我在网站上验证了相同的字符串)。但是,当我将值打印为整数时,它有 36 位数字。我的理解是它应该有 16 位数字,因为生成的哈希是 128 位长。

我想知道应该如何从 unsigned char 转换为 int 以及如何将其存储在变量中,以便最终将其打印到文件中。

如果有人能解释这些值是如何存储在 unsigned char 中的,例如表示十六进制和十进制的一位数字需要多少位以及如何在它们之间进行转换,那就太好了。我尝试了 sscanf 和 strtol 但我想我没有正确使用它们。

    int main (void)
    {
      char *str = "tell";
      u_int8_t *output; //unsigned char
      output = malloc(16 * sizeof(char));
      int i = 0;
      MD5_CTX ctx;
      MD5Init(&ctx);
      MD5Update(&ctx, str, strlen(str));
      MD5Final(output, &ctx);

      while(i < 16)
        printf("%x",output[i++]);
      printf("\n");
      i = 0;
      while(i < 16)
        printf("%i",output[i++]);
      printf("\n");
    }

这里的输出是

fe17ec3c451f132ef82a3a54e84a461e
254232366069311946248425884232747030

【问题讨论】:

标签: c hex int md5


【解决方案1】:

您正在打印每个字节的十进制值(254、23、236,...),而不是转换为 int 的单个 128 位值。您的循环应该类似于value &lt;&lt;= 8; value+=output[i++](前提是您的value 是一种可以容纳如此大数字的类型)。

你对结果应该是多少位数的期望也没有;除非您打印前导零,否则它的长度可以是 1 到 len(2**128-1) 之间的任何值,即 39 个十进制数字。

顺便说一句,您还应该对十六进制输出进行零填充,否则任何值低于 16 的字节都将打印一个十六进制数字 (printf("%02x",...))。

【讨论】:

  • 三人组,感谢您的回复。你能告诉我value &lt;&lt;= 8; value+=output[i++] 的工作原理吗?我知道你在左移值,但为什么每次都添加value+output[i++]?如果我们只是说value=output[i++],输出[i] 的位不会填充值的最低有效位空间,然后我们只是左移它们以容纳接下来的 8 位?
  • 是的,完全正确。您得到的表示可以解释为一个 base-256 数字,其中每个字节包含一个“数字”0-255。
【解决方案2】:

您不能在 int 中存储 128 位值(除非 int 在您的 C 实现中至少有 128 位,我有信心预测它不是)。 long long 也是如此,这是最大的标准整数类型。

您打印的十进制值是“254”(0xfe 的十进制),然后是“23”(0x17 的十进制),依此类推。这基本上没有意义——如果你像这样代表0x010001 0x0A01,你会得到相同的字符串101。你得到了 36 位数字,因为这恰好是 16 个字节值中每个小数位数的总数。

您打印的十六进制值是 32 个字符长(每个字符 4 位,32 个字符,128 位)。这实际上有点幸运,您的摘要中的每个字节恰好至少是0x10。您应该使用 %02x 打印以包含小值的前导 0。

如果要将 128 位值表示为十进制字符串,则需要 bignum 库或长除法。但是用十进制表示 MD5 校验和是毫无意义的:当人们将它们表示为字符串时,他们总是使用十六进制。

如果有人能解释这些值是如何存储在无符号字符中的,那就太好了

每个unsigned char 中的摘要有 8 位,数组中有 16 个无符号字符,构成 128 位。不能使用sscanfstrtol,因为MD5Final 存储的值不是字符串。

【讨论】:

  • 感谢您的详细回复。我意识到用十进制我打印的是 8 位数字而不是整数。但是,为什么相同的方法适用于十六进制,即打印 8 位,每个得到摘要的十六进制。我需要十进制值,因为我想将十进制值用作哈希表中的键,并在其他一些计算中使用它。
  • 十六进制是一种表示,其中每 4 位由一个符号表示。您可以方便地同时获取和打印两个...十六进制是处理 2 因数的流行表示并非巧合!
  • 三人组怎么说。任何 2 的幂都具有相同的便利性。您可以获取一些二进制数据,一次抓取n 位,然后将每个块独立打印为基数2^n 中的数字(可能与字节序有关)。结果是以2^n 为基础的整个二进制数据的表示。它不适用于不是 2 的幂的基数,因为以 10 为基数的第一个数字不仅仅取决于前几位。
猜你喜欢
  • 2012-04-02
  • 2014-07-24
  • 2021-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多