diff options
author | lloyd <[email protected]> | 2012-07-01 20:03:29 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-07-01 20:03:29 +0000 |
commit | c5c144de5b5dbb03b942178ad09a66ebf5cdcb9d (patch) | |
tree | a1c5c8ea850206eedd428ba52c273efeae48e989 /doc/passhash.rst | |
parent | f5f2c6d68bd31f72c5837ebc75d5a35741c3b664 (diff) |
Rename all text files that are actually reStructuredText to .rst
Diffstat (limited to 'doc/passhash.rst')
-rw-r--r-- | doc/passhash.rst | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/doc/passhash.rst b/doc/passhash.rst new file mode 100644 index 000000000..8ce3cf805 --- /dev/null +++ b/doc/passhash.rst @@ -0,0 +1,117 @@ + +Password Hashing +======================================== + +Storing passwords for user authentication purposes in plaintext is the +simplest but least secure method; when an attacker compromises the +database in which the passwords are stored, they immediately gain +access to all of them. Often passwords are reused among multiple +services or machines, meaning once a password to a single service is +known an attacker has a substantial head start on attacking other +machines. + +The general approach is to store, instead of the password, the output +of a one way function of the password. Upon receiving an +authentication request, the authenticator can recompute the one way +function and compare the value just computed with the one that was +stored. If they match, then the authentication request succeeds. But +when an attacker gains access to the database, they only have the +output of the one way function, not the original password. + +Common hash functions such as SHA-256 are one way, but used alone they +have problems for this purpose. What an attacker can do, upon gaining +access to such a stored password database, is hash common dictionary +words and other possible passwords, storing them in a list. Then he +can search through his list; if a stored hash and an entry in his list +match, then he has found the password. Even worse, this can happen +*offline*: an attacker can begin hashing common passwords days, +months, or years before ever gaining access to the database. In +addition, if two users choose the same password, the one way function +output will be the same for both of them, which will be visible upon +inspection of the database. + +There are two solutions to these problems: salting and +iteration. Salting refers to including, along with the password, a +randomly chosen value which perturbs the one way function. Salting can +reduce the effectivness of offline dictionary generation (because for +each potential password, an attacker would have to compute the one way +function output for all possible salts - with a large enough salt, +this can make the problem quite difficult). It also prevents the same +password from producing the same output, as long as the salts do not +collide. With a large salt (say 80 to 128 bits) this will be quite +unlikely. Iteration refers to the general technique of forcing +multiple one way function evaluations when computing the output, to +slow down the operation. For instance if hashing a single password +requires running SHA-256 100,000 times instead of just once, that will +slow down user authentication by a factor of 100,000, but user +authentication happens quite rarely, and usually there are more +expensive operations that need to occur anyway (network and database +I/O, etc). On the other hand, an attacker who is attempting to break a +database full of stolen password hashes will be seriously +inconvenienced by a factor of 100,000 slowdown; they will be able to +only test at a rate of .0001% of what they would without iterations +(or, equivalently, will require 100,000 times as many zombie botnet +hosts). + +Botan provides two techniques for password hashing, bcrypt and +passhash9. + +.. _bcrypt: + +Bcrypt Password Hashing +---------------------------------------- + +Bcrypt is a password hashing scheme originally designed for use in +OpenBSD, but numerous other implementations exist. It is made +available by including ``bcrypt.h``. Bcrypt provides outputs that +look like this:: + + "$2a$12$7KIYdyv8Bp32WAvc.7YvI.wvRlyVn0HP/EhPmmOyMQA4YKxINO0p2" + +.. cpp:function:: std::string generate_bcrypt(const std::string& password, \ + RandomNumberGenerator& rng, u16bit work_factor = 10) + + Takes the password to hash, a rng, and a work factor. Higher values + increase the amount of time the algorithm runs, increasing the cost + of cracking attempts. The resulting hash is returned as a string. + +.. cpp:function:: bool check_bcrypt(const std::string& password, \ + const std::string& hash) + + Takes a password and a bcrypt output and returns true if the + password is the same as the one that was used to generate the + bcrypt hash. + +Here is an example of using bcrypt: + +.. literalinclude:: examples/bcrypt.cpp + +.. _passhash9: + +Passhash9 +---------------------------------------- + +Botan also provides a password hashing technique called passhash9, in +``passhash9.h``, which is based on PBKDF2. Its outputs look like:: + + "$9$AAAKxwMGNPSdPkOKJS07Xutm3+1Cr3ytmbnkjO6LjHzCMcMQXvcT" + +.. cpp:function:: std::string generate_passhash9(const std::string& password, \ + RandomNumberGenerator& rng, u16bit work_factor = 10, byte alg_id = 0) + + Functions much like ``generate_bcrypt``. The last parameter, + ``alg_id``, specifies which PRF to use. Currently defined values + are + + ======= ============== + Value PRF algorithm + ======= ============== + 0 HMAC(SHA-1) + 1 HMAC(SHA-256) + 2 CMAC(Blowfish) + ======= ============== + +.. cpp:function:: bool check_passhash9(const std::string& password, \ + const std::string& hash) + + Functions much like ``check_bcrypt`` |