How do I create a unix password hash with php - php

I'm trying to create system users with a php script securely, In that, I'd like to be able to hash the password with the php script, so that their password shows up nowhere in the bash history.
How to I take a string, and hash it so it is a unix password hash?
$UX_PW = some_function('my_password');
exec("useradd -p $UX_PW newusername");

It's crypt() that implements the UNIX password hashing.
http://us.php.net/manual/en/function.crypt.php

Depending on your system, you're either looking for crypt() or md5().
Traditionally, unix uses DES-encrypted passwords (thats the 'crypt' function), with a 2-character salt (two random characters from the set [a-zA-Z0-9./]) which is prepended to the hash to perturb the algorithm.
Newer systems often use MD5 though.

Use crypt. Recent linux/unixes use CRYPT_MD5 or
CRYPT_BLOWFISH. MD5 is the most widely supported one. DES's are for old systems.
Also I should note that the MD5 version is not a simple MD5 sum operation, it also uses a "salt" value to make hashes not-precalculatable. [[ I made up this term :) ]]

The password-hashing used on UNIX, Linux, and other UNIX-like POSIX operating systems varies a lot. Most "passwd" hashing methods uses a modified DES algorithm (not true DES), they may apply the hashing to the input multiple times, and they use a salt of 16 or 24 bits. A specific answer of the method to produce a passwd-compatible hash depends on which operating system you're using.
The crypt() system call should be the way to do password hashing according to your operating system. You can access it in PHP using the function crypt().
As for which crypt algorithm to use, this depends on your operating system.

From the Ubuntu Intrepid man page on passwd (change password)
The security of a password depends upon the strength of the encryption algorithm and the size of the key space. The UNIX System encryption method is based on the
NBS DES algorithm and is very secure. The size of the key space depends upon the randomness of the password which is selected.
Also, instead of using crypt() you may prefer hash() because this allows you to keep the string setting for the hash algorithm elsewhere. If your code needs to use a different hash algorithm for other environments, you'll only have to change the string and not the name of the function.

Related

Create and verify sha-512 password hashes with crypt() and PHP

The PHP function crypt() creates a hash for a password. It requires a second parameter for a random salt. This salt can also include additional instructions about which algorithm to use. Seems like a hack, but that's the API. So I add the $6$ prefix to get the SHA-512 hash I need. (Can't use bcrypt for the external non-PHP application that shall also be able to verify the hash. The hash must be verified from PHP and other applications with limited algorithms support.)
Now there are two problems that the PHP manual leaves me alone with:
1) Where do I get a random salt and what requirement does it need to satisfy? I've read about openssl_random_pseudo_bytes and I thought I'd just base64-encode it. But how many source bytes or encoded characters do I need?
2) How can I verify such a hash in PHP again? There doesn't seem to be a single function to do that. I believe I can call crypt again with the same salt as before, but to do that, I need to extract the hash and algorithm and whatever else is needed from the stored password hash. I've seen hashes with variable number of $ characters, so that doesn't seem like a good delimiter to split by.
I've read about phpass but it doesn't support sha-512, so I can't use that.
PHP version is 5.5.9 so some functions may not be available.

Local/Production Crypt Returning Different Hashes

PHP crypt function is returning different hashes on local and production server.
On localhost the crypt hash validation is working fine, but on production its not.
Local: PHP 5.4.4
Procution: PHP 5.3.10-1ubuntu3.5
Code:
echo crypt('123123123');
Local Example Response:
$1$7ymnm8q/$M6HLj2JEvzWGElqlwjAKm0
Production Example Response:
$6$sbttg2v6$2YAU3dNKR/.MRGmbBV4sR8vEhr/L8aOMTej1u3gArhgIiCiJ5IFJ
Citing from the PHP docu on crypt():
crypt() will return a hashed string using the standard Unix DES-based algorithm or alternative algorithms that may be available on the system.
So cyrpt() is not bound to a specific algorithm, but uses, what the system supports.
You may use the following constants to see, which are supported in the system you are running crypt():
CRYPT_STD_DES
CRYPT_EXT_DES
CRYPT_MD5
CRYPT_BLOWFISH
CRYPT_SHA256
CRYPT_SHA512
If you look at the examples in the docu, you'll see, that your local code uses MD5 for encryption, while the production server uses SHA-512.
Furthermore you don't specify a specific salt, so PHP will generate one for you, which will also differ in each invocation of crypt().
The systems use different default hashing algorithms: $1$ stands for MD5, $6$ for SHA-512
You should specify the algorithm explicitly using the salt parameter:
crypt('123123123', '$6$somerandomstring');
See crypt() documentation:
salt An optional salt string to base the hashing on. If not provided, the behaviour is defined by the algorithm implementation and
can lead to unexpected results.

Using Blowfish for Encryption with PHP

I am working on a registration form where I need to encrypt password, I've heard that it is recommended for me to use the Blowfish encryption for passwords, How do you implement a blowfish encryption using PHP crypt() function? also, I am planning to retrieve the password later for logging in.
The short answer is use crypt with a salt beginning with the characters $2a$, a two digit cost parameter, $, and 22 digits from the alphabet ./0-9A-Za-z. That only works on systems that support the Blowfish encryption algorithm. However, PHP 5.3 implements it natively. See PHP manual — crypt for more details.
Example:
crypt('rasmuslerdorf', '$2a$07$somesillystringforsalt')
The salt string triggers the appropriate algorithm. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithm and must be in range [04 – 31]. In the example 07 tells the algorithm to use 27 or 128 iterations. The higher this number, the longer it will take to execute BUT, in the context of hashing user passwords, that is a GOOD thing.
This answer to a similar question explains in more detail what BCrypt is,how it relates to Blowfish, and why you should use it. There are many other related topics here on Stack Overflow.
phpass is an excellent, easy to use password hashing framework that works on all systems, using Blowfish if it’s supported, and falling back to other algorithms if it’s not.
You should never need blowfish to encrypt a password like this. The registration form should be over HTTPS, which will handle defense against an attacker on the wire. The password its self should be hashed (never encrypted). bcrypt is a good password hash function based on blowfish. But there are plenty of posts related to secure password storage on SO.

Storing passwords securely in MySQL, but still accessible by PAM

We have a PHP application that stores passwords just using the MD5 function (with no salt).
We have OpenSSH set to use pam-mysql to authenticate users from the same database.
We would like to switch to use hashed passwords and we are considering either: 1. doing it ourselves, (something like md5($salt."$".$password) or hash("sha256", $salt."$".$password)), or 2. using php's crypt function (which uses the OS crypt(3) if available).
The problem is that I have not found whether pam-mysql supports crypt(3) or any replacement pam module that does.
crpyt(3) uses a user supplied algorithm and salt: crypt('password', '$5$saltstring$') for sha256 which returns $5$saltstring$OH4IDuTlsuTYPdED1gsuiRMyTAwNlRWyA6Xr3I4/dQ5. Any language that uses the crypt(3) library will see that string and know to use sha256 with the given hash and expect the given result.
Is the first method sufficient or is there some PAM module out there that supports MySQL and crypt(3)?
Use sha512, either a mysql implementation or a php implementation. If you use md5 you're using a known insecure function which opens you up to liability.
you may also use 3DES encryption for stronger security.

How to make a permanent tripcode?

I mean, crypt()'s return is always different.
So how do websites like 4chan do to give a permanent tripcode to a password?
Are they stored in a database?
4chan's tripcodes are created using a specific formula, and are a shorter version of a hash. You can achieve the same effect by using MD5 or SHA1.
Encrypt string to MD5 (PHP):
$md5 = md5("$string");
Encrypt string to SHA1 (PHP):
$sha1 = sha1("$string");
There is no way to reverse the hashing process (just like tripcodes), but with time and power they can be "bruteforced" back to plain text.
It's quite common to salt a password, then hash it using DES, MD5, SHA, or newer hashes. The salt is then stored as part of the password.
PHP's crypt works this way, although the exact algorithm it uses to hash the password may be different between versions of PHP... and even between operating systems, although the latter supposedly changed in PHP 5.3. (PHP now includes its own hashing library instead of relying on the OS library, which is really, really important if you're using Windows, as crypt function on Windows only supported DES with 2-byte salt prior to this)
Edit:
Note: crypt has an optional second argument. Passing the encrypted password as the second argument will usually get PHP to detect the salt and algorithm used to originally hash the password, namely because everything other than DES start with $#$ where # is a number.
You pass the salt to crypt() as the second argument. This causes the output to use that salt instead of generating one on the fly.
The salt being randomly generated is why crypt("something") returns different results each time. If I run crypt("something", "ab"), it'll be identical every time. I don't have PHP here to check what the value is, though.
Wikipedia has an article about Tripcodes.
I think there's a table "tripcodes" where tripcodes were generated with the Wikipedia's and they are associated with strings they come from, no?
Yes password are stored in a database but without the use of crypt(). They use sha1() or encryption database function like AES_ENCRYPT() in mysql.

Categories