了解MD5情况下crypt()的输出

时间:2018-07-10 08:33:45

标签: c linux md5 glibc crypt

crypt(3)函数的glibc版本支持MD5算法。根据文档:

If salt is a character string starting with the characters "$id$"
followed by a string optionally terminated by "$", then the result
has the form:

       $id$salt$encrypted

文档还指出,对于MD5,$id必须为1,并且encrypted字符串的大小固定为22个字符。

但是MD5输出始终为128位长度。那怎么只有22个字符呢?

我认为它将是Base64编码的,因为128位可以表示22个Base64字符。让我们验证一下我的假设。

下面是我编写的用MD5调用crypt()的简单代码,没有盐用于加密:

#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    char md5[] = "$1$";
    char *res;
    res = crypt("helloworld", md5);
    printf("res = %s\n", res);
    return 0;
}

运行它:

$ ./crypt
res = $1$$edK86ZB1Vvaz2eneY.itb.

根据helloworld的{​​{1}}的MD5加密值为crypt()

现在通过online tooledK86ZB1Vvaz2eneY.itb.计算helloworld的MD5哈希值:

md5sum

MD5哈希值为$ echo -n helloworld | md5sum fc5e038d38a57032085441e7fe7010b0 - 。通过this online converter或以下命令将该十六进制字符串转换为Base64:

fc5e038d38a57032085441e7fe7010b0

此值不同于上面$ echo "fc5e038d38a57032085441e7fe7010b0" | xxd -r -p | base64 /F4DjTilcDIIVEHn/nAQsA== 产生的值。

那么crypt()在这种情况下如何产生其输出,或者我应该如何解释它?我在这里想念什么?

1 个答案:

答案 0 :(得分:3)

它使用MD5算法,但不返回生成的MD5哈希。来自here的来源中发生了许多奇怪的事情:

#define OP1(a,b,op) ((a) op (b))

/* The original implementation now does something weird: for every 1
   bit in the key the first 0 is added to the buffer, for every 0
   bit the first character of the key.  This does not seem to be
   what was intended but we have to follow this to be compatible.  */
here/* Now comes another weirdness. In fear of password crackers here comes a quite long loop which just processes the output of the previous round again. We cannot ignore this here. */ 调用

__md5_crypt_r

它使用MD5算法,但不会在用户字符串中返回md5哈希。而是使用多个transformations来“加密”输入字符串。

对于md5哈希,请使用openssl / md5.h。我想我建议不要使用libc的加密系列功能,除非编写的东西很小而且不能移植。从html documentation

  

[...] DES仅使用56位密钥(加上8个奇偶校验位),并且于1998年制造了一台机器,可以在大约6天的时间内搜索所有可能的密钥,价格约为20万美元;有了更多的钱,就有可能更快地进行搜索。这使得简单的DES在大多数情况下都不安全,并且NIST不再允许新的美国政府系统使用简单的DES。