Thread: Encoding passwords

Encoding passwords

From
"Mike Arace"
Date:
Hey everyone,

Is there a function out there for pg which allows you to generate a random
number given a seed value?  I'm trying to create a users table which would
require the storage of a password in a database field, and I'm hesitant to
put it in there in plain text, despite the fact I plan to put very tight
restrictions on that particular table.  Ideally, I would encode each letter
one by one, using the random number generator with the previous letter as a
seed for the next.  I was told that certain unixes use a similar way to
store their passwords, and it seemed to make sense for this application.  I
noticed that there is a rand() function, but I'm a little slow today and
couldn't think a way to use that in this scenario.  Any suggestions would be
greatly appreciated.

Thanks
Mike

_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp


Re: Encoding passwords

From
Bruno Wolff III
Date:
On Tue, Sep 25, 2001 at 08:42:04AM -0400,
  Mike Arace <mikearace@hotmail.com> wrote:
>
> Is there a function out there for pg which allows you to generate a random
> number given a seed value?  I'm trying to create a users table which would
> require the storage of a password in a database field, and I'm hesitant to
> put it in there in plain text, despite the fact I plan to put very tight
> restrictions on that particular table.  Ideally, I would encode each letter
> one by one, using the random number generator with the previous letter as a
> seed for the next.  I was told that certain unixes use a similar way to
> store their passwords, and it seemed to make sense for this application.  I
> noticed that there is a rand() function, but I'm a little slow today and
> couldn't think a way to use that in this scenario.  Any suggestions would be
> greatly appreciated.

The more normal way to do this is to store a cryptographic hash of the
password in the database and have the application calculate the hash
and compare that to the hash in the database. This approach won't work
if the database is used to store passwords for use by applications in
connecting to other services.

Typical cryptographic hash functions are SHA-1 and MD5 and you shouldn't
have much trouble finding libraries that provide these functions.

Re: Encoding passwords

From
Marko Kreen
Date:
On Tue, Sep 25, 2001 at 08:42:04AM -0400, Mike Arace wrote:
>
> Is there a function out there for pg which allows you to generate a random
> number given a seed value?  I'm trying to create a users table which would
> require the storage of a password in a database field, and I'm hesitant to
> put it in there in plain text, despite the fact I plan to put very tight
> restrictions on that particular table.  Ideally, I would encode each letter
> one by one, using the random number generator with the previous letter as a
> seed for the next.  I was told that certain unixes use a similar way to
> store their passwords, and it seemed to make sense for this application.  I
> noticed that there is a rand() function, but I'm a little slow today and
> couldn't think a way to use that in this scenario.  Any suggestions would be
>
> greatly appreciated.

Look into contrib/pgcrypto in CVS, or

http://www.l-t.ee/marko/pgsql/pgcrypto-0.3.tar.gz

in meantime.  Gives you crypt() function not unlike in UNIXes.
Also gen_salt() for generating salts for it.

--
marko


Re: Encoding passwords

From
"Nick Fankhauser"
Date:
> Is there a function out there for pg which allows you to generate
> a random
> number given a seed value?  I'm trying to create a users table
> which would

There is the following:

"select setseed(<new seed value>);"

This sets the seed for the random() function.

However, the approach we use is more like the suggestion from Bruno Wolf
that you received earlier- In our case we use JDBC to pass data between our
application & the database, so we use the java crypt package to encrypt
everything we get before it gets stored or compared to a stored value & then
just compare the hash. I think his suggestion is the best way *if* your
development environment supports something similar.

-Nick

---------------------------------------------------------------------
Nick Fankhauser

Business:
nickf@doxpop.com  Phone 1.765.965.7363  Fax 1.765.962.9788
doxpop  - Court records at your fingertips - http://www.doxpop.com/

Personal:
nick@fankhausers.com   http://www.fankhausers.com


Re: Encoding passwords

From
Lincoln Yeoh
Date:
I personally use encoded password= hash( concat(salt,password)), and store
both the salt and the encoded password. Where hash = sha1 or md5.

The DB columns are: salt, encoded password, encoding method.

Note that apparently there are some cryptographic weaknesses with
concatenating the salt and the password with the salt in the front, the way
I did it unfortunately :). If I recall correctly, if the salt is short then
attackers only need to attack a subset of the full hash. The salt being a
known plaintext. So some say to concat with the salt at the back. I suspect
a long salt should make the attack far less feasible, or alternatively
XORed the salt with the password or maybe hash multiple times.
Unfortunately I can't seem to find the original article.

I haven't got around to changing my apps. It's not too bad since the fields
allow for different encoding methods - for this reason I suggest you have a
field to store the encoding method too.

So you can have 'NONE' or 'SHA1' or 'MD5' or 'SHA1B' and so on.

That said if hostile people get to the stage where they can read the
encoded passwords, you're probably screwed anyway - they're likely to be
able to do other things some even more undesirable. So it's not really a
big deal compared to other issues.

Cheerio,
Link.

At 08:42 AM 9/25/01 -0400, Mike Arace wrote:
>
>Hey everyone,
>
>Is there a function out there for pg which allows you to generate a random
>number given a seed value?  I'm trying to create a users table which would
>require the storage of a password in a database field, and I'm hesitant to
>put it in there in plain text, despite the fact I plan to put very tight
>restrictions on that particular table.  Ideally, I would encode each letter
>one by one, using the random number generator with the previous letter


Re: Encoding passwords

From
Bruce Momjian
Date:
> I personally use encoded password= hash( concat(salt,password)), and store
> both the salt and the encoded password. Where hash = sha1 or md5.
>
> The DB columns are: salt, encoded password, encoding method.
>
> Note that apparently there are some cryptographic weaknesses with
> concatenating the salt and the password with the salt in the front, the way
> I did it unfortunately :). If I recall correctly, if the salt is short then
> attackers only need to attack a subset of the full hash. The salt being a
> known plaintext. So some say to concat with the salt at the back. I suspect
> a long salt should make the attack far less feasible, or alternatively
> XORed the salt with the password or maybe hash multiple times.
> Unfortunately I can't seem to find the original article.
>
> I haven't got around to changing my apps. It's not too bad since the fields
> allow for different encoding methods - for this reason I suggest you have a
> field to store the encoding method too.
>
> So you can have 'NONE' or 'SHA1' or 'MD5' or 'SHA1B' and so on.
>
> That said if hostile people get to the stage where they can read the
> encoded passwords, you're probably screwed anyway - they're likely to be
> able to do other things some even more undesirable. So it's not really a
> big deal compared to other issues.
>

We have new code in 7.2 that will do MD5 encryption of passwords stored
in pg_shadow.  We add the salt to the front of the password before
passing through MD5.  You are suggesting putting the salt at the end.

I guess the issue is that if you can get the salt part found out, you
can use that to attack the password part.  Also, consider that we use
the username as the salt as stored in pg_shadow.  We can easily put the
salt in the back, but then there is the risk that a long password would
not take into account the salt.  My feeling that this is more a
theoretical concern and we may be opening ourselves up to more problems
if we make the change.

Other ideas?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: Encoding passwords

From
Bruce Momjian
Date:
> > That said if hostile people get to the stage where they can read the
> > encoded passwords, you're probably screwed anyway - they're likely to be
> > able to do other things some even more undesirable. So it's not really a
> > big deal compared to other issues.
> >
>
> We have new code in 7.2 that will do MD5 encryption of passwords stored
> in pg_shadow.  We add the salt to the front of the password before
> passing through MD5.  You are suggesting putting the salt at the end.
>
> I guess the issue is that if you can get the salt part found out, you
> can use that to attack the password part.  Also, consider that we use
> the username as the salt as stored in pg_shadow.  We can easily put the
> salt in the back, but then there is the risk that a long password would
> not take into account the salt.  My feeling that this is more a
> theoretical concern and we may be opening ourselves up to more problems
> if we make the change.

OK, I have applied the following patch to the MD5 code that puts the
salt at the end.  We can't change the crypt() stuff because that is
being used in older releases.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
Index: src/backend/libpq/md5.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/libpq/md5.c,v
retrieving revision 1.6
diff -c -r1.6 md5.c
*** src/backend/libpq/md5.c    2001/09/21 20:31:47    1.6
--- src/backend/libpq/md5.c    2001/09/27 22:23:20
***************
*** 19,24 ****
--- 19,32 ----

  #include "libpq/crypt.h"

+ #ifdef FRONTEND
+ #undef palloc
+ #define palloc malloc
+ #undef pfree
+ #define pfree free
+ #endif
+
+
  /*
   *    PRIVATE FUNCTIONS
   */
***************
*** 289,303 ****
  bool EncryptMD5(const char *passwd, const char *salt, size_t salt_len,
                  char *buf)
  {
!     char crypt_buf[128];
!
!     if (salt_len + strlen(passwd) > 127)
!         return false;
!
      strcpy(buf, "md5");
!     memset(crypt_buf, 0, 128);
!     memcpy(crypt_buf, salt, salt_len);
!     memcpy(crypt_buf+salt_len, passwd, strlen(passwd));

!     return md5_hash(crypt_buf, salt_len + strlen(passwd), buf + 3);
  }
--- 297,315 ----
  bool EncryptMD5(const char *passwd, const char *salt, size_t salt_len,
                  char *buf)
  {
!     char *crypt_buf = palloc(strlen(passwd) + salt_len);
!     bool ret;
!
      strcpy(buf, "md5");
!     /*
!      *    Place salt at the end because it may be known by users
!      *    trying to crack the MD5 output.
!      */
!     strcpy(crypt_buf, passwd);
!     memcpy(crypt_buf+strlen(passwd), salt, salt_len);
!
!     ret = md5_hash(crypt_buf, strlen(passwd) + salt_len, buf + 3);
!     pfree(crypt_buf);

!     return ret;
  }

Re: Encoding passwords

From
Bruce Momjian
Date:
> >OK, I have applied the following patch to the MD5 code that puts the
> >salt at the end.  We can't change the crypt() stuff because that is
> >being used in older releases.
>
> I think it needs further confirmation, because what I said was from memory
> - I still can't find the source- so take what I said with a pinch of erm
> MSG. I'd personally go with the XOR rather than concat. And I'd use a
> random salt rather than a predictable salt.
>
> But I emphasize again that I believe this is actually a small issue,  and
> that leaving the salt in front won't really weaken things much looking at
> the big picture. Because nowadays computers are so fast and cheap, cracking
> the passwords usually boils down to whether the password is weak or not,
> and usually the passwords picked are weak, a week at most to crack :). You
> use salts just to _discourage_ attackers from precomputing. A skilled and
> determined attacker who knows how to exploit any hash-salt weakness will
> find it easier to crack the whole blooming computer open and get root.

It was easy to throw the salt on the end, and XOR is easy too.  Can
somone else comment on this?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: Encoding passwords

From
Marko Kreen
Date:
On Thu, Sep 27, 2001 at 02:58:37PM -0400, Bruce Momjian wrote:
> > I personally use encoded password= hash( concat(salt,password)), and store
> > both the salt and the encoded password. Where hash = sha1 or md5.
> >
> > The DB columns are: salt, encoded password, encoding method.

> We have new code in 7.2 that will do MD5 encryption of passwords stored
> in pg_shadow.  We add the salt to the front of the password before
> passing through MD5.  You are suggesting putting the salt at the end.
>
> I guess the issue is that if you can get the salt part found out, you
> can use that to attack the password part.  Also, consider that we use
> the username as the salt as stored in pg_shadow.  We can easily put the
> salt in the back, but then there is the risk that a long password would
> not take into account the salt.  My feeling that this is more a
> theoretical concern and we may be opening ourselves up to more problems
> if we make the change.
>
> Other ideas?

It does not matter.  As you are using only one round of MD5/SHA1
which are quite fast, on very short data, it is very easy to
brute-force it anyway, salt or no salt.  Only good solution for
storing short data hashed is to use very slow algorithm, like
crypt-md5 and crypt-blowfish are doing.  On crypt-blowfish
you can even 'tune' the slowness by giving number of rounds
to run.

Another idea is stop storing hashes altogether and use protocol
like SRP which stores on server side on 'verificators'.  I am
interested hacking PostgreSQL to use SRP, but have not had time
for it yet.

--
marko


Re: Encoding passwords

From
Lincoln Yeoh
Date:
At 07:15 PM 9/27/01 -0400, Bruce Momjian wrote:
>>
>> I guess the issue is that if you can get the salt part found out, you
>> can use that to attack the password part.  Also, consider that we use
>> the username as the salt as stored in pg_shadow.  We can easily put the
>> salt in the back, but then there is the risk that a long password would
>> not take into account the salt.  My feeling that this is more a
>> theoretical concern and we may be opening ourselves up to more problems
>> if we make the change.
>
>OK, I have applied the following patch to the MD5 code that puts the
>salt at the end.  We can't change the crypt() stuff because that is
>being used in older releases.

I think it needs further confirmation, because what I said was from memory
- I still can't find the source- so take what I said with a pinch of erm
MSG. I'd personally go with the XOR rather than concat. And I'd use a
random salt rather than a predictable salt.

But I emphasize again that I believe this is actually a small issue,  and
that leaving the salt in front won't really weaken things much looking at
the big picture. Because nowadays computers are so fast and cheap, cracking
the passwords usually boils down to whether the password is weak or not,
and usually the passwords picked are weak, a week at most to crack :). You
use salts just to _discourage_ attackers from precomputing. A skilled and
determined attacker who knows how to exploit any hash-salt weakness will
find it easier to crack the whole blooming computer open and get root.

Cheerio,
Link.


Re: Encoding passwords

From
Tom Lane
Date:
Lincoln Yeoh <lyeoh@pop.jaring.my> writes:
> I think it needs further confirmation, because what I said was from memory
> - I still can't find the source- so take what I said with a pinch of erm
> MSG. I'd personally go with the XOR rather than concat.

Why?  AFAIK, appending a salt is a well-understood process with MD5.
I see no reason to think that XORing would be better, and it might be
worse.

> And I'd use a random salt rather than a predictable salt.

We do, at least for passwords flowing across the net.  There's no
randomness in the salt for a password stored in pg_shadow, but the only
way to have randomness there would be to add a separate column showing
what the random salt was --- so an attacker with access to pg_shadow
would know what the salt was, anyway.

> But I emphasize again that I believe this is actually a small issue,

Indeed, but I'd rather get it right now than realize we made a small
error after it's too late to change.

            regards, tom lane

Re: Encoding passwords

From
teg@redhat.com (Trond Eivind Glomsrød)
Date:
Marko Kreen <marko@l-t.ee> writes:

> Another idea is stop storing hashes altogether

You can already avoid passwords by using kerberos authentication.

--
Trond Eivind Glomsrød
Red Hat, Inc.

Re: Encoding passwords

From
sean-pgsql-general@chittenden.org
Date:
> > Another idea is stop storing hashes altogether
>
> You can already avoid passwords by using kerberos authentication.

Are there any good docs on kerberos with postgres?  Unlike almost
everything else in this project, I've found them quite lacking.  My
biggest question would be I've got kerberos setup and working well.  How
do I get postgres to authorize a user.

For the sake of example, let's say I've got the principle:
johndoe@REALM.COM.  Do I need to create a principle
johndoe/postgres@REALM.COM?  If so, what is the keytab that I'd create
for the postmaster?  postgres/host.example.com@REALM.COM?

Thanks.  -sc

--
Sean Chittenden

Re: Encoding passwords

From
Tom Lane
Date:
sean-pgsql-general@chittenden.org writes:
> Are there any good docs on kerberos with postgres?

No.  Since you seem to know more about Kerberos than most of us
(ie, more than zero), could we trouble you to dig into it and
write some docs?

You might find there are some bugs to fix too.  I doubt that code
has seen much use lately :-(

            regards, tom lane

Re: Encoding passwords

From
teg@redhat.com (Trond Eivind Glomsrød)
Date:
Tom Lane <tgl@sss.pgh.pa.us> writes:

> sean-pgsql-general@chittenden.org writes:
> > Are there any good docs on kerberos with postgres?
>
> No.  Since you seem to know more about Kerberos than most of us
> (ie, more than zero), could we trouble you to dig into it and
> write some docs?
>
> You might find there are some bugs to fix too.  I doubt that code
> has seen much use lately :-(

We've been using it a little lately, and it seems to work (we added a
postgres principle, but that was about it) -  one think which would be
nice, though, is multiple authentication methods for the same
database, keyed by user. While you might want to use kerberos for
standard users, you  might like to give an unprivileged one access to
some simple selects, to give one example.

--
Trond Eivind Glomsrød
Red Hat, Inc.

Re: Encoding passwords

From
Nalin Dahyabhai
Date:
On Sat, Sep 29, 2001 at 07:05:19PM -0700, Sean Chittenden wrote:
> For the sake of example, let's say I've got the principle:
> johndoe@REALM.COM.  Do I need to create a principle
> johndoe/postgres@REALM.COM?  If so, what is the keytab that I'd create
> for the postmaster?  postgres/host.example.com@REALM.COM?

You're right about the keytab -- the postmaster needs a key for
"postgres/hostname@REALM" in the keytab file (which it needs to be able
to read -- I often forget that) in order to use Kerberos for
authentication.

Authorization is still handled the same way it would be if you were
using password authentication (i.e., you need to grant privileges to
particular users for particular databases and tables, in your example,
for a user named "johndoe").

HTH,

Nalin

Re: Encoding passwords

From
Sean Chittenden
Date:
> > Another idea is stop storing hashes altogether
>
> You can already avoid passwords by using kerberos authentication.

Are there any good docs on kerberos with postgres?  Unlike almost
everything else in this project, I've found them quite lacking.  My
biggest question would be I've got kerberos setup and working well.  How
do I get postgres to authorize a user.

For the sake of example, let's say I've got the principle:
johndoe@REALM.COM.  Do I need to create a principle
johndoe/postgres@REALM.COM?  If so, what is the keytab that I'd create
for the postmaster?  postgres/host.example.com@REALM.COM?

Thanks.  -sc

--
Sean Chittenden