如何在 C 和 ubuntu 中用盐加密 SHA512 散列?
How can I encrypt SHA512 hash with salt in C and ubuntu?
我正在尝试用盐加密散列。
在命令行中,我使用以下命令在影子文件中找到了正确的哈希值。
openssl passwd -6 -salt abcd apple
$6$abcd$vIWAp1OzuGuo376cRkZ5DXcgI8KIlnUibsk.iydtfCFqb9okOz.S70Ysu7.qRRg9Me5XwAyTjkZBQJXiIxwpL/
我尝试使用 openssl(How to convert a raw 64-byte binary to Hex or ASCII in C) 在 C 中获取它。
#include <openssl/sha.h>
#include <stdio.h>
#include <string.h>
int main() {
char data[] = "abcdapple";
unsigned char hash[SHA512_DIGEST_LENGTH*2+1];
SHA512((unsigned char *)&data, strlen(data), (unsigned char *)&hash);
char buffer[SHA512_DIGEST_LENGTH*2+1];
for(int i =0; i < SHA512_DIGEST_LENGTH; ++i)
sprintf(&buffer[i*2],"%02x", (unsigned int)hash[i]);
printf("digest: %s\n", buffer);
printf("\n");
}
但生成的哈希是 ea1d5a8b11297d20f954a3ab15092d21b733484b2eb9b7226b2b138639f0df30627774945458a774eb279cd83d2e977a2bc5599606d6a9a3b2f1875f9d=3
我觉得我没用好盐。似乎还有一个基本问题。
我不能用C实现加salt的加密程序吗?
您可以在 GitHub 找到 openssl passwd
命令(尤其是核心 do_passwd
函数)的源代码:https://github.com/openssl/openssl/blob/8ea761bf40e6578ecd95ec47772ef86a2e4d4607/apps/passwd.c#L795-L874
(非常 non-trivial,290 行)SHA-512 密码哈希计算函数位于 https://github.com/openssl/openssl/blob/8ea761bf40e6578ecd95ec47772ef86a2e4d4607/apps/passwd.c#L509-L793
之上一点
您最好只从您的应用中调用 openssl passwd
作为子进程。
您尝试生成的不是普通的 SHA-512 哈希。这是一个 散列密码,使用 special-purpose 算法 基于 SHA-512。 openssl passwd
计算此算法,但 OpenSSL 库的 SHA512
函数计算普通 SHA-512。 special-purpose 算法和其他几个具有相同功能的算法记录在 crypt(5) manpage.
中
您可以可能使用crypt_r
function, from the libcrypt
库(由于历史原因,该库的命名不准确;它仅提供password-hashing 算法),使用与 openssl passwd
相同的 special-purpose 算法计算散列密码。在我的电脑上,这个程序打印出与你得到的以 $abcd
开头的相同字符串:
#include <crypt.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
struct crypt_data cd;
memset(&cd, 0, sizeof cd);
puts(crypt_r("appple", "$abcd", &cd));
return 0;
}
注意第二个参数(在我一直链接到的文档中称为“设置字符串”)如何包含盐值 abcd
和前缀 $
(告诉crypt_r
使用基于 SHA-512 的哈希)。它以这种方式工作,因此 login(1)
可以调用 crypt_r
,并将刚刚从 tty 读取的密码作为第一个参数,从影子文件中输入的密码作为第二个参数,如果它返回与第二个参数相同的字符串表示用户已成功通过身份验证。
像这样编译和运行:
$ gcc -std=gnu11 -O test.c -lcrypt
$ test $(./a.out) = '$abcd$vIWAp1OzuGuo376cRkZ5DXcgI8KIlnUibsk.iydtfCFqb9okOz.S70Ysu7.qRRg9Me5XwAyTjkZBQJXiIxwpL/'; echo $?
0
我说 可能 因为这个库支持的 special-purpose 散列算法集因 Unix 而异。如果(且仅当)您可以将字符串 $abcd$...
放入 /etc/shadow
中某个帐户的密码条目中,然后使用密码 appple
以该帐户成功登录,那么它应该可以工作。
libcrypt 也可能有一个名为 crypt_gensalt_rn
的函数,您可以使用它来生成设置字符串和 select 适当的哈希算法。这是该功能的演示:
#include <crypt.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
char setting[CRYPT_GENSALT_OUTPUT_SIZE];
crypt_gensalt_rn(0, 0, 0, 0, setting, CRYPT_GENSALT_OUTPUT_SIZE);
struct crypt_data cd;
memset(&cd, 0, sizeof cd);
puts(crypt_r("appple", setting, &cd));
return 0;
}
如果你编译并运行这个程序它将不会打印以$abcd
开头的字符串;它将打印其他内容,例如
$y$j9T[=13=]aVoGQ/PFN0PHbcYlKZdZ1NbMJLbRliM7fmtSAeZoy3OoRsBqETpAZXQpnPey82
每次你 运行 它打印的内容都会改变,但它输出的每个字符串都可以用作 /etc/shadow
条目,允许某人使用密码登录 appple
.您可以使用我保留为 0 的前四个参数来控制它的行为。
(披露:我是 lib(x)crypt 的作者之一。)
我正在尝试用盐加密散列。
在命令行中,我使用以下命令在影子文件中找到了正确的哈希值。
openssl passwd -6 -salt abcd apple $6$abcd$vIWAp1OzuGuo376cRkZ5DXcgI8KIlnUibsk.iydtfCFqb9okOz.S70Ysu7.qRRg9Me5XwAyTjkZBQJXiIxwpL/
我尝试使用 openssl(How to convert a raw 64-byte binary to Hex or ASCII in C) 在 C 中获取它。
#include <openssl/sha.h>
#include <stdio.h>
#include <string.h>
int main() {
char data[] = "abcdapple";
unsigned char hash[SHA512_DIGEST_LENGTH*2+1];
SHA512((unsigned char *)&data, strlen(data), (unsigned char *)&hash);
char buffer[SHA512_DIGEST_LENGTH*2+1];
for(int i =0; i < SHA512_DIGEST_LENGTH; ++i)
sprintf(&buffer[i*2],"%02x", (unsigned int)hash[i]);
printf("digest: %s\n", buffer);
printf("\n");
}
但生成的哈希是 ea1d5a8b11297d20f954a3ab15092d21b733484b2eb9b7226b2b138639f0df30627774945458a774eb279cd83d2e977a2bc5599606d6a9a3b2f1875f9d=3
我觉得我没用好盐。似乎还有一个基本问题。 我不能用C实现加salt的加密程序吗?
您可以在 GitHub 找到 openssl passwd
命令(尤其是核心 do_passwd
函数)的源代码:https://github.com/openssl/openssl/blob/8ea761bf40e6578ecd95ec47772ef86a2e4d4607/apps/passwd.c#L795-L874
(非常 non-trivial,290 行)SHA-512 密码哈希计算函数位于 https://github.com/openssl/openssl/blob/8ea761bf40e6578ecd95ec47772ef86a2e4d4607/apps/passwd.c#L509-L793
之上一点您最好只从您的应用中调用 openssl passwd
作为子进程。
您尝试生成的不是普通的 SHA-512 哈希。这是一个 散列密码,使用 special-purpose 算法 基于 SHA-512。 openssl passwd
计算此算法,但 OpenSSL 库的 SHA512
函数计算普通 SHA-512。 special-purpose 算法和其他几个具有相同功能的算法记录在 crypt(5) manpage.
您可以可能使用crypt_r
function, from the libcrypt
库(由于历史原因,该库的命名不准确;它仅提供password-hashing 算法),使用与 openssl passwd
相同的 special-purpose 算法计算散列密码。在我的电脑上,这个程序打印出与你得到的以 $abcd
开头的相同字符串:
#include <crypt.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
struct crypt_data cd;
memset(&cd, 0, sizeof cd);
puts(crypt_r("appple", "$abcd", &cd));
return 0;
}
注意第二个参数(在我一直链接到的文档中称为“设置字符串”)如何包含盐值 abcd
和前缀 $
(告诉crypt_r
使用基于 SHA-512 的哈希)。它以这种方式工作,因此 login(1)
可以调用 crypt_r
,并将刚刚从 tty 读取的密码作为第一个参数,从影子文件中输入的密码作为第二个参数,如果它返回与第二个参数相同的字符串表示用户已成功通过身份验证。
像这样编译和运行:
$ gcc -std=gnu11 -O test.c -lcrypt
$ test $(./a.out) = '$abcd$vIWAp1OzuGuo376cRkZ5DXcgI8KIlnUibsk.iydtfCFqb9okOz.S70Ysu7.qRRg9Me5XwAyTjkZBQJXiIxwpL/'; echo $?
0
我说 可能 因为这个库支持的 special-purpose 散列算法集因 Unix 而异。如果(且仅当)您可以将字符串 $abcd$...
放入 /etc/shadow
中某个帐户的密码条目中,然后使用密码 appple
以该帐户成功登录,那么它应该可以工作。
libcrypt 也可能有一个名为 crypt_gensalt_rn
的函数,您可以使用它来生成设置字符串和 select 适当的哈希算法。这是该功能的演示:
#include <crypt.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
char setting[CRYPT_GENSALT_OUTPUT_SIZE];
crypt_gensalt_rn(0, 0, 0, 0, setting, CRYPT_GENSALT_OUTPUT_SIZE);
struct crypt_data cd;
memset(&cd, 0, sizeof cd);
puts(crypt_r("appple", setting, &cd));
return 0;
}
如果你编译并运行这个程序它将不会打印以$abcd
开头的字符串;它将打印其他内容,例如
$y$j9T[=13=]aVoGQ/PFN0PHbcYlKZdZ1NbMJLbRliM7fmtSAeZoy3OoRsBqETpAZXQpnPey82
每次你 运行 它打印的内容都会改变,但它输出的每个字符串都可以用作 /etc/shadow
条目,允许某人使用密码登录 appple
.您可以使用我保留为 0 的前四个参数来控制它的行为。
(披露:我是 lib(x)crypt 的作者之一。)