Reputation: 71
I'm trying to encrypt hash with salt.
In command line, I found right hash written in the shadow file using below command.
openssl passwd -6 -salt abcd appple $6$abcd$vIWAp1OzuGuo376cRkZ5DXcgI8KIlnUibsk.iydtfCFqb9okOz.S70Ysu7.qRRg9Me5XwAyTjkZBQJXiIxwpL/
And I tried to get it in C using openssl(How to convert a raw 64-byte binary to Hex or ASCII in 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");
}
but generated hash is ea1d5a8b11297d20f954a3ab15092d21b733484b2eb9b7226b2b138639f0df30627774945458a774eb279cd83d2e977a2bc5599606d6a9a3b2f075f9b1895ecd, which is different from right thing.
I think I didn't use salt well. Also there seems to be a fundamental problem. Can't I implement encrypt program with salt using C?
Upvotes: 1
Views: 2731
Reputation: 140445
What you are trying to generate is not an ordinary SHA-512 hash. It's a hashed password using a special-purpose algorithm based on SHA-512. openssl passwd
computes this algorithm, but the OpenSSL library's SHA512
function computes ordinary SHA-512. This special-purpose algorithm, and several others with the same function, are documented in the crypt(5) manpage.
You can probably use the crypt_r
function, from the libcrypt
library (this library is inaccurately named for historical reasons; it only provides password-hashing algorithms), to compute hashed passwords using the same special-purpose algorithm as openssl passwd
does. On my computer, this program prints the same string starting with $6$abcd
that you got:
#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", "$6$abcd", &cd));
return 0;
}
Notice how the second argument (referred to as a "setting string" in the documentation I've been linking to) contains both the salt value abcd
and the prefix $6$
(which tells crypt_r
to use the SHA-512-based hash). It works this way so that login(1)
can call crypt_r
with the password it just read from the tty as the first argument, and the password entry from the shadow file as the second argument, and if it gets back the same string it put as the second argument then the user has successfully authenticated.
Compile and run like so:
$ gcc -std=gnu11 -O test.c -lcrypt
$ test $(./a.out) = '$6$abcd$vIWAp1OzuGuo376cRkZ5DXcgI8KIlnUibsk.iydtfCFqb9okOz.S70Ysu7.qRRg9Me5XwAyTjkZBQJXiIxwpL/'; echo $?
0
I say probably because the set of special-purpose hashing algorithms supported by this library varies from Unix to Unix. If (and only if) you can put the string $6$abcd$...
in some account's password entry in /etc/shadow
and then successfully log in as that account using the password appple
, then it should work.
libcrypt may also have a function called crypt_gensalt_rn
which you can use to generate setting strings and select an appropriate hashing algorithm. Here's a demo of that function:
#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;
}
If you compile and run this program it will not print the string starting with $6$abcd
; it will print something else, such as
$y$j9T$0aVoGQ/PFN0PHbcYlKZdZ1$05NbMJLbRliM7fmtSAeZoy3OoRsBqETpAZXQpnPey82
and what it prints will change every time you run it, but each of the strings it outputs will be usable as an /etc/shadow
entry allowing someone to log in with password appple
. You can control its behavior with the first four arguments that I left at 0.
(Disclosure: I am one of the authors of lib(x)crypt.)
Upvotes: 3
Reputation: 168824
You can find the source for the openssl passwd
command (and in particular the core do_passwd
function) over at GitHub: https://github.com/openssl/openssl/blob/8ea761bf40e6578ecd95ec47772ef86a2e4d4607/apps/passwd.c#L795-L874
The (very non-trivial, 290-line) SHA-512 passwd hash computation function is found a little above that, at https://github.com/openssl/openssl/blob/8ea761bf40e6578ecd95ec47772ef86a2e4d4607/apps/passwd.c#L509-L793
You're probably better off just calling openssl passwd
from your app as a subprocess.
Upvotes: 1