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 tool或edK86ZB1Vvaz2eneY.itb.
计算helloworld
的MD5哈希值:
md5sum
MD5哈希值为$ echo -n helloworld | md5sum
fc5e038d38a57032085441e7fe7010b0 -
。通过this online converter或以下命令将该十六进制字符串转换为Base64:
fc5e038d38a57032085441e7fe7010b0
此值不同于上面$ echo "fc5e038d38a57032085441e7fe7010b0" | xxd -r -p | base64
/F4DjTilcDIIVEHn/nAQsA==
产生的值。
那么crypt()
在这种情况下如何产生其输出,或者我应该如何解释它?我在这里想念什么?
答案 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。