Search Postgresql Archives

Non-Fun with SSHA Password scheme

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I have been trying to set up pl/pgsql code to generate and evaluate
{SSHA} passwords, with somewhat limited success.

{SSHA} is a password scheme that uses SHA-1 along with salting to ward
off dictionary attacks.  Apparently it's used quite a bit with LDAP.

There does not seem to be a "claimed authoritative" source on it; the
nearest is an OpenLDAP FAQ entry that points to a now-dead Netscape
source; apparently the idea was created by someone in Netscape's LDAP
group.

  http://www.openldap.org/faq/data/cache/347.html

  http://developer.netscape.com/docs/technote/ldap/pass_sha.html  (dead)

 (So instead, see the WayBack Machine...)
  http://web.archive.org/web/20040810221808/http://developer.netscape.com/docs/technote/ldap/pass_sha.html

The OpenLDAP FAQ shows examples in Python, Perl, PHP, and Ruby;
they're not very self-explanatory :-).

A Sun Blog has a very nice algorithmic description:
   http://blogs.sun.com/DirectoryManager/entry/the_ssha_password_storage_scheme

I've been trying to create a pair of functions to encode & decode
them.  I get something *internally* consistent, but that doesn't
consistently evaluate other tools' SSHA passwords rightly.

The "consistent" part is the odd part.

If I take the Python/Ruby implementations in the OpenLDAP FAQ, and
choose a human-readable-text salt value, those values seem to (near as
I can tell with a limited selection set :-)) evaluate successfully in
the function ssha_verify(), below.

If, instead, I allow them to use arbitrary binary salts (e.g. - a
series of randomly chosen bytes), then ssha_verify() is quite sure
they don't match.

I suspect I'm doing something dumb surrounding the string smashing,
but just what is not occurring to me.

--------- Set phasers to Cut Here ----------------------
create or replace function ssha_encode (i_secret text) returns text as $$
declare
	c_salt bytea;
	c_shaed_pw bytea;
begin
	-- 1.  Generate 8 bytes of random data to use as salt
	c_salt := public.digest(now()::text || i_secret || random()::text, 'sha1');
	-- 2+3 Append salt, generate SHA1 digest
	c_shaed_pw := public.digest((i_secret||c_salt), 'sha1');
	-- 4-5 - append salt, and encode in base64
	return '{SSHA}' || pg_catalog.encode(c_shaed_pw || c_salt, 'base64');
end $$ language plpgsql;

create or replace function ssha_verify (i_secret text, i_hash text) returns boolean as $$
declare
	c_decoded bytea;
	c_body text;
	c_chash bytea;
	c_salt bytea;
	c_hash bytea;
begin
	if not (i_hash like '{SSHA}%') then
		raise exception 'ssha_verify(%,%) - hash not of SSHA form!', i_secret, i_hash;
	end if;
	c_body := substr(i_hash, 7);
	c_chash := substr(pg_catalog.decode(c_body, 'base64')::bytea, 1, 20);
	c_salt := substr(pg_catalog.decode(c_body, 'base64')::bytea, 21);
	c_hash := public.digest((i_secret || c_salt), 'sha1');
	if c_hash = c_chash then
		return 't';
	else
		return 'f';
	end if;
end
$$ language plpgsql;
--------- Set phasers to Cut Here ----------------------
-- 
select 'cbbrowne' || '@' || 'linuxfinances.info';
http://cbbrowne.com/info/sap.html
Rules of the  Evil Overlord #22. "No matter how tempted  I am with the
prospect  of unlimited  power, I  will  not consume  any energy  field
bigger than my head. <http://www.eviloverlord.com/>

-- 
Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux