1

I have a postgres 9.1 database that is used by both a django website and a application server.

Currently, I use the old SHA1 authentication in both system, but will upgrade to bcrypt. I have this:

CREATE OR REPLACE FUNCTION random_string(length INTEGER, OUT RETURNS TEXT) 
AS $$
BEGIN
  IF length < 0 THEN
    raise exception 'Given length cannot be less than 0';
  END IF;

  RETURNS = libs.gen_salt('bf', length);
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION encryp_TEXT(_TEXT TEXT, OUT RETURNS TEXT)
AS $$
DECLARE
    hash TEXT := '';
    salt TEXT := '';
BEGIN
    salt := random_string(12);
    hash := libs.crypt(_TEXT,salt);

    RETURNS =  'bcrypt$' || salt || '$' || hash;
END;
$$
LANGUAGE 'plpgsql';

select encryp_TEXT('123');

However, is generating invalid passwords (ie, django can't login with that):

In [9]: from django.contrib.auth.hashers import BCryptPasswordHasher

In [10]: a=BCryptPasswordHasher()

In [19]: p='bcrypt$$2a$12$dCw4N7U1aQbuTVhE8ybV0O$2a$12$dCw4N7U1aQbuTVhE8ybV0OVVeFYgl1EMtBhG.4/PobMWDlih1IGLK'

In [20]: a.verify('123',p)
Out[20]: False

Before, using the SHA1 auth both system work fine, so I wonder what I'm missing...

Before I have this:

-- Genera una cadena aleatoria del tamaño especificado
CREATE OR REPLACE FUNCTION random_string(length INTEGER, OUT RETURNS TEXT) 
AS $$
DECLARE
  chars TEXT[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}';
  result TEXT := '';
  i INTEGER := 0;
BEGIN
  IF length < 0 THEN
    raise exception 'Given length cannot be less than 0';
  END IF;

  FOR i IN 1..length LOOP
    result := result || chars[1+random()*(array_length(chars, 1)-1)];
  END LOOP;

  RETURNS =  result;
END;
$$
LANGUAGE plpgsql;

-- Encripta con SHA1 una cadena y retorna el tipo de algoritmo + salt + hash
CREATE OR REPLACE FUNCTION encryp_TEXT(_TEXT TEXT, OUT RETURNS TEXT)
AS $$
DECLARE
    hash TEXT := '';
    salt TEXT := '';
BEGIN
    salt := random_string(12);
    hash := encode( libs.digest(salt || _TEXT, 'sha1'), 'hex');

    RETURNS =  'sha1$' || salt || '$' || hash;
END;
$$
LANGUAGE 'plpgsql';

Looking at the source of django and checking this, I modify the salt generation. However, even if I use the same code the check will fail anyway (with a ValueError: Invalid salt), so I don't know if the problem is in the salt or the encrypt

P.D: I will be equally happy with reimplement PBKDF2 or using a custom hasher, if necesary

3
  • "Invalid salt" means something that uses it as input doesn't like it .. wrong type? incorrect value? (That is, what are the values, and what does the documentation say is required?) Commented Oct 4, 2012 at 21:51
  • Yes, I understand that. Is only to show that the previous implementation was not compatible... Commented Oct 4, 2012 at 22:37
  • This is a bad idea from a security perspective. Plaintext passwords should be passed around as little as possible. It'd be better to do the hashing in django as early as possible and then discard the plaintext password. When you send the plaintext password to the database, you have worry about securing the database connection (you should worry about this anyways), making sure that passwords don't show up in query logs, etc, etc. Best to avoid the additional risk. Commented Jun 1, 2014 at 15:56

1 Answer 1

1

Well, finally I do it. I check the generated string by postgres and django and found that the ones with postgres duplicate the salt. So was a simple change to:

-- Encripta con bcrypto una cadena y retorna el tipo de algoritmo + salt + hash, django compatible
CREATE OR REPLACE FUNCTION encryp_text(_TEXT TEXT, OUT RETURNS TEXT)
AS $$
DECLARE
    hash TEXT := '';
    salt TEXT := '';
BEGIN
    salt := random_string(12);
    hash := libs.crypt(_TEXT,salt);

    RETURNS =  'bcrypt$' || hash;
END;
$$
LANGUAGE 'plpgsql';
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.