vitalnix user management suite 3.2.0


Name

vxutil_phash -- password hashing in Vitalnix

Syntax

#include <vitalnix/libvxutil/libvxutil.h>

bool vxutil_phash(const char *key, const char *salt, unsigned int algorithm, char **result);


Link with -lvxutil.

Description

vxutil_phash() is the password hashing/encryption function in Vitalnix.

key is a password or any random string that is to be hashed/encrypted.

salt is a random string used to perturb the algorithm in varying number of ways. Different algorithms require different salt strings. See below for details. salt may be NULL, in which case vxutil_phash() will generate a suitable random salt internally and use it.

The base64 set

The base64 character set is [./0-9A-Za-z].

While non-base64 characters in the salt work in Glibc's and Vitalnix's implementations, you should not rely on this behavior, especially because database backends (such as Shadow, see vxdrv_shadow(7)) put restrictions on what characters to use. Using non-base64 characters will yield undefined results and possibly corrupts your database or the hash when the hash is inserted into the DB.

Algorithm overview

DES crypt

DES crypt is selected using the VXPHASH_DES constant for the algorithm argument. DES is a weak 56-bit block cipher, and only the first eight characters of the key are used. The salt must be a two-character string from the base64 character set. Vitalnix relies on libc/libcrypt to provide the implementation of this algorithm, so it is not available, for example, under Microsoft Windows. Use of DES is discouraged.

MD5 hash

MD5 hashing is selected using the VXPHASH_MD5 constant. Both the key and salt (full length, unlike DES) are used to build the 128 bit digest.

The salt consits of a ID prefix, the salt and optionally a dollar sign. The ID is the three-character string "$1$", and the salt is string of base64 characters with minimum length 0 and maximum length 8. It will automatically be truncated if it is longer than this. Valid salts would be, for example, "$1$", "$1$$", "$1$ABC" and "$1$longerthaneight$".

Blowfish crypt

Blowfish crypt is selected using VXPHASH_BLOWFISH. It features a highly complex key schedule and its number of rounds is tunable, which makes it fit for the long-term use.

The salt consists of the ID prefix "$2a$", a salt string of exactly 22 base64 characters and an optional dollar sign.

NT4 hash

Windows NT hashing is selected using VXPHASH_SMBNT. The salt argument is ignored. The NT4 hash is a simple 128-bit MD4 digest of the key with a few static transformations without any salt perturbation, and hence is susceptible to dictionary and rainbow attacks. I discourage its use, though unfortunately, Windows clients rely on this.

SHA-256 hash

The SHA family of password hashing has been introduced just recently (September 2007) as a successor to the DES crypt and MD5 hash methods. It works similarly to the MD5 variant, but like Blowfish, the number of rounds can also be tuned.

The SHA-256 hash method can be selected using VXPHASH_SHA256. The salt string is made up of the ID "$5$", an optional rounds parameter "rounds=N$", up to 16 base64 characters and an optional dollar sign. The number of rounds, if provided, must be between 1,000 and 999,999,999 (inclusive). If it exceeds these limits, the value will be clamped. A valid example: $5$rounds=5000$abcdefghijklmnop$

SHA-512 hash

The SHA-512 hash method can be selected using VXPHASH_SHA512. Its ID is "$6$" and also allows a rounds parameter and uses 16 base64 characters.

Return value

vxutil_phash() will return a boolean, indicating either success or failure. On success, *result is filled with a pointer to an allocated region of memory containing the hash, which you are supposed to free when you are done with it.

Failure may arise if the wanted algorithm is not available or a memory allocation failure occurred. The contents of the errno variable are undefined.

Example

char *result = NULL;
if (vxutil_phash("password", "$2a$05$ABCDEFGHIJKLMNOPQRSTUV$", VXPHASH_BLOWFISH, &result)) {
    printf("%s\n", result);
    free(result);
}