Wiki
Download
Manual
Eggs
API
Tests
Bugs
show
edit
history
You can edit this page using
wiki syntax
for markup.
Article contents:
== crypt This egg provides functions for generating secure password hashes. This is done by providing Chicken bindings for the Unix crypt() function. It will attempt to use the system's crypt() for all available types, and supplies fallbacks when the native crypt does not implement a common scheme like Niels Provos' bcrypt() or Ulrich Drepper's SHA-2 based crypt(). If you need to forcefully override what native crypt() features are available (for example when you're cross-compiling to another platform), you can set the {{FORCE_CRYPT_HASHTYPES}} environment variable when invoking {{chicken-install}}. This should be a space-separated list of hash types. The allowed names are the same as the ones accepted by the {{crypt-gensalt}} procedure for the {{type}} argument (see below). If in doubt, set the variable to an empty string. This will force usage of all procedures provided by the egg only. If you are cross-compiling from or to OpenBSD or some other system which has {{crypt()}} as part of libc (as opposed to being in libcrypt), you may additionally need to set the {{FORCE_CRYPT_USE_LIBCRYPT}} environment variable to {{TRUE}}/{{YES}}/{{1}} or {{FALSE}}/{{NO}}/{{0}} depending on whether the target system uses a separate libcrypt or not. === Basic usage Basic usage is extremely simple (just like Unix crypt()): ==== Generating a new password hash <enscript highlight="scheme"> (import crypt) (crypt "password") => "$2a$12$eeOD.RHX7kex47wGOu3ZVu2JhRyQBBOyORhd/mTWjQghMWbrxGNCy" </enscript> This will automatically use the hashing mechanism currently deemed most secure. At the moment that is the Blowfish hashing scheme ("bcrypt") with 2^12 rounds. A new random salt is automatically generated each time this procedure is invoked with only one argument. If you want to create a crypt hash using a specific algorithm, you need to a little more work: <enscript highlight="scheme"> (import crypt) (crypt "password" (crypt-gensalt type: 'sha512)) => "$6$IDmt7XiTy5xZal/b$9Z3K/CpJsX8up48yY4ZeSlwSKEpAl73SJYzJTzX1x4/GodsKjrdRc7aLp7E4Tz6H8x04sYJx5quQgUHCMBelX/" </enscript> ==== Checking whether a password matches a hash This is done just like Unix crypt() by checking whether the generated hash matches the input hash: <enscript highlight="scheme"> (import crypt) (define h "$2a$12$eeOD.RHX7kex47wGOu3ZVu2JhRyQBBOyORhd/mTWjQghMWbrxGNCy") (string=? (crypt "password" h) h) => #t (string=? (crypt "wrong" h) h) => #f </enscript> === Why use crypt()? First and foremost, crypt() is ''safe''. Lots of thought has gone into the modern flavors of crypt. The UNIX family of operating systems have been using crypt() [[http://www.usenix.org/events/usenix99/provos/provos_html/node9.html|since 1976]] and the algorithms used by crypt() have been constantly improved over time to keep up with improvements in password cracking. It provides stretching, salting and defeats parallel cracking by using a unique salt for each password which is then automatically added to the hash. The main advantage of Unix crypt() over other safe password hashing schemes is that crypt() provides a way to upgrade the hashing mechanism to a more secure one without having to rehash all passwords; hashes are stored with a prefix code which indicates the hashing mechanism used to generate that hash, so they continue to work using the old algorithm while newly generated hashes are hashed using the stronger algorithm. It's still up to you to implement an update strategy and decide if and when to expire hashes that are no longer deemed secure enough, though! Modern flavors of crypt() allow you to tweak the cost of generating a hash (the stretching factor), to compensate for Moore's law so that as computers get faster, you can make it more expensive to generate a hash. This thwarts even highly optimized password cracking tools. Remember: slower is better for password hashing schemes! Of course, this too can be done without rehashing older passwords. Other languages might include [[http://codahale.com/how-to-safely-store-a-password/|just a library specifically for bcrypt()]], but this egg's author thinks it is a bit silly to provide a separate library with a dedicated API, since crypt() is ''designed'' to transparently upgrade to stronger algorithms as time progresses. bcrypt(), because it is [[http://www.usenix.org/events/usenix99/provos.html|adaptive for CPU speed improvements]], will provide good security for the foreseeable future ''as long as no weaknesses are discovered in the algorithm itself''. Once that happens (or a substantially better scheme is developed, etc) you would need to replace all calls to that library with a new one, or change bcrypt() to include whatevercrypt() code so that the name is no longer descriptive. This defeats the point of having a modular hash syntax in the first place. ==== Background info Crypt hashes come in three basic flavors: ===== Raw DES rEK1ecacw.7.c (salt: rE) This is just a raw base64-encoded DES password hash. The first two characters encode the salt, the rest is the hashed password. This DES-based implementation uses a fixed number of 25 rounds. ===== Extended DES Extended DES uses a variable number of encryption rounds and 24 bits of salt rather than 12 bits. _J9..K0AyUubDrfOgO4s (prefix: _J9.. salt: K0Ay) The leading underscore indicates we're using the extended DES scheme here. The first four characters after the underscore indicate the number of iterations to run the encryption algorithm, the next four represent the salt and the final eleven are the hashed password. ===== Modern, modular format This looks like the following: $ALG$ALGSPECIFIC For example: $1$O3JMY.Tw$AdLnLjQ/5jXF9.MTp3gHv/ (prefix: $1$ salt: O3JMY.Tw) For more examples of hashes, see the [[http://openwall.info/wiki/john/sample-hashes|OpenWall/John the Ripper community wiki page with sample hashes]] The ALG encodes the algorithm used for generating the hash, the ALGSPECIFIC is usually the salt followed by the hash. Some schemes store some additional settings before the salt, and some separate the salt from the hash with a dollar sign. Currently, the following values for {{ALG}} are standardized: ; {{$1$}} : Paul Hennig-Kamp's MD5 scheme. This is a very baroque system, introduced in FreeBSD, which runs a convoluted series of MD5 calls for a large but ''fixed'' number of iterations. ; {{$2a$}} : Niels Provos' Blowfish scheme, aka {{bcrypt}}. This is an adaptable scheme introduced in OpenBSD, which allows the system administrator to determine the number of rounds to run the algorithm. As hardware speed improves, this number can be increased to compensate. ; {{$5$}}: Ulrich Drepper's SHA-256 scheme. This is also an adaptable scheme, introduced in glibc. ; {{$6$}}: Ulrich Drepper's SHA-512 scheme. Same as the above, except with hashes of double the size :) There are also some less common values: ; {{$apr1$}} : Identical to {{$1$}}. This prefix is generated by the Apache Portable Runtime library (used by {{htpasswd}}, for example) ; {SHA} : SHA-1 hash, also used by the Apache Portable Runtime library. (yes, this is not compatible with the standard dollar-sign prefix. Apparently these guys '''like''' being completely incompatible to the rest of the world) ; {{$P$}} : MD5-based hash used by [[http://www.openwall.com/phpass/|PHPass - the Portable PHP password hashing framework]] ; {{$H$}} : Same as above, but used by [[http://area51.phpbb.com/docs/code/30x/phpbb3/package-functions.html#phpbb_hash()|PHPbb]] because, well, they're PHP developers. (I wonder if these developers are somehow related to the people working on APR...) ; {{$2x$}} : "compatibility" option for OpenWall's bcrypt implementation (used as fallback for bcrypt in this egg) to trigger old [[http://www.openwall.com/lists/oss-security/2011/06/20/2|buggy behavior that has a known vulnerability]], only to be used when comparing values produced by the old version. ; {{$2y$}} : "force correct algorithm" option for OpenWall's bcrypt implementation. When passed {{$2a$}} normally bcrypt will sometimes fall back to the buggy algorithm, but in this egg it acts like {{$2y}} was passed. This is done to ensure compatibility with the BSD implementation, which dictates the standard. Currently there is no way to pass {{$2x$}} or {{$2y$}} to {{crypt}} even if the OpenWall version is used internally. If you really need this, please contact me and I'll try to figure out a way to do it. === Full API reference The full API consists of two main procedures with some helpers and several algorithm-specific salt generation procedures. It's recommended you use only the algorithm-specific salt generation procedures when you have very specific needs. In the future these extra procedures might be dropped. ==== Main API <procedure>(crypt plaintext-password [salt-or-hash])</procedure> This procedure returns the hashed version of the string {{plaintext-password}} based on the settings provided by the string {{salt-or-hash}} (typically this argument is called "{{setting}}" in most POSIX documentation). If {{salt-or-hash}} is not provided or {{#f}}, a salt will automatically be generated by calling {{(crypt-gensalt)}} with no arguments. This means this procedure can be used in two ways: the first is to generate a hash for a new password and the second is to validate a password against a previously generated hash. The return value of this procedure can be stored and later used as a {{salt-or-hash}} value in subsequent calls to this procedure to validate a user-supplied password; it is a string that contains the salt and algorithm specifications as a prefix of the hash. For more info about why this works, see the "[[#background-info|Background Info]]" section. <procedure>(crypt-gensalt #!key type random)</procedure> This procedure can be used to obtain a string you can pass to the {{crypt}} procedure as the {{salt-or-hash}} argument. The string generally starts with a dollar-sign followed by an algorithm specifier, followed by the salt. For more specific info about the format of this string, see the "[[#background-info|Background Info]]" section. The {{type}} argument selects the algorithm type to use. It can currently be one of the following symbols: {{blowfish}}, {{sha512}}, {{sha256}}, {{md5}}, {{des-extended}} or {{des}}. If not supplied or {{#f}}, the value of {{(crypt-default-implementation)}} is used. The {{random}} argument can be used to supply a stronger randomization procedure. It should be a procedure that accepts two integers (a minimum and a maximum) and returns an u8vector with random values. The u8vector must have a length between the minimum and the maximum, both inclusive. The maximum can be {{#f}} when there is no upper bound. If {{random}} is not supplied or {{#f}}, the value of {{(crypt-default-random-u8vector)}} is used. ===== Generic configuration parameters <parameter>(crypt-default-implementation [type])</parameter> The default implementation specifier to put in newly generated salt strings. Can be any symbol accepted by {{crypt-gensalt}}. It will always default to the strongest algorithm that was current at the time the egg was last updated. Currently that is {{blowfish}}. <parameter>(crypt-default-random-u8vector [proc])</parameter> The default implementation to use by {{crypt-gensalt}} as a source of randomly-filled u8vectors. This procedure should accept two integer arguments; a minimum and a maximum length for the u8vector to return. The maximum may also be {{#f}} if there is no upper bound. Defaults to {{crypt-maximum-random-u8vector}}, which uses the [[/man/5/Module (chicken random)#pseudo-random-integer|pseudo-random-integer]] procedure which is provided by the CHICKEN {{(chicken random)}} module. This is relatively strong, so you no longer need to override it for security reasons (in CHICKEN 4 this used to be necessary). ===== Utility procedures <procedure>(crypt-prefix->type prefix)</procedure> Given a {{prefix}} string (which may also be a complete salted hash string), determine what algorithm type it specifies. Note that because the historical UNIX crypt() had no prefix at all, {{'des}} will be returned for arbitrary strings that don't start with a dollar, even if they're not actually proper DES strings! Example: <enscript highlight="scheme"> (crypt-prefix->type "$1$") => 'md5 (crypt-prefix->type "whatever") => 'des (crypt-prefix->type "$nonexistant$") => ERROR: Unknown crypt prefix type </enscript> <procedure>(crypt-maximum-random-u8vector min max)</procedure> The initial value of {{crypt-default-random-u8vector}}. This procedure simply calls Chicken's built-in [[/man/5/Module (chicken random)#pseudo-random-integer|pseudo-random-integer]] to get enough values between 0 and 255 to fill the u8vector. It will use the maximum length if available, otherwise the minimum length (this may change later). ==== Algorithm-specific procedures You should only use these when you have specific needs for a particular type of algorithm. The defaults are supposed to be good enough for general use. If you disagree, please let me know so I can change this. ===== Blowfish <procedure>(crypt-blowfish-gensalt random #!key logrounds)</procedure> Generates a salt string for the Blowfish-based crypt() implementation as introduced by Niels Provos and David Mazières in OpenBSD. This is sometimes referred to as {{bcrypt}}. {{logrounds}} is the 2-based logarithm of the number of iterations to run the EksBlowfish algorithm. If not specified or {{#f}} it defaults to the value of {{crypt-blowfish-default-logrounds}}. {{random}} is a procedure that returns a randomly filled u8vector. See the documentation on {{crypt-default-random-u8vector}} and {{crypt-gensalt}} for more information. <parameter>(crypt-blowfish-default-logrounds logrounds)</parameter> The default value for {{crypt-blowfish-gensalt}}'s {{logrounds}} argument. This is the 2-based logarithm of the number of rounds, so the number 10 indicates 1024 iterations of the blowfish encryption algorithm should be run. Currently it is set to 12 by default, but this value should grow as computing power grows. ===== SHA-2 <procedure>(crypt-sha512-gensalt random #!key rounds)</procedure> Generates a salt string for the SHA-512 variant of the SHA-2-based crypt() implementation as introduced into GNU libc by Ulrich Drepper of Red Hat. {{rounds}} is the number of iterations to run the SHA-2 algorithm. If not specified or {{#f}} it defaults to the value of {{crypt-sha512-default-rounds}}. {{random}} is a procedure that returns a randomly filled u8vector. See the documentation on {{crypt-default-random-u8vector}} and {{crypt-gensalt}} for more information. <parameter>(crypt-sha512-default-rounds [rounds])</parameter> The default value for {{crypt-sha512-gensalt}}'s {{rounds}} argument. Currently defaults to 5000, but should be tweaked to compensate for increasing computing power. <procedure>(crypt-sha256-gensalt random #!key rounds)</procedure> Generates a salt string for the SHA-256 variant of the SHA-2-based crypt() implementation as introduced into GNU libc by Ulrich Drepper of Red Hat. {{rounds}} is the number of iterations to run the SHA-2 algorithm. If not specified or {{#f}} it defaults to the value of {{crypt-sha256-default-rounds}}. {{random}} is a procedure that returns a randomly filled u8vector. See the documentation on {{crypt-default-random-u8vector}} and {{crypt-gensalt}} for more information. <parameter>(crypt-sha256-default-rounds [rounds])</parameter> The default value for {{crypt-sha256-gensalt}}'s {{rounds}} argument. Currently defaults to 5000, but should be tweaked to compensate for increasing computing power. ===== MD5 <procedure>(crypt-md5-gensalt random)</procedure> Generates a salt string for the MD5-based crypt() implementation as introduced by Paul Hennig-Kamp in FreeBSD. {{random}} is a procedure that returns a randomly filled u8vector. See the documentation on {{crypt-default-random-u8vector}} and {{crypt-gensalt}} for more information. ===== DES ====== Extended BSDi DES <procedure>(crypt-des-extended-gensalt random #!key rounds)</procedure> Generates a salt string for the extended DES-based crypt() implementation as introduced by BSDi. {{rounds}} is the number of iterations to run the DES algorithm. If not specified or {{#f}} it defaults to the value of {{crypt-des-extended-default-rounds}}. '''Important note''': DES has specific weaknesses that makes it easier to detect weak keys when it is run for an even number of rounds, so it's important to specify an odd number here. {{random}} is a procedure that returns a randomly filled u8vector. See the documentation on {{crypt-default-random-u8vector}} and {{crypt-gensalt}} for more information. <parameter>(crypt-des-extended-default-rounds [rounds])</parameter> The default value for {{crypt-des-extended-gensalt}}'s {{rounds}} argument. Currently defaults to 725. ====== Original UNIX DES <procedure>(crypt-des-gensalt random)</procedure> Generates a salt string for the original UNIX DES-based crypt() implementation. {{random}} is a procedure that returns a randomly filled u8vector. See the documentation on {{crypt-default-random-u8vector}} and {{crypt-gensalt}} for more information. === Repository This egg is hosted on the CHICKEN Subversion repository: [[https://anonymous@code.call-cc.org/svn/chicken-eggs/release/5/crypt|https://anonymous@code.call-cc.org/svn/chicken-eggs/release/5/crypt]] If you want to check out the source code repository of this egg and you are not familiar with Subversion, see [[/egg-svn-checkout|this page]]. === License All code in this egg is explicitly placed in the public domain. You may do whatever you want with it. This egg contains code written by the following people: * Peter Bex (Chicken glue code, MD5 and DES crypt implementation) * Colin Plumb (MD5 code) * [[http://www.akkadia.org/drepper/sha-crypt.html|Ulrich Drepper]] (SHA-2 implementation) * "[[http://www.openwall.org/crypt|Solar Designer]]" (Blowfish implementation, salt generation code) * [[http://ka9q.net/code/des/|Phil Karn]] (DES code) Keeping these credits in the source code is not required, but it would be appreciated. === Changelog * 1.0.1 Fix build script to include shebang line (thanks to Chris Brannon) * 1.0 Port to CHICKEN 5 * 0.4.3 Fix compilation for Android: {{crypt()}} is part of libc, just like in OpenBSD (thanks to Kristian Lein-Mathisen) * 0.4.2 Fix compilation on OpenBSD: {{crypt()}} is part of libc there (reported by "pcoutin" on IRC) * 0.4.1 Small bugfix for libcs whose {{crypt()}} return {{NULL}} upon receiving an invalid "setting" string (thanks to Matt Gushee for reporting this bug) * 0.4 Update bcrypt fallback implementation to [[http://www.openwall.org/crypt|OpenWall bcrypt]] 1.2, fixing [[http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-2483|CVE-2011-2483]] (hashing passwords containing UTF or other characters with the high bit set produced bogus values). Fix compilation on Linux. * 0.3 Allow for manually overriding the native crypt types (suggested by [[/users/mario-domenech-goulart|Mario Domenech Goulart]]) * 0.2 Minor changes in previously undocumented API. Use an odd default number of rounds for extended DES algorithm. * 0.1 Initial release === References * Shiro Kawai, "[[http://blog.practical-scheme.net/gauche/20100427-crypt-bcrypt|Blowfish password hashing]]" * Thomas Ptacek, "[[http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes.html|Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes]]" * Coda Hale, "[[http://codahale.com/how-to-safely-store-a-password/|How to safely store a password]]" * Niels Provos and David Mazières, "[[http://www.usenix.org/events/usenix99/provos.html|A Future-Adaptable Password Scheme]]" * Philip Leong and Chris Tham, "Unix Password Encryption Considered Insecure", proceedings of the 1991 USENIX Winter conference. (there used to be a link to the paper here, but it's dead by now. Let me know if you find a copy) * J. Orlin Grabbe, "[[http://page.math.tu-berlin.de/~kant/teaching/hess/krypto-ws2006/des.htm|The DES Algorithm Illustrated]]" (mirror, original site is down) * Assurance Technologies, "[[http://packages.python.org/passlib/lib/passlib.hash.html|passlib.hash - Password Hashing Schemes]]" (this is a good overview of existing UNIX and other hash systems complete with explanations for each) * Jeff Jarmoc, "[[http://chargen.matasano.com/chargen/2015/3/26/enough-with-the-salts-updates-on-secure-password-schemes.html|Enough With the Salts: Updates on Secure Password Schemes]]" * Poul Henning-Kamp, "[[http://phk.freebsd.dk/sagas/md5crypt/|The history of md5crypt]]".
Description of your changes:
I would like to authenticate
Authentication
Username:
Password:
Spam control
What do you get when you subtract 15 from 6?