Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

What's the idea of different salts in crypt()?

by jeorgen (Pilgrim)
on Sep 20, 2001 at 03:04 UTC ( [id://113490]=perlquestion: print w/replies, xml ) Need Help??

jeorgen has asked for the wisdom of the Perl Monks concerning the following question:

The crypt function wants a salt, and the returning value is the "crypted" string with the salt tucked on at the front.

So, it shouldn't be rocket science for an intruder to figure out what the salt is. So my question is:
Is there any meaning in using different salts? Am I missing something?

Thanks

/jeorgen

  • Comment on What's the idea of different salts in crypt()?

Replies are listed 'Best First'.
Re: What's the idea of different salts in crypt()?
by dga (Hermit) on Sep 20, 2001 at 03:18 UTC

    You should not let intruders have the encrypted password text.

    That being said, given the speed of machines today if they have access to the full encrypted text version of your passwords its time to get new passwords and really soon.

    The salt makes the password string asdfghjl with salt Az look radically different from asdfghjl with salt Ay. This means that it is unlikely that 2 peoples encrypted passwords will look the same even if they have the exact same plaintext due to the randomly selected salts.

    It also means that a complete password reverse lookup table is 4096 times bigger than one with with no salt.

    You should look into the Digest::MD5 and friends which will allow passwords longer than 56 bits. Also you should keep the encoded passwords in a seperate, highly secured, file in any case.

Re: What's the idea of different salts in crypt()?
by wog (Curate) on Sep 20, 2001 at 03:12 UTC
    The reason that salts are used is to make it harder to break a crypted password file. Instead of being able to go through a dictionary or similar and compare the crypted value of every word to every password, they can only work on passwords with one salt. This makes the task of looking for an easily guessed ("insecure") password within a password file much slower.
Re: What's the idea of different salts in crypt()?
by converter (Priest) on Sep 20, 2001 at 07:24 UTC
    perlfunc recommends a random salt:
    crypt PLAINTEXT,SALT ... When choosing a new salt create a random two character string whose characters come from the set "[./0-9A-Za-z]" (like "join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64] +"). ...

    The random salt makes the cracker's job a lot more difficult.

    conv

Re: What's the idea of different salts in crypt()?
by cacharbe (Curate) on Sep 20, 2001 at 16:36 UTC
    This is directly from The Handbook of Applied Cryptography
    Alfred J. Menezes, Paul C. van Oorschot and Scott A. Vanstone
    CRC Press
    ISBN: 0-8493-8523-7

    Chapter 10, page 390
    (v) Salting passwords
    To make dictionary attacks less effective, each password, upon initial entry, may be aug-mented with a t-bit random string called a salt (it alters the “flavor” of the password; cf. x10.2.3) before applying the one-way function. Both the hashed password and the salt are recorded in the password file. When the user subsequently enters a password, the system looks up the salt, and applies the one-way function to the entered password, as altered or augmented by the salt. The difficulty of exhaustive search on any particular user’s pass-word is unchanged by salting (since the salt is given in cleartext in the password file); how-ever, salting increases the complexity of a dictionary attack against a large set of passwords simultaneously, by requiring the dictionary to contain 2 t variations of each trial password, implying a larger memory requirement for storing an encrypted dictionary, and correspondingly more time for its preparation. Note that with salting, two users who choose the same password have different entries in the system password file. In some systems, it may be appropriate to use an entity’s userid itself as salt.

    Although the entire book is available in PDF at the link I provided above, I highly suggest that anyone interested in crypto add it to their paper library, right next to Bruce Schneier's book.

    C-.

        Although a little pedantic at times, I feel that it should be the Number One Read (tm) for any and all CIOs and CSOs. I see people everyday who are quelled into thinking that security can be had with a product, and they are duped into leaving the humans, and the process alone.

        Security is a process, not a product, and I think Bruce hits the nail on the head (a bunch of times). I didn't mention Secrets and Lies in my post because it deals with the whole process, and I wanted text book product investigation.

        Yes, read "Secrets and Lies". Even if you aren't interested in how encryption works on a mathematical level, how to properly implement the process should be foremost on everyone's minds.

        C-.

(crazyinsomniac) Re: What's the idea of different salts in crypt()?
by crazyinsomniac (Prior) on Sep 20, 2001 at 09:22 UTC
    If you're going to be using this for some kind of app, I would lop the salt off (if i didn't use "better" encryption), and have it be formulaic (a combo of the userid, create time and id or linenumber in whatever database type thing you're keeping the list), so that you can "correctly" recreate it for authentication.

    If whoever doesn't know the salt, it'll take them twice as long to bruteforce the pass, and chances are, they'll never get it (the salt is half the encryption).

     
    ___crazyinsomniac_______________________________________
    Disclaimer: Don't blame. It came from inside the void

    perl -e "$q=$_;map({chr unpack qq;H*;,$_}split(q;;,q*H*));print;$q/$q;"

Re: What's the idea of different salts in crypt()?
by oneiros (Scribe) on Sep 20, 2001 at 10:36 UTC

    Right. Knowing the salt is half the battle in cracking the password.

    In addition to the suggestions of our fellow monks, I can add two more points.

    Use a random salt and store the password in such a way where it will be extremely difficult for someone to obtain. Such as a configuration file only readable by the application itself. Some example code follows:

    use strict; my $pass; $| = 1; print "password: "; chomp($pass = <STDIN>); print crypt_pass($pass), "\n"; exit; sub crypt_pass { my $p = shift; return unless $p; my $salt = chr(65+rand(27)).chr(65+rand(27)); return crypt($p, $salt); }

    Another thing you can do is use the first two characters of the password as the salt, then strip those two characters off before you store it.

    use strict; my $pass; $| = 1; print "password: "; chomp($pass = <STDIN>); print crypt_pass($pass), "\n"; exit; sub crypt_pass { my $p = shift; return unless $p; crypt($p, $p) =~ /..(.*)/; my $cpass = $1; return $cpass; }
      oneiros,

      I agree with you about the need for random salt but not about "knowing it is half the battle." You always know the salt - it's right there out in the semi-open. It's always going to be the first two characters of the stored "hashed" value (I hate to call it an encrypted value because the value is normally the output of a crypto hash algrorithm).

      Consider the code for checking passwords:

      $pwd = (getpwuid($<))[1]; system "stty -echo"; print "Password: "; chomp($word = <STDIN>); print "\n"; system "stty echo"; if (crypt($word, $pwd) ne $pwd) { die "Sorry...\n"; } else { print "ok\n"; }
      The whole purpose of the salt is to slow down an attacker from comparing a list of pre-generated hashes against the target hash. Instead of needing to pre-compute one "hashed" value for each plaintext password, an attacker needs to precompute 16384 "hashed" values for each plaintext password (2^7 * 2^7). That kinda pales today but was pretty big when the crypt function was first developed - the computational power to pre-compute that many passwords times the number of plaintext password you suspect (dictionary) was pretty high. Not so much today which is why we have things like shadow passwords, other core password functions besides crypt and every sysad wanting you to pick a password that would not show up in a dictionary.

      -derby

      I've seen people use the password as the salt before, but I have some hesitations about it. This seems to defeat the two arguments I've heard for salts.

      • Same plaintext yields different ciphertext.
        Obviously if the salt is determined by the plaintext, this idea flys out the window.
      • Greatly expands the ciphertext dictionary needed to check for common passwords.
        If the cracker figures out that your salts are based on the plaintext, the dictionary needed is exactly the same size as if there were no salts used at all.
      Of course, I've never quite gotten the concept of salts anyway.... They seem like a poorly thought out concept left over from the 70s. Use one of the modules mentioned above instead.

      -Blake

        It think you're confusing when to apply the advice to use the whole password. You don't use the plaintext password to create a salt when encrypting the password. You give the crypt function the whole encrypted password, salt and hashed password together as appears in the file, as the salt when authenticating a freshly entered plaintext password. This allows the crypt function to pull out as many bytes for the salt as the native crypt uses, whether that be the two for DES or some longer value. The rest is generally simply discarded by the crypt function. This way, you can write password authentication code which will work so long as the algortihm being used for authentication is the same as the one used for password creation and the two use the same interface. There's no need this way for the application to know beforehand how many bytes need to be given for the salt.

        That being said, let me repeat that when generating the salt, the plaintext password should play absolutely no role.

        Chris
        911
Re: What's the idea of different salts in crypt()?
by Nitsuj (Hermit) on Sep 20, 2001 at 16:08 UTC
    The shadowing used on passwords can only be worked one way. You never work the encrypted password to retrieve the plaintext password, you always work the plaintext password to retrieve the shadow.

    That said, you don't need "THE" password, just "A" password that yields the same value when shadowed (of course, for our purposes, we'll assume that these are the same).

    Of course, this is far from impossible, and of course, knowing the salt gets you PART of the way there, as was already commented, but you gotta have the salt expressed somewhere so the shadow can be worked again in order to get the encrypted text to test the password against. An afternoon running John the Ripper will show you JUST how secure older algorithms are against NEWER processors, of course, the goal of encryption is generally not to permanently obscure data, just to make it hard enough that it's obscured for long enough.

    Of course, you can always just use a different algorithm.

    Just Another Perl Backpacker
Re: What's the idea of different salts in crypt()?
by tadman (Prior) on Sep 20, 2001 at 20:33 UTC
    The "salt" is there to "spice up" the encrypted password, under DES effectively making it 4096 times more difficult to store all possible encrypted versions of a password. Up until recently, this made it impractical to store a decent dictionary encoded 4096 times over, requiring at least an 8GB drive. Now, though, with 160GB drives on the market, you can see how trivial it is to crack passwords.

    The "salt" is also important to validate passwords. Without knowledge of the salt, you would have to crack it and this would slow down password validation in a huge way. Now, to check that your guess is correct, you just do:
    if (crypt($guess,$real) eq $real) { # ... }
    Since the crypt function only uses the "salt" part of the second parameter, ignoring the rest, and since your guess encrypted with the same "salt" should be the same as the real encrypted version, your guess will only be correct if it encrypts the same.

    Something I would like to point out is that the DES encryption used by default is very, very flimsy. You should use RSA instead, and this is, to the best of my knowledge, very well supported, though I'm sure someone else can provide specifics on a platform by platform basis. RSA uses a much more robust method of encryption, and the salt is much larger. I haven't heard of an RSA password cracking program that works as well as the old DES cracking ones which are now frighteningly efficient.

    Here's a comparison:
    CypherPasswordSaltCrypted
    DESforknobFkFkM26CvyESMcI
    RSAforknob$1$FkH.DxzR$$1$FkH.DxzR$RA4AHFtog6v3RTO8Fa60c0
    Generating eight letters of salt instead of two is really simple. As long as they are formatted correctly, and you don't accidentally interpolate the $'s, that is.
Re: What's the idea of different salts in crypt()?
by jeorgen (Pilgrim) on Sep 21, 2001 at 03:12 UTC
    Thanks all for the replies!

    I summarize:

    1) Salt is there to make a dictionary attack harder by a couple of magnitudes. Modern computing power however now makes a dictionary attack feasible.

    2) Crypt is weak, use something stronger, as e.g. MD5. I would like to point out that I knew that, I just happened to be programming an awkward web server where I during the user register process had to make do with MySQLs internal hashing functions, of which only crypt worked in the version at hand (It is not a high security application.).

    3.) Perlmonks is getting to be a real big community. I haven't been around much in the last 6 months; the reputation points to my posting is 300-400% higher than I expected!

    Thanks all,

    /jeorgen

Re: What's the idea of different salts in crypt()?
by mr_mischief (Monsignor) on Jul 22, 2003 at 22:05 UTC
    Let me say, re-reading this thread after ever so long, that you can both use MD5 and use Perl's crypt() on GNU/Linux and certain other systems without the use of outside modules.

    If you hand crypt() on GNU/Linux a bare salt, it's used for DES (or triple DES actually I think in Linux's case). If you hand crypt() a salt of the format $1$salt$ then it does MD5, with up to 8 characters of salt and up to 22 bytes of (encrypted) password.

    With Perl's crypt being implemented on Linux as a wrapper around the library call, it behaves the same.

    This is at least valid on GNU/Linux. The man page for crypt(3) on a GNU/Linux box I was just on says it's a GNU extension as of glibc2. So I'd imagine that any system using glibc2 (and on which perl is linked against the crypt library, which is a specific requirement according to the man page) should be able to do the same.

    Look at crypt(3) with your friendly neighborhood man program or its equivalent on your target system(s) to find out for sure.

    Christopher E. Stith

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://113490]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (5)
As of 2024-04-19 13:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found