Hello and happy New Year!

On Sun, Dec 30, 2012 at 09:46:00PM +0100, Tomas Vondra <t...@fuzzy.cz> wrote:
> I'm learning SQLObject - checking if we could use it on our projects, 
> and I got stuck at hashing passwords inside the database.
> 
> Imagine a simple table with info about users:
> 
> CREATE TABLE users (
>      id       INT PRIMARY KEY,
>      login    TEXT NOT NULL UNIQUE,
>      pwdhash  TEXT NOT NULL
> )
> 
> where "pwdhash" is a hashed password. We're using PostgreSQL and we 
> usually handle this inside the database using a pgcrypto module, that 
> provides various hash/crypto functions. An insert into the table then 
> looks like this
> 
>      INSERT INTO users VALUES (1, 'login', crypt('mypassword', 
> gen_salt('bf')))
> 
> which generates a salt, computes the hash and stores that into a single 
> text column (salt+hash). The authentication then looks like this:
> 
>      SELECT id, login FROM users WHERE login = 'login' AND pwdhash = 
> crypt('mypassword', pwdhash)
> 
> which reuses the salt stored in the column.
> 
> I'm investigating if we could do this with SQLObject

   I think it's possible with many lines of code. SQLObject doesn't send
raw values on INSERT/UPDATE -- it calls sqlrepr(value) which in turn
calls value.__sqlrepr__(dbname) if the value has __sqlrepr__ method. So
you have to return a wrapper with __sqlrepr__ method, and it can be
returned from a validator.
   See the following program as a small example:

from formencode import validators

class CryptValue(object):
    def __init__(self, value):
        self.value = value

    def __sqlrepr__(self, db):
        assert db == 'postgres'
        return "crypt('%s')" % self.value

class CryptValidator(validators.Validator):
    def from_python(self, value, state):
        return CryptValue(value)

class SOCryptCol(SOCol):
    def createValidators(self, dataType=None):
        return [CryptValidator()]

    def _sqlType(self):
        return 'TEXT NOT NULL'

class CryptCol(Col):
    baseClass = SOCryptCol

class Test(SQLObject):
    test1 = StringCol()
    test2 = CryptCol()

Test.createTable()

test = Test(test1='1', test2='2')
print test

   It produces the following debugging output:

 1/QueryR  :  CREATE TABLE test (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    test1 TEXT,
    test2 TEXT NOT NULL
)
 2/QueryIns:  INSERT INTO test (test1, test2) VALUES ('1', crypt('2'))

   I hope it'd be helpful as a starting point.

Oleg.
-- 
     Oleg Broytman            http://phdru.name/            p...@phdru.name
           Programmers don't die, they just GOSUB without RETURN.

------------------------------------------------------------------------------
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnmore_123012
_______________________________________________
sqlobject-discuss mailing list
sqlobject-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss

Reply via email to