This scheme looks clever, but it isn't.
Salts are usually stored in cleartext. And they serve one purpose - to restrict the usability of precomputed hash tables. There is also the side-effect that no two hashes computed for two different user accounts with the same password will be the same.
By storing a portion of the password as a salt, you are decreasing the security posture of the application, and also complicating matters:
- I would consider that the entropy associated with the password is reduced by a minimum value of the entropy associated with the 8 bits; in the Shannon model of calculating entropy of user selected passwords from a 94 character alphabet, this around 4 bits of entropy. The reduction in entropy is due to the model in use - most passwords are not a sequence of random bits, especially if they are chosen from natural languages. Concatenating n-bits from the password to itself to compute a hash will quite obviously make the contents of the password even less random, thus reducing entropy.
- Using the first 8 bits of the password as the salt is in itself a poor decision, compared to using the last 8 bits, not that the latter is a good decision. It so happens that under the Shannon model for computing entropy of a password, the entropy per bit reduces as the length of the password increases. If you are using the first n bits as the salt, then you are weakening the password further, as the Shannon model works on the premise that "if the first n bit is known, then how well can anyone guess the other following bits".
Now that you've stored the password fragment in cleartext, you will need to encrypt it. That sounds easy, except that keys have to associated with a management lifecycle where you need to issue them, protect them, and discard them after a particular period; getting of this right is certainly not as easy as using a secure PRNG to generate the salt and storing this random sequence of bits in the clear.This is irrelevant if one is not storing the salt.
Cryptographic properties of a salt
This is based on Paul's answer and the comments interspersed on this page. Any data used as a salt to a password, must satisfy certain cryptographic properties. The most important one is that
A salt must be unique across the passwords stored in the system.
If the salt is not unique, then one loses the ability to create unique hashes for every password managed by the system, leading to the possibility that a dump of hashes might reveal passwords that are used across accounts or passwords present in dictionaries.
It cannot be guaranteed that the scheme in question has this property. In fact it is easy to assume that the property is bound to be absent in a system with more than 2^8 = 256 users, rendering the scheme quite useless.
Also, if one is under the impression that this scheme can reasonably protect against pre-computed hashes then that assumption is moot. It assumes that an attacker does not have resources at his disposal to compute hashes to compromise all the accounts in a reasonable timeframe. Using a salt with the cryptographic property of being unique would have certainly slowed down the attacker by a large factor, as a computed hash would be valid only for one salt and not for the others (i.e. hashes for any password in a dictionary must be recomputed for every user). If the current scheme were to be employed, an attacker can restrict himself to computing only 1 hash per password in a dictionary, making it no different from not using a salt, thus making it pointless to have a salt in the first place.
This would lead to another property of a cryptographic salt:
A salt must enhance the resistance of the system against bruteforce attacks and the like.
By using a salt derived from a password, one loses this property, for a hash of every password in a dictionary can be computed in more or less the same amount of time, with or without the salt. The apparent loss in entropy has already been pointed out (see above).
It it to this effect that most systems are engineered to generate the salt of sufficient length using a secure PRNG. One of the comments stated that using a "service name" + "user name" combination is enough. I would say that it is a good thing to start of with. The service name typically acts as a pepper (especially when it is not stored), so that hashes themselves cannot be copied and used across services using the same hashing scheme. The username is decent enough to use as a salt, except in scenarios where the username is public (the root
account in *nix, or Administrator
in Windows, for example). If your usernames will be public and consistent across several deployments, then using n bits of randomness ought to be the way to go. This is an extension of the second property, in that any choice of a salt must consider resistance to bruteforce attacks across all deployments.