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

Dear Monks,

I need help with the syntax for salting a password using CGI::Application::Plugin::Authentication and Digest::MD5.

1. the password is entered by the user
2. the salt found in TableB is added
3. the salt and the password are MD5 encrypted
4. the results are then to be compared to the salted password already in TableA
(The salt is in TableB and the md5 salted password is in TableA -- joined on column2.)

I believe that I need to use a custom filter. I've read and re-read the CPAN examples but I still can't "get it". Any help or links to other examples would be appreciated.

TABLES => ['column1 TableA, 'column1 TableB'], JOIN_ON => 'TableA.column2 = TableB.column2', CONSTRAINTS => { 'TableA.username' => '__CREDENTIAL_1__', 'md5_base64:salt:password' => '__CREDENTIAL_2__', 'TableB.column3' => __CREDENTIAL_3__', } FILTERS => { salt => \&salt_filter }, ], sub salt_filter { my $param = shift; my $value = shift; $value = $dbh->prepare ("SELECT salt FROM TableB JOIN TableA ON TableB.column2 = TableA.column2 "); return $value; }

Replies are listed 'Best First'.
Re: How to use salt with CGI::Application::Plugin::Authentication
by scorpio17 (Canon) on May 10, 2011 at 15:13 UTC

    I've never seen anyone store salts in a separate table - that's pretty weird. The salt is normally appended to the password, and the two stored together in the same table column.

    So, what you would normally see looks more like this:

    __PACKAGE__->authen->config( DRIVER => [ 'DBI', DBH => $dbh, # provide your own DBI handle TABLE => 'user', CONSTRAINTS => { 'user.name' => '__CREDENTIAL_1__' } COLUMNS => { 'crypt:password' => '__CREDENTIAL_2__' }, ], );

    Note that there's only one table, so there's no need for a join, but since the password is encoded, you need a 'COLUMNS' field.

    But what you really want is MD5 encryption. To do that, you need to write a custom filter using Crypt::PasswdMD5, call it cryptmd5, then use it like this:

    __PACKAGE__->authen->config( DRIVER => [ 'DBI', DBH => $dbh, # provide your own DBI handle TABLE => 'user', CONSTRAINTS => { 'user.name' => '__CREDENTIAL_1__' } COLUMNS => { 'cryptmd5:password' => '__CREDENTIAL_2__' }, FILTERS => { cryptmd5 => \&cryptmd5_filter }, ], );

    Implement cryptmd5_filter just like crypt_filter (see the CGI::Application::Plugin::Authentication::Driver::Filter::crypt source), only replace crypt() with unix_md5_crypt(). I think that will do what you want.

      I want to use a different salt for each account. The salt *is* eventually appended to the password but stored separately. Storing them in a different table instead of a different column was just an added (perhaps unnecessary) security step.

      Thanks for your suggestion. I have been trying it out. The 'Columns' has been added but as of yet, I haven't been able to get the sub cryptmd5_filter working.
Re: How to use salt with CGI::Application::Plugin::Authentication
by locked_user sundialsvc4 (Abbot) on May 10, 2011 at 12:28 UTC

    I believe that the purpose of “salt” is that it is a purely random number, passed around along with the salted key and unencrypted.   It isn’t stored in any database table anywhere.

    “Eve” is left with the salted password and the salt-value, and no way to determine the (secret) actual session-key to which the web application (alone) is able to convert them.   In fact it is possible for the salt value to be constantly changing throughout the session.

Re: How to use salt with CGI::Application::Plugin::Authentication
by locked_user sundialsvc4 (Abbot) on May 10, 2011 at 15:40 UTC

    Here’s my understanding of the purpose of “salting.”   The secret consists of three things:

    1. A fixed but unpredictable (and unknown) string which is a secret that can only be obtained by hacking into the source code of the system.
    2. A randomly generated string which is “the actual session key.”
    3. A third piece of pure-entropy, the “salt,” which is provided openly, and which may as well be without any concealment at all.

    If the token that you have in your hands was formed only from the first two things, then there would be a one-to-one correspondence (details unknown to you, perhaps, but nonetheless one-to-one) between that token and the secret which it conceals.   If you could accumulate a few hundred million messages (not an unreasonable proposition), you might be able to divine the secret.   But if the secrets are “salted” using a number that also has a few hundred million possibilities, you might never wind up with the exact same token value twice, even though every one of them conceals the same secret.   You have just tossed a huge amount of entropy into what would otherwise be a deterministic (although convoluted...) calculation.

    But you do have to use the idea of salt in the right way.   If the salt value is stored, all you’ve really done is to make the effective-password 32 bits longer.   You haven’t actually “salted” anything.

      Different passwords can result in the same MD5 hash. The purpose of the salt is to prevent users from abusing this (i.e. logging in with a different password that happens to hash to the same value). Which means the user should not know what the salt is since that makes the salt pointless. Your notion about what the salt is above (#3) is wrong. Agree with scorpio17 that normally the salt and the encrypted password are stored together. Would be interested in knowing the reason why they are separated.

      Elda Taluta; Sarks Sark; Ark Arks

        Please see my response to Scorpio17.

        The separate salt is mostly for Admin use. It will make sure that there is not any repeated use of same salt string.
      I was hoping to have a salt made of a *specified number* for each account. The security would be in the placement, amount/type of encryption, etc.

      If the salt is random and changing, how can the hash be verified?