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

oh, hello,

i want to save a password in a Berkley DB for a script that allows multiple accounts to it, the problem is anyone can check out the .db file and see the password lickiddy split. is there a better way to save the password, or maybe a good routine to encrpyte the password before saving it into the db and then being able to decrypte it back? i know perl has a crypt() function but its a bit over me on how it works. can anyone help?

Replies are listed 'Best First'.
Re: P@$$w0rd$ in perl?
by ZZamboni (Curate) on Apr 24, 2000 at 22:51 UTC
    crypt accesses the standard Unix crypt() function, which takes a string and a salt (a random two-byte string) and using a one-way hash function encrypts the password. The salt gets assigned randomly when the password is created, and its purpose is that even if you use the same password on two different places, the encrypted passwords will be different. There are some packages in CPAN that provide similar interfaces using MD5 and other algorithms. Do a search for "crypt".

    Sample use for crypt would be as follows. The first function receives the plain-text password and returns the encrypted password string. The second one takes an encrypted password string (as generated by the first function) and a plain-text password, and tell you whether the password is correct. Notice how the salt is stored in the first two bytes of the encrypted password. Also note that crypt only uses the first 8 characters of the password.

    sub encrypt_passwd { my $pw=shift; # Seed random number generator. From Camel book p. 223. # This should be outside this function, in the program # initialization, otherwise calls to this function very # close in time will result in the same salt. srand ( time() ^ ($$ + ($$ << 15)) ); my @c=('a'..'z', 'A'..'Z', '0'..'9','.','/'); my $s=$c[rand(@c)].$c[rand(@c)]; return crypt($pw, $s); } sub verify_passwd { my ($epw, $pw)=@_; my $s=substr($epw,0,2); return $epw eq crypt($pw,$s); }
Re: P@$$w0rd$ in perl?
by btrott (Parson) on Apr 24, 2000 at 21:48 UTC
    crypt does the same thing as the crypt C function. It provides one-way encryption, meaning that you can't actually decrypt the encrypted string. So, for example, say that you stored a password; then you want to test whether a password provided by a user matches that password that you've stored. In order to test that, you need to crypt the user-provided password and compare it against the already-encrypted password.

    Make sense?

    There are also a bunch of Crypt modules on CPAN that you may want to take a look at.

Re: P@$$w0rd$ in perl?
by comatose (Monk) on Apr 24, 2000 at 22:12 UTC

    Generally, for passwords, you only need one-way encryption. Someone sets their password, encrypt it, store it. Someone enters their password to login, encrypt it, compare it to what's in the database, go on if they're identical. crypt() works good as well as anything that does MD5. The idea being that if someone is trying to guess passwords and gets the encrypted passwords and/or your algorithm, they still have a lot of work to do.

Re: P@$$w0rd$ in perl?
by buzzcutbuddha (Chaplain) on Apr 24, 2000 at 22:06 UTC

    Try serializing the data as discussed in this tutorial.
    That will encode the data, and then store it in a file that you can then Thaw, etc. Then, as far as I know, someone would not be able to
    just glance at the password.

      But anyone would be able to write a simple perl script that reads the serialized data and prints the password. No. The purpose is to encrypt the password by encrypting it.

        You are correct. I was not commenting on the encryption technique
        but speaking towards saving the password in something a little more
        obscure and difficult than a DB. By all means encrypt the date, but
        don't give anyone with a Brute Force program an inch towards getting your
        password.

        Sorry, should have made that clearer.

Thanks!
by skazat (Chaplain) on Apr 25, 2000 at 01:45 UTC
    hey thanks a bunch, all of you, that really cleared up the usage of crypt, and does everything i want exept the functionality of being able to email the user their password if they forget. (why like this here website)

    i'd rather have someone loose their password then having someone else crack their acount ;) does anyone have a scheme to encrypt the password (securely enough) and if forgotten can be accessed by the right people?

    that would be super,

    -justin simoni
    !skazat!

      Actually, the Everything Engine (last time I checked) doesn't encrypt passwords at all.

      Assuming you keep your database properly secured, that shouldn't be a problem. Otherwise, you'll need a two-way encryption scheme, maybe a rotation cipher?

      my $password = "foobar+"; my $salt = 11; my $newpass = ""; sub encrypt { my $password = shift; my @letters = split '', $password; foreach my $letter (@letters) { my $value = ord($letter) + $salt; while ($value > 255) { $value -= 255; } $newpass .= chr($value); } } sub decrypt { my $password = shift; my @letters = split '', $password; foreach my $letter (@letters) { my $value = ord($letter) - $salt; while ($value < 0) { $value += 255; } $newpass .= chr($value); } }
      Not very secure, but better than plain text, if you keep your salt hidden. Keep your database more secure.

      What I've always done is put in functionality for the user to receive a new random password via email. If they forget it, they just put in their email address and their login and password are sent. Sites implement this in any number of ways.

      Enter email address only - Just sends out a new password to the email address.

      Enter email address and answer question - When you create an account, you include a question and answer portion. For example, "What is your favorite color?" "Red." In order for the new password to be set, the user has to successfully answer the question. Most allow the user to pick their own question.

        that seems to be the best idea, just email a new password to the email address, thanks alot!
      Being able to recover a user's password would mean that there would need to be a "secret key" for the "right people" to be able to decrypt it. This opens yet another possible security hole. The preferred way of doing things is simply giving the "right people" the power to change any user's password. That way, if a user loses his/her password, they can have it reset to something known.

      Most password-protected web pages out there evidently store the passwords in clear text, since they are able to mail it to you if you lose it. Although convenient, this is not necessarily secure. I think the best thing would be what comatose suggested, have the system generate a new random password and send it to the user. That way you don't have to store clear-text passwords.

        Heh. Unless you do on-the-fly brute forcing of the crypt'd password when a user requests to be email'd it. That would just about be feasible for crypt'd passwords.

        (Mostly a joke).